October 2015 Blog Posts

新手学python-笨方法学python-ex15-读取文件

LC 2015-10-31 Python

跟着笨方法学python个教程学习,边学边做习题边记录。

新手学python-笨方法学python-ex15-读取文件 - 学习记录
上一小节的加分题3想不出来argv和raw_input怎么结合使用,就分开使用了。刚好这一小节学到,真好。

本小节学习内容:
你已经学过了 raw_input 和 argv,这些是你开始学习读取文件的必备基础。你可能需要多多实验才能明白它的工作原理,所以你要细心做练习,并且仔细检查结果。处理文件需要非常仔细,如果不仔细的话,你可能会吧有用的文件弄坏或者清空。导致前功尽弃。

这节练习涉及到写两个文件。一个正常的 ex15.py 文件,另外一个是 ex15_sample.txt,第二个文件并不是脚本,而是供你的脚本读取的文本文件。以下是后者的内容:

This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.

我们要做的是把该文件用我们的脚本“打开(open)”,然后打印出来。然而把文件名ex15_sample.txt 写死(hardcode)在代码中不是一个好主意,这些信息应该是用户输入的才对。如果我们碰到其他文件要处理,写死的文件名就会给你带来麻烦了。我们的解决方案是使用 argv 和 raw_input 来从用户获取信息,从而知道哪些文件该被处理。

from sys import argv

script, filename = argv

txt = open(filename)

print "Here's your file %r:" % filename
print txt.read()

print "Type the filename again:"
file_again = raw_input("> ")

txt_again = open(file_again)

print txt_again.read()

 

这个脚本中有一些新奇的玩意,我们来快速地过一遍:

代码的 1-3 行使用 argv 来获取文件名,这个你应该已经熟悉了。接下来第 5 行我们看到 open 这个新命令。现在请在命令行运行 pydoc open 来读读它的说明。你可以看到它和你自己的脚本、或者 raw_input 命令类似,它会接受一个参数,并且返回一个值,你可以将这个值赋予一个变量。这就是你打开文件的过程。

第 7 行我们打印了一小行,但在第 8 行我们看到了新奇的东西。我们在 txt 上调用了一个函数。你从 open 获得的东西是一个 file (文件),文件本身也支持一些命令。它接受命令的方式是使用句点 . (英文称作 dot 或者 period),紧跟着你的命令,然后是类似 open 和 raw_input 一样的参数。不同点是:当你说 txt.read 时,你的意思其实是:“嘿 txt!执行你的 read 命令,无需任何参数!”

脚本剩下的部分基本差不多,不过我就把剩下的分析作为加分习题留给你自己了。

你应该看到的结果:

我的脚本叫 “ex15_sample.txt”,以下是执行结果:

$ python ex15.py ex15_sample.txt 
Here's your file 'ex15_sample.txt':
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.


Type the filename again:
> ex15_sample.txt
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.


$

 

加分习题
这节的难度跨越有点大,所以你要尽量做好这节加分习题,然后再继续后面的章节。

1.在每一行的上面用注解说明这一行的用途。
ex15-1.py

form sys import argv #import argument varible from function sys

script, filename = argv #argument variable,include the prameters you transfer to python

txt = open(filename) #define txt as open(filename)

print "Here's your file %r:" % filename #print something
print txt.read() # print the txt's contents

print "Type the filename again:" # print someting
file_again = raw_input("> ") #define file_again,set it as the you type in

txt_again = open(file_again) # set txt_again as open(file_again)

print txt_again.read() # print the txt_again's content

 

2.如果你不确定答案,就问别人,或者上网搜索。大部分时候,只要搜索 “python” 加上你要搜的东西就能得到你要的答案。比如搜索一下“python open”。

3.我使用了“命令”这个词,不过实际上它们的名字是“函数(function)”和“方法(method)。上网搜索一下这两者的意义和区别。看不明白也没关系,迷失在别的程序员的知识海洋里是很正常的一件事情。

4.删掉 10-15 行使用到 raw_input 的部分,再运行一遍脚本。
ex15-4.py

from sys import argv

script, filename = argv

txt = open(filename)

print "Here's your file %r:" % filename
print txt.read()

运行该程序:

$python ex15-4.py ex15-sample.txt
Here's your file 'ex15-sample.txt':
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.

$

5.只是用 raw_input 写这个脚本,想想哪种种得到文件名称的方法更好,以及为什么。
ex15-5.py

filename = raw_input("Please input your file name:")
txt = open(filename)
print txt.read()

执行该脚本,可以打印脚本本身:

$python ex15-5.py
Please input your file name:ex15-5.py
filename = raw_input("Please input your file name:")
txt = open(filename)
print txt.read()

$


raw_input好,有提示。

6.运行 pydoc file 向下滚动直到看见 read() 命令(函数/方法)。看到很多别的命令了吧,你可以找几条试试看。不需要看那些包含 __ (两个下划线)的命令,这些只是垃圾而已。
ex15-6.py

filename = raw_input("Pls input your file name:")
txt = open(filename)
print txt.tell()
print txt.readline()

执行该脚本:

$python ex15-6.py
Pls input your file name:ex15-6.py
0
filename = raw_input("Pls input your file name:")


$


7.再次运行 python 在命令行下使用 open 打开一个文件,这种 open 和 read 的方法也值得你一学。

>>> filename = "ex15-sample.txt"
>>> txt = open(filename)
>>> print txt.read()
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
>>>

 或者

>>> txt = open("ex15-sample.txt")
>>> print txt.read()
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
>>>

8.让你的脚本针对 txt and txt_again 变量执行一下 close() ,处理完文件后你需要将其关闭,这是很重要的一点。
ex15-8.py

from sys import argv

script, filename = argv

txt = open(filename)

print txt.read()

txt.close()

print "Pls input your filename again:"
file_again = raw_input(">")

txt_again = open(file_again)

print txt_again.read()

txt_again.close()

 

运行该程序:

$python ex15-8.py ex15-sample.txt
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
Pls input your filename again:
>ex15-sample.txt
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.

$

 

 

 

至此,笨方法学python-ex15-读取文件这一小节的学习结束了。

新手学python-笨方法学python-ex14-提示和传递

LC 2015-10-30 Python

跟着个教程学习,边学边做习题边记录。

新手学python-笨方法学python-ex14-提示和传递 - 学习记录
上一小节的加分题3想不出来argv和raw_input怎么结合使用,就分开使用了。刚好这一小节学到,真好。

本小节学习内容:

让我们使用argv和raw_input一起来向用户提一些特别的问题。下一节习题你会学习如何读写文件,这节练习是下节的基础。
这道练习题里我们将略微不同的方法使用raw_input,让它打出一个简单的>作为提示符。这和一些游戏中的方式类似,例如Zork或者Adventure这两款游戏。

from sys import argv

script, user_name = argv
prompt = '>'

print "Hi %s,I'm the %s script." %(user_name, script)
print "I'd like to ask you a few questions."
print "Do you like me %s?" % user_name
likes = raw_input(prompt)

print "Where do you live %s?" % user_name
lives = raw_input(prompt)

print "What kind of computer do you have?"
computer = raw_input(prompt)

print """
Alright, so you said %r about liking me.
You live in %r. Not sure where that is.
And you have a %r computer. Nice.
""" %(likes, lives, computer)

 

我们将用户提示符设置为变量 prompt,这样我们就不需要在每次用到raw_input的时候重复输入提示用户的字符了。而且如果你要将提示符修改成别的字串,你只需要修改一个位置就可以了。

非常顺手吧。

执行这个脚本,我们将看到结果:


$python ex14.py Zed
Hi Zed,I'm the ex14.py script.
I'd like to ask you a few questions.
Do you like me Zed?
>yes
Where do you live Zed?
>America
What kind of computer do you have?
>Tandy

Alright, so you said 'yes' about liking me.
You live in 'America'. Not sure where that is.
And you have a 'Tandy' computer. Nice.


$


加分习题
1.查一下 Zork 和 Adventure 是两个怎样的游戏。 看看能不能下载到一版,然后玩玩看。
Zork I是电子游戏历史上最早的一款文字冒险游戏,是Colossal Cave Adventure的一个早期后继。

2.将 prompt 变量改成完全不同的内容再运行一遍。
ex14-2.py

from sys import argv

script, user_name = argv

prompt = "Pls input>"

print "Hi %s,I'm the %s script." %(user_name, script)
print "I'd like to ask you a few questions."
print "Do you like me %s?" % user_name
likes = raw_input(prompt)

print "Where do you live %s?" % user_name
lives = raw_input(prompt)

print "What kind of computer do you have?"
computer = raw_input(prompt)

print """
Alright, so you said %r about liking me.
You live in %r. Not sure where that is.
And you have a %r computer. Nice.
""" %(likes, lives, computer)

运行该脚本:

$python ex14-2.py Zed
Hi Zed,I'm the ex14-2.py script.
I'd like to ask you a few questions.
Do you like me Zed?
Pls input>yes
Where do you live Zed?
Pls input>us
What kind of computer do you have?
Pls input>Mac

Alright, so you said 'yes' about liking me.
You live in 'us'. Not sure where that is.
And you have a 'Mac' computer. Nice.


$

3.给你的脚本再添加一个参数,让你的程序用到这个参数。

ex14-3.py

from sys import argv

script, user_name, age = argv
prompt = '>'

print "Hi %s,I'm the %s script." %(user_name, script)
print "I'd like to ask you a few questions."
print "How old are you? %s." % age
print "Do you like me %s?" % user_name
likes = raw_input(prompt)

print "Where do you live %s?" % user_name
lives = raw_input(prompt)

print "What kind of computer do you have?"
computer = raw_input(prompt)

print """
Alright, so you said %r about liking me.
You live in %r. Not sure where that is.
And you have a %r computer. Nice.
""" %(likes, lives, computer)

运行该脚本

 

$python ex14-3.py Zed 25
Hi Zed,I'm the ex14-3.py script.
I'd like to ask you a few questions.
How old are you? 25.
Do you like me Zed?
>yes
Where do you live Zed?
>us
What kind of computer do you have?
>Mac

Alright, so you said 'yes' about liking me.
You live in 'us'. Not sure where that is.
And you have a 'Mac' computer. Nice.



$

4.确认你弄懂了三个引号 """ 可以定义多行字符串,而 % 是字符串的格式化工具。

from sys import argv

script, name, age, hight = argv

prompt = 'lc>'

print "Hello %s ,It's a %s script." %(name, script)

print "Which fruit do you like? %s." % name

fruit = raw_input(prompt)

print "It's 7 o'clock,time to get up. Do you want to get up?"

get_up = raw_input(prompt)

print "When did you go to bed last night? %s." %name

time = raw_input(prompt)

print """
So your name is %s and you like %s
you are %s years old and you are %s tall
And you %s want to get up
And you went to bed at %s last night
""" % (name, fruit, age, hight, get_up, time)

 

运行该程序:

 

$python ex14-0.py cc 10 135cm
Hello cc ,It's a ex14-0.py script.
Which fruit do you like? cc.
lc>apple
It's 7 o'clock,time to get up. Do you want to get up?
lc>do not
When did you go to bed last night? cc.
lc>9 o'clock

So your name is cc and you like apple
you are 10 years old and you are 135cm tall
And you do not want to get up
And you went to bed at 9 o'clock last night


$

 

 

至此,笨方法学-ex14-提示和传递这一小节的学习结束了。

新手学python-笨方法学python-ex13-参数、解包和变量

LC 2015-10-29 Python

跟着笨方法学python个教程学习,边学变做习题边记录。

新手学python-笨方法学python-ex13-参数、解包和变量 - 学习记录

本小节学习内容:
在这节练习中,我们将讲到另外一种将变量传递给脚本的方法(所谓脚本,就是你写的.py程序)。
你已经知道,如果要运行ex13.py,只要在命令行运行python ex13.py就可以了。
这句命令中ex13.py部分就是所谓的“参数(argument)”,我们现在要做的就是写一个可以接受参数的脚本。
将下面的程序写下来,后面你将看到详细解释。

from sys import argv

script, first, second, third = argv

print "The script is called:", script
print "Your first variable is:", first
print "Your second variable is:", second
print "Your third variable is:", third

在第一行我们有一个“import”语句。这是你将python的功能引入你的脚本的方法。
不会一下子将它所有的功能给你,而是让你需要什么就调用什么。
这样可以让你的程序保持精简,而后面的程序员看到你的代码的时候,这些“import”可以作为提示,让他们明白你的代码用到了哪些功能。

argv是所谓的“参数变量(argument variable)”,是一个非常标准的变成术语。在其他的编程语言里你也可以看到它。
这个变量包含了你传递给Python的参数。通过后面的练习你将对它有更多的了解。

第3行讲argv“解包(unpack)”,与其将所有的参数放到同一个变量下面,我们将每个参数赋予一个变量名:script,first,second,以及third。
这样看上去有些奇怪,不过“解包”可能是最好的描述方式了。它的含义很简单:“把argv中的东西解包,将所有的参数一次赋予左边的变量名”。

等一下!“功能”还有另外一个名字

前面我们使用import让你的程序实现更多的功能,但实际上没人把import称为“功能”。我希望你可以在没接触到正式术语的时候就弄懂它的功能。
在继续下去之前,你需要知道它们真正的名称:模组(modules)。

从现在开始我们将把这些我们导入(import)进来的功能称作模组。你将看到类似这样的说法:“你需要把sys模组import进来。”也有人将它们称作“库(libraries)”,不过我们还是叫它们模组吧。


跟着课程学习:

输入不同的参数运行上面的脚本试试看结果:

$python ex13.py
Traceback (most recent call last):
  File "ex13.py", line 3, in <module>
    script, first, second, third = argv
ValueError: need more than 1 value to unpack

$
$python ex13.py
Traceback (most recent call last):
  File "ex13.py", line 3, in <module>
    script, first, second, third = argv
ValueError: need more than 1 value to unpack

$python ex13.py 1st
Traceback (most recent call last):
  File "ex13.py", line 3, in <module>
    script, first, second, third = argv
ValueError: need more than 2 values to unpack

$python ex13.py 1st 2nd
Traceback (most recent call last):
  File "ex13.py", line 3, in <module>
    script, first, second, third = argv
ValueError: need more than 3 values to unpack

$python ex13.py 1st 2nd 3rd
The script is called: ex13.py
Your first variable is: 1st
Your second variable is: 2nd
Your third variable is: 3rd

$python ex13.py one two three
The script is called: ex13.py
Your first variable is: one
Your second variable is: two
Your third variable is: three

$python ex13.py cheese apples bread
The script is called: ex13.py
Your first variable is: cheese
Your second variable is: apples
Your third variable is: bread

$

 


1.给你的脚本三个以下的参数。看看会得到什么错误信息。试着解释一下。
由上面的结果可以看到,输入三个一下的参数时,提示ValueError: need more than * value(s) to unpack,需要更多的值来解包。

2.再写两个脚本,其中一个接受更少的参数,另一个接受更多的参数,在参数解包时给它们取一些有意义的变量名。
ex13-2-1.py

from sys import argv

script, name, age, hight, weight = argv

print "What's your name?", name
print "How old are you?", age
print "How tall are you?", hight
print "How much are you weigh?", weight

运行该脚本
python ex13-2-1.py Vera 12 135cm 30kg

$python ex13-2-1.py Vera 12 135cm 30kg
What's your name? Vera
How old are you? 12
How tall are you? 135cm
How much are you weigh? 30kg

$

 

第二个脚本


ex13-2-2.py

from sys import argv

script, fruit, color = argv

print "What's this? \nThis is a %s.\nWhat's the color of it?\nIt's %s." %(fruit, color)

运行该脚本

python ex13-2-2.py apple red
python ex13-2-2.py pear yellow
python ex13-2-2.py orange orange

$python ex13-2-2.py apple red
What's this?
This is a apple.
What's the color of it?
It's red.

$python ex13-2-2.py pear yellow
What's this?
This is a pear.
What's the color of it?
It's yellow.

$python ex13-2-2.py orange orange
What's this?
This is a orange.
What's the color of it?
It's orange.

$

 

3.将 raw_input 和 argv 一起使用,让你的脚本从用户手上得到更多的输入。
ex13-3.py 这个不大会用,先这样分开用着吧

from sys import argv
script, first, second, third = argv
fourth = raw_input("Pls input the 4th variable: ")
fifth = raw_input("Pls input the 5th variable: ")
sixth = raw_input("Pls input the 6th variable: ")
print "The argv including these three variables: %s, %s and %s." %(first, second, third)
print "Thanks for inputting these three variables: %s, %s and %s." %(fourth, fifth, sixth)

执行该脚本

$python ex13-3.py 11 22 33
Pls input the 4th variable: 4
Pls input the 5th variable: 5
Pls input the 6th variable: 6
The argv including these three variables: 11, 22 and 33.
Thanks for inputting these three variables: 4, 5 and 6.

$

 


4.记住“模组(modules)”为你提供额外功能。多读几遍把这个词记住,因为我们后面还会用到它。

 

至此,-ex13-参数、解包和变量这一小节的学习结束了。

新手学python-笨方法学python-ex12-提示别人

LC 2015-10-28 Python

跟着笨方法学python个教程学习,边学边做习题边记录。

新手学-笨方法学python-ex12-提示别人 - 学习记录

课程内容:
当你键入 raw_input() 的时候,你需要键入 ( 和 ) 也就是“括号(parenthesis)”。这和你格式化输出两个以上变量时的情况有点类似,比如说 "%s %s" % (x, y) 里边就有括号。对于 raw_input 而言,你还可以让它显示出一个提示,从而告诉别人应该输入什么东西。你可以在 () 之间放入一个你想要作为提示的字符串,如下所示:

y = raw_input("Name? ")
这句话会用 “Name?” 提示用户,然后将用户输入的结果赋值给变量 y。这就是我们提问用户并且得到答案的方式。

也就是说,我们的上一个练习可以使用 raw_input 重写一次。所有的提示都可以通过 raw_input 实现。

跟着课程练习:

[root@lc test]# vi ex12.py 

age = raw_input("How old are you? ")
height = raw_input("How tall are you? ")
weight = raw_input("How much do you weigh? ")

print "So, you're %r old, %r tall and %r heavy." % (age, height, weight)
"ex12.py" 5L, 198C written
[root@lc test]# 

执行该脚本:

[root@lc test]# python ex12.py 
How old are you? 35
How tall are you? 6'2" 
How much do you weigh? 180lbs
So, you're '35' old, '6\'2"' tall and '180lbs' heavy.
[root@lc test]# 

加分习题
1.在命令行界面下运行你的程序,然后在命令行输入 pydoc raw_input 看它说了些什么。如果你用的是 Window,那就试一下 python -m pydoc raw_input 。
[root@lc test]# python -m pydoc raw_input
Help on built-in function raw_input in module __builtin__:

raw_input(...)
    raw_input([prompt]) -> string
   
    Read a string from standard input.  The trailing newline is stripped.
    If the user hits EOF (Unix: Ctl-D, Windows: Ctl-Z+Return), raise EOFError.
    On Unix, GNU readline is used if enabled.  The prompt string, if given,
    is printed without a trailing newline before reading.
(END)

2.输入 q 退出 pydoc。
[root@lc test]# python -m pydoc raw_input
Help on built-in function raw_input in module __builtin__:

raw_input(...)
    raw_input([prompt]) -> string
   
    Read a string from standard input.  The trailing newline is stripped.
    If the user hits EOF (Unix: Ctl-D, Windows: Ctl-Z+Return), raise EOFError.
    On Unix, GNU readline is used if enabled.  The prompt string, if given,
    is printed without a trailing newline before reading.

[root@lc test]#

3.上网找一下 pydoc 命令是用来做什么的。
[root@lc test]# python -m pydoc
pydoc - the Python documentation tool

pydoc.py <name> ...
    Show text documentation on something.  <name> may be the name of a
    Python keyword, topic, function, module, or package, or a dotted
    reference to a class or function within a module or module in a
    package.  If <name> contains a '/', it is used as the path to a
    Python source file to document. If name is 'keywords', 'topics',
    or 'modules', a listing of these things is displayed.

pydoc.py -k <keyword>
    Search for a keyword in the synopsis lines of all available modules.

pydoc.py -p <port>
    Start an HTTP server on the given port on the local machine.

pydoc.py -g
    Pop up a graphical interface for finding and serving documentation.

pydoc.py -w <name> ...
    Write out the HTML documentation for a module to a file in the current
    directory.  If <name> contains a '/', it is treated as a filename; if
    it names a directory, documentation is written for all the contents.

[root@lc test]# python -m pydoc -p 8888
然后使用http://localhost:8888可以看到所有模块说明的文档


4.使用 pydoc 再看一下 open, file, os, 和 sys 的含义。看不懂没关系,只要通读一下,记下你觉得有意思的点就行了。

python -m pydoc open
python -m pydoc file
python -m pydoc os
python -m pydoc sys

至此,-ex12-提示别人这一小节的学习结束了。

新手学python-笨方法学python-ex11-提问

LC 2015-10-28 Python

跟着笨方法学python个教程学习,边学边做习题边记录。

新手学python--ex11-提问 - 学习记录

课程内容:
我已经出过很多打印相关的练习,让你习惯写简单的东西,但简单的东西都有点无聊,现在该跟上脚步了。我们现在要做的是把数据读到你的程序里边去。这可能对你有点难度,你可能一下子不明白,不过你需要相信我,无论如何把习题做了再说。只要做几个练习你就明白了。

一般软件做的事情主要就是下面几条:

1.接受人的输入。
2.改变输入。
3.打印出改变了的输入。
到目前为止你只做了打印,但还不会接受或者修改人的输入。你也许还不知道“输入(input)”是什么意思。所以闲话少说,我们还是开始做点练习看你能不能明白。下一个习题里边我们会给你更多的解释。

跟着课程练习:

[root@lc test]# vi ex11.py     

print "How old are you?",
age = raw_input()
print "How tall are you?",
height = raw_input()
print "How much do you weigh?",
weight = raw_input()

print "So, you're %r old, %r tall and %r heavy." %(age, height, weight)
"ex11.py" 8L, 218C written
[root@lc test]# 

执行该程序:

[root@lc test]# python ex11.py 
How old are you? 35
How tall are you? 6'2"
How much do you weigh? 180lbs
So, you're '35' old, '6\'2"' tall and '180lbs' heavy.
[root@lc test]# 


加分习题
1.上网查一下 的 raw_input 实现的是什么功能。
使用input和raw_input都可以读取控制台的输入,但是input和raw_input在处理数字时是有区别的
当输入为纯数字时:
input返回的是数值类型,如int,float
raw_inpout返回的是字符串类型,string类型
输入字符串为表达式
input会计算在字符串中的数字表达式,而raw_input不会。
如输入“57 + 3”:
input会得到整数60
raw_input会得到字符串”57 + 3”

2.你能找到它的别的用法吗?测试一下你上网搜索到的例子。
print "Hello, ",name = raw_input()

3.用类似的格式再写一段,把问题改成你自己的问题。

[root@lc test]# vi ex11-3.py        

print "What's the color of apple?",
apple_color = raw_input()
print "What's the color of orange?",
orange_color = raw_input()
print "What's the color of pear?",
pear_color = raw_input()

print "So the apple is %s, the orange is %s and the pear is %s." %(apple_color, orange_color, pear_color)
"ex11-3.py" 8L, 293C written
[root@lc test]# 

 

执行该程序:

[root@lc test]# python ex11-3.py 
What's the color of apple? red
What's the color of orange? orange
What's the color of pear? yellow
So the apple is red, the orange is orange and the pear is yellow.
[root@lc test]# 


4.和转义序列有关的,想想为什么最后一行 '6\'2"' 里边有一个 \' 序列。单引号需要被转义,从而防止它被识别为字符串的结尾。有没有注意到这一点
如果写成'6'2"'程序就看不懂了。


至此,笨方法学python-ex11-提问这一小节的学习结束了。

新手学python-笨方法学python-ex10-what's that

LC 2015-10-28 Python

跟着笨方法学python个教程学习,边学边做习题边记录。

新手学python-笨方法学python-ex10-what's that - 学习记录

课程内容:

在习题 9 中我你接触了一些新东西。我让你看到两种让字符串扩展到多行的方法。第一种方法是在月份之间用 \n (back-slash n )隔开。这两个字符的作用是在该位置上放入一个“新行(new line)”字符。

使用反斜杠 \ (back-slash) 可以将难打印出来的字符放到字符串。针对不同的符号有很多这样的所谓“转义序列(escape sequences)”,但有一个特殊的转义序列,就是 双反斜杠(double back-slash) \\ 。这两个字符组合会打印出一个反斜杠来。接下来我们做几个练习,然后你就知道这些转义序列的意义了。

另外一种重要的转义序列是用来将单引号 ' 和双引号 " 转义。想象你有一个用双引号引用起来的字符串,你想要在字符串的内容里再添加一组双引号进去,比如你想说"I "understand" joe.",Python 就会认为 "understand" 前后的两个引号是字符串的边界,从而把字符串弄错。你需要一种方法告诉 python 字符串里边的双引号不是真正的双引号。

要解决这个问题,你需要将双引号和单引号转义,让 Python 将引号也包含到字符串里边去。这里有一个例子:

"I am 6'2\" tall."  # 将字符串中的双引号转义
'I am 6\'2" tall.'  # 将字符串种的单引号转义

第二种方法是使用“三引号(triple-quotes)”,也就是 """,你可以在一组三引号之间放入任意多行的文字。接下来你将看到用法。

跟着课程练习:

[root@lc test]# vi ex10.py 

tabby_cat = "\tI'm tabbed in."
persian_cat = "I'm split\non a line."
backslash_cat = "I'm \\ a \\ cat."

fat_cat = """
I'll do a list:
\t* Cat food
\t* Fishies
\t* Catnip\n\t* Grass
"""

print tabby_cat
print persian_cat
print backslash_cat
print fat_cat
"ex10.py" 15L, 255C written
[root@lc test]# 

 

执行该程序得到以下结果:

[root@lc test]# python ex10.py 
        I'm tabbed in.
I'm split
on a line.
I'm \ a \ cat.

I'll do a list:
        * Cat food
        * Fishies
        * Catnip
        * Grass

[root@lc test]# 

 

加分练习:
1.上网搜索一下还有哪些可用的转义字符。
的转义字符及其含义

    符    号     说     明
      \'   单引号
      \"   双引号
      \a   发出系统响铃声
      \b   退格符
      \n   换行符
      \t   横向制表符
      \v   纵向制表符
      \r   回车符
      \f   换页符
      \o   八进制数代表的字符
      \x   十六进制数代表的字符
      \000   终止符,\000后的字符串全部忽略
   如果在字符串中输出"\",需使用"\\"

2.使用 ''' (三个单引号)取代三个双引号,看看效果是不是一样的?
试了一下,结果是一样的。

[root@lc test]# vi ex10-2.py 

tabby_cat = "\tI'm tabbed in."
persian_cat = "I'm split\non a line."
backslash_cat = "I'm \\ a \\ cat."

fat_cat = '''
I'll do a list:
\t* Cat food
\t* Fishies
\t* Catnip\n\t* Grass
'''

print tabby_cat
print persian_cat
print backslash_cat
print fat_cat
"ex10-2.py" 15L, 255C written
[root@lc test]# 

 

运行该程序:

[root@lc test]# python ex10-2.py 
        I'm tabbed in.
I'm split
on a line.
I'm \ a \ cat.

I'll do a list:
        * Cat food
        * Fishies
        * Catnip
        * Grass

[root@lc test]# 


3.将转义序列和格式化字符串放到一起,创建一种更复杂的格式。
 格式化字符串的替代符以及含义
    符   号     说     明
      %c  格式化字符及其ASCII码
      %s  格式化字符串
      %d  格式化整数
      %u  格式化无符号整型
      %o  格式化无符号八进制数
      %x  格式化无符号十六进制数
      %X  格式化无符号十六进制数(大写)
      %f  格式化浮点数字,可指定小数点后的精度
      %e  用科学计数法格式化浮点数
      %E  作用同%e,用科学计数法格式化浮点数
      %g  根据值的大小决定使用%f活%e
      %G  作用同%g,根据值的大小决定使用%f活%e
      %p  用十六进制数格式化变量的地址
   
    试试看:
   

>>> print 'what\'s this: %s' % 'this is a word'
what's this: this is a word
>>> print 'what\'s this: %s' % 'this is a "word"'
what's this: this is a "word"
>>> print 'what\'s this? %s' % '\nthis is a "word"' 
what's this? 
this is a "word"
>>> print 'what\'s this? %s' % '\nthis is \ta tab '         
what's this? 
this is         a tab 
>>> 

 

4.记得 %r 格式化字符串吗?使用 %r 搭配单引号和双引号转义字符打印一些字符串出来。 将 %r 和 %s 比较一下。 注意到了吗?%r 打印出来的是你写在脚本里的内容,而 %s 打印的是你应该看到的内容。

>>> print 'what\'s this: %s' % 'this is a word'
what's this: this is a word
>>> print 'what\'s this: %s' % 'this is a "word"'
what's this: this is a "word"
>>> print 'what\'s this: %r' % 'this is a word'   
what's this: 'this is a word'
>>> print 'what\'s this: %r' % 'this is a "word"' 
what's this: 'this is a "word"'
>>> 


至此,笨方法学-ex10-what's that这一小节的学习结束了。

新手学python-笨方法学python-ex9-打印打印打印

LC 2015-10-28 Python

跟着个教程学习,边学边做习题边记录。

新手学python-笨方法学python-ex9-打印打印打印 - 学习记录

跟着课程练习:

[root@lc test]# vi ex9.py 

# Here's some new strange stuff, remember bype it exactly.

days = "Mon Tue Wed The Fri Sat Sun"
months = "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug"

print "Here are the days: ", days
print "Here are the months: ", months

print """
There's something going on here.
With the three double-quotes.
We'll be able to type as much as we like.
Even 4 lines if we want, or 5, or 6.
"""
"ex9.py" 14L, 377C written
[root@lc test]# 


执行该程序

[root@lc test]# python ex9.py 
Here are the days:  Mon Tue Wed The Fri Sat Sun
Here are the months:  Jan
Feb
Mar
Apr
May
Jun
Jul
Aug

There's something going on here.
With the three double-quotes.
We'll be able to type as much as we like.
Even 4 lines if we want, or 5, or 6.

[root@lc test]# 


Three double-quotes可以打印多行,\n是换行。

至此,笨方法学-ex9-打印打印打印这一小节的学习结束了。

新手学python-笨方法学python-ex8-打印打印

LC 2015-10-28 Python

跟着笨方法学python个教程学习,边学边做习题边记录。

新手学python-笨方法学python-ex8-打印打印 - 学习记录

跟着课程练习:


[root@lc test]# vi ex8.py 

formatter = "%r %r %r %r"

print formatter % (1, 2, 3, 4)
print formatter % ("one", "two", "three", "four")
print formatter % (True, False, False, True)
print formatter % (formatter, formatter, formatter, formatter)
print formatter % (
    "I had this thing.",
    "That you could type up right.",
    "But it didn't sing.",
    "So I said goodnight."
)
"ex8.py" 12L, 354C written
[root@lc test]# 

 

执行该程序:

[root@lc test]# python ex8.py 
1 2 3 4
'one' 'two' 'three' 'four'
True False False True
'%r %r %r %r' '%r %r %r %r' '%r %r %r %r' '%r %r %r %r'
'I had this thing.' 'That you could type up right.' "But it didn't sing." 'So I said goodnight.'
[root@lc test]# 


加分习题:注意最后一行程序中既有单引号又有双引号,你觉得它是如何工作的?
我觉得是默认打印单引号,但是因为第三句里面有个didn't单词自带有',所以第三句使用双引号。
以此类推,如果打印的字符串里面含有双引号,那么打印出来的语句也是单引号。
为了验证自己的想法,修改程序试试看结果:

 

[root@lc test]# vi ex8-2.py     

formatter = "%r %r %r %r"

print formatter % (1, 2, 3, 4)
print formatter % ("one", "two", "three", "four")
print formatter % (True, False, False, True)
print formatter % (formatter, formatter, formatter, formatter)
print formatter % (
    "I had this thing.",
    "That you'd type up right.", # modify to debug
    "But it did not sing.", # modify to debug
    'So I said "goodnight."' # modify to debug
)
"ex8-2.py" 12L, 408C written
[root@lc test]# 

 

执行该程序:

[root@lc test]# python ex8-2.py 
1 2 3 4
'one' 'two' 'three' 'four'
True False False True
'%r %r %r %r' '%r %r %r %r' '%r %r %r %r' '%r %r %r %r'
'I had this thing.' "That you'd type up right." 'But it did not sing.' 'So I said "goodnight."'
[root@lc test]# 

 

看这次执行的结果和上次的比较,验证了自己的想法。

至此,-ex8-打印打印这一小节的学习结束了。

新手学python-笨方法学python-ex7-更多打印

LC 2015-10-28 Python

跟着个教程学习,边学边做习题边记录。

新手学python-笨方法学python-ex7-更多打印 - 学习记录

跟着课程练习:

[root@lc test]# vi ex7.py 

print "Mary had a little lamb."
print "Its fleece was white as %s." % 'snow'
print "And everywhere that Mary went."
print "." * 10 # what'd that do?

end1 = "C"
end2 = "h"
end3 = "e"
end4 = "e"
end5 = "s"
end6 = "e"
end7 = "B"
end8 = "u"
end9 = "r"
end10 = "g"
end11 = "e"
end12 = "r"

# watch that comma at the end. try removing it to see what happens
print end1 + end2 + end3 + end4 + end5 + end6,
print end7 + end8 + end9 + end10 + end11 + end12
"ex7.py" 21L, 449C written
[root@lc test]# 

运行该程序:

[root@lc test]# python ex7.py 
Mary had a little lamb.
Its fleece was white as snow.
And everywhere that Mary went.
..........
Cheese Burger
[root@lc test]# 

 

根据提示去掉print里面end6后面的comma逗号看看发生了什么

[root@lc test]# vi ex7-0.py 

print "Mary had a little lamb."
print "Its fleece was white as %s." % 'snow'
print "And everywhere that Mary went."
print "." * 10 # what'd that do?

end1 = "C"
end2 = "h"
end3 = "e"
end4 = "e"
end5 = "s"
end6 = "e"
end7 = "B"
end8 = "u"
end9 = "r"
end10 = "g"
end11 = "e"
end12 = "r"

# watch that comma at the end. try removing it to see what happens
print end1 + end2 + end3 + end4 + end5 + end6
print end7 + end8 + end9 + end10 + end11 + end12
"ex7-0.py" 21L, 448C written
[root@lc test]# 

 

运行该程序

[root@lc test]# python ex7-0.py 
Mary had a little lamb.
Its fleece was white as snow.
And everywhere that Mary went.
..........
Cheese
Burger
[root@lc test]# 

有逗号的时候,两个print打印在同一行,中间隔了一个空格;
去掉逗号之后,两个print分别打印了一行。


加分练习,从后往前添加注释:


[root@lc test]# vi ex7-1.py 

#print string "Mary had a little lamb."
print "Mary had a little lamb."
#print string "Its fleece was white as %s." where %s is snow
print "Its fleece was white as %s." % 'snow'
#print string "And everywhere that Mary went."
print "And everywhere that Mary went."
#repeat "." 10 times
print "." * 10 # what'd that do?

#define variable end1~end12
end1 = "C"
end2 = "h"
end3 = "e"
end4 = "e"
end5 = "s"
end6 = "e"
end7 = "B"
end8 = "u"
end9 = "r"
end10 = "g"
end11 = "e"
end12 = "r"

# watch that comma at the end. try removing it to see what happens
#print variable end1~end6's value and then a space
print end1 + end2 + end3 + end4 + end5 + end6,
#print variable end7~end12's value
print end7 + end8 + end9 + end10 + end11 + end12
"ex7-1.py" 28L, 732C written
[root@lc test]# 

 

运行该程序:

[root@lc test]# python ex7-1.py 
Mary had a little lamb.
Its fleece was white as snow.
And everywhere that Mary went.
..........
Cheese Burger
[root@lc test]# 


至此,这一小节的学习结束了。

新手学python-笨方法学python-ex6-字符串(string)和文本

LC 2015-10-28 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

跟着个教程学习,边学变做习题边记录。

新手学python-笨方法学python-ex6-字符串(string)和文本 - 学习记录

本小节学习内容:
虽然你已经在程序中写过字符串了,你还没学过它们的用处。在这章习题中我们将使用复杂的字符串来建立一系列的变量,从中你将学到它们的用途。首先我们解释一下字符串是什么 东西。

字符串通常是指你想要展示给别人的、或者是你想要从程序里“导出”的一小段字符。Python 可以通过文本里的双引号 " 或者单引号 ' 识别出字符串来。这在你以前的 print 练习中你已经见过很多次了。如果你把单引号或者双引号括起来的文本放到 print 后面,它们就会被 python 打印出来。

字符串可以包含格式化字符 %s,这个你之前也见过的。你只要将格式化的变量放到字符串中,再紧跟着一个百分号 % (percent),再紧跟着变量名即可。唯一要注意的地方,是如果你想要在字符串中通过格式化字符放入多个变量的时候,你需要将变量放到 ( ) 圆括号(parenthesis)中,而且变量之间用 , 逗号(comma)隔开。就像你逛商店说“我要买牛奶、面包、鸡蛋、八宝粥”一样,只不过程序员说的是”(milk, eggs, bread, soup)”。

我们将键入大量的字符串、变量、和格式化字符,并且将它们打印出来。我们还将练习使用简写的变量名。程序员喜欢使用恼人的难度的简写来节约打字时间,所以我们现在就提早学会这个,这样你就能读懂并且写出这些东西了。

跟着课程学习:

[root@lc test]# vi ex6.py 
x = "There are %d types of people." % 10
binary = "binary"
do_not = "don't"
y = "Those who know %s and those who %s." % (binary, do_not)

print x
print y

print "I said: %r." % x
print "I said: '%s'." % y

hilarious = False
joke_evaluation = "Isn't that joke so funny?! %r"

print joke_evaluation % hilarious

w = "This is the left side of..."
e = "a string with a right side."

print w + e
"ex6.py" 21L, 392C written
[root@lc test]# 

 

执行该程序:

[root@lc test]# python ex6.py 
There are 10 types of people.
Those who know binary and those who don't.
I said: 'There are 10 types of people.'.
I said: 'Those who know binary and those who don't.'.
Isn't that joke so funny?! False
This is the left side of...a string with a right side.
[root@lc test]# 

加分习题:
1.通读程序,在每一行的上面写一行注解,给自己解释一下这一行的作用。

[root@lc test]# vi ex6-1.py 

#define x as "There are %d types of peole." where the %d is 10
x = "There are %d types of people." % 10
#define binary as binary
binary = "binary"
#define do_not as don't
do_not = "don't"
#define y as "Those who know %s and those who %s." where the 1st %s is the content of variable binary and the 2nd %s is the content 
variable do_not
y = "Those who know %s and those who %s." % (binary, do_not)
#print x
print x
#print y
print y
#print "I said: %r." where the %r is all the content the variable x has,include all""
print "I said: %r." % x
#print "I said: '%s'." where the %s is the content of the variable y
print "I said: '%s'." % y
#define hilarious as False
hilarious = False
#define joke_evaluation as "Isn't that joke so funny?! %r"
joke_evaluation = "Isn't that joke so funny?! %r"
#print Isn't that joke so funny?! %r where %r is the content of variable hilariour
print joke_evaluation % hilarious
#define w as a string
w = "This is the left side of..."
#define e as a string
e = "a string with a right side."
#print string a and string b
print w + e    
"ex6-1.py" 29L, 1061C written
[root@lc test]# 

 

执行该程序:

[root@lc test]# python ex6-1.py 
There are 10 types of people.
Those who know binary and those who don't.
I said: 'There are 10 types of people.'.
I said: 'Those who know binary and those who don't.'.
Isn't that joke so funny?! False
This is the left side of...a string with a right side.
[root@lc test]# 


2.找到所有的”字符串包含字符串”的位置,总共有四个位置。
1)y = "Those who know %s and those who %s." % (binary, do_not) - 这里有两个
2)print "I said: %r." % x 这里第三个
3)print "I said: '%s'." % y 这里第四个
4)print joke_evaluation % hilarious 这里第五个

3.你确定只有四个位置吗?你怎么知道的?没准我在骗你呢。
找出来5个

4.解释一下为什么 w 和 e 用 + 连起来就可以生成一个更长的字符串。
的print + 可以连接字符串, *数字可以循环重复字符串,例如:

>>> a = "test "
>>> b = "this is for test"
>>> print a + b
test this is for test
>>> print a *3
test test test 
>>> print b * 4
this is for testthis is for testthis is for testthis is for test
>>> print a * 3 + b * 4
test test test this is for testthis is for testthis is for testthis is for test
>>> 


至此,这一小节的学习结束了。

 

新手学python-笨方法学python-ex5-更多的变量和打印

LC 2015-10-28 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

跟着笨方法学python个教程学习,边学变做习题边记录。

笨方法学英语-ex5-更多的变量和打印 - 学习记录
教程说明:
我们现在要键入更多的变量并且把它们打印出来。这次我们将使用一个叫“格式化字符串(format string)”的东西. 每一次你使用 " 把一些文本引用起来,你就建立了一个字符串。 字符串是程序将信息展示给人的方式。你可以打印它们,可以将它们写入文件,还可以将它们发送给网站服务器,很多事情都是通过字符串交流实现的。

字符串是非常好用的东西,所以再这个练习中你将学会如何创建包含变量内容的字符串。使用专门的格式和语法把变量的内容放到字符串里,相当于来告诉 :“嘿,这是一个格式化字符串,把这些变量放到那几个位置。”

跟着练习:

[root@lc test]# vi ex5.py 

my_name = 'Zed A. Shaw'
my_age = 35 # not a lie
my_height = 74 # inches
my_weight = 180 # lbs
my_eyes = 'Blue'
my_teeth = 'White'
my_hair = 'Brown'

print "Let's talk about %s." % my_name
print "He's %d inches tall." % my_height
print "He's %d pounds heavy." % my_weight
print "Actually that's not too heavy."
print "He's got %s eyes and %s hair." %(my_eyes, my_hair)
print "His teeth are usually %s depending on the coffee." % my_teeth

# this line is tricky,try to get it exactly right
print "If I add %d, %d, and %d I get %d." % (my_age, my_height, my_weight, my_age + my_height + my_weight)
"ex5.py" 17L, 595C written
[root@lc test]# 

运行该程序:

[root@lc test]# python ex5.py 
Let's talk about Zed A. Shaw.
He's 74 inches tall.
He's 180 pounds heavy.
Actually that's not too heavy.
He's got Blue eyes and Brown hair.
His teeth are usually White depending on the coffee.
If I add 35, 74, and 180 I get 289.
[root@lc test]# 

 

加分习题
1.修改所有的变量名字,把它们前面的``my_``去掉。确认将每一个地方的都改掉,不只是你使用``=``赋值过的地方。

[root@lc test]# vi ex5-1.py 
name = 'Zed A. Shaw'
age = 35 # not a lie
height = 74 # inches
weight = 180 # lbs
eyes = 'Blue'
teeth = 'White'
hair = 'Brown'

print "Let's talk about %s." % name
print "He's %d inches tall." % height
print "He's %d pounds heavy." % weight
print "Actually that's not too heavy."
print "He's got %s eyes and %s hair." %(eyes, hair)
print "His teeth are usually %s depending on the coffee." % teeth

# this line is tricky,try to get it exactly right
print "If I add %d, %d, and %d I get %d." % (age, height, weight, age + height + weight)
"ex5-1.py" 17L, 538C written
[root@lc test]# 

 

运行该程序:

2.试着使用更多的格式化字符。例如 %r 就是是非常有用的一个,它的含义是“不管什么都打印出来”。


[root@lc test]# vi ex5-2.py     

words = 'Hello, World!'

print "The 1st test %s." % words
print "The 2nd test %r." % words
[root@lc test]#

 

运行该程序:
 

3.在网上搜索所有的 Python 格式化字符。

格式符为真实值预留位置,并控制显示的格式。格式符可以包含有一个类型码,用以控制显示的类型,如下:

%s    字符串 (采用str()的显示)
%r    字符串 (采用repr()的显示)
%c    单个字符
%b    二进制整数
%d    十进制整数
%i    十进制整数
%o    八进制整数
%x    十六进制整数
%e    指数 (基底写为e)
%E    指数 (基底写为E)
%f    浮点数
%F    浮点数,与上相同
%g    指数(e)或浮点数 (根据显示长度)
%G    指数(E)或浮点数 (根据显示长度)
%%    字符"%"

可以用如下的方式,对格式进行进一步的控制:
%[(name)][flags][width].[precision]typecode
(name)为命名
flags可以有+,-,' '或0。+表示右对齐。-表示左对齐。' '为一个空格,表示在正数的左侧填充一个空格,从而与负数对齐。0表示使用0填充。
width表示显示宽度
precision表示小数点后精度


比如:

print("%+10x" % 10)
print("%04d" % 5)
print("%6.3f" % 2.3)

上面的width, precision为两个整数。我们可以利用*,来动态代入这两个量。比如:
print("%.*f" % (4, 1.2))
Python实际上用4来替换*。所以实际的模板为"%.4f"。

总结

Python中内置的%操作符可用于格式化字符串操作,控制字符串的呈现格式。Python中还有其他的格式化字符串的方式,但%操作符的使用是最方便的。

4.试着使用变量将英寸和磅转换成厘米和千克。不要直接键入答案。使用 Python 的计算功能来完成。

[root@lc test]# vi ex5-4.py  
my_name = 'Zed A. Shaw'
my_age = 35 # not a lie
my_height = 74 # inches
my_weight = 180 # lbs
my_eyes = 'Blue'
my_teeth = 'White'
my_hair = 'Brown'

print "Let's talk about %s." % my_name
print "He's %d inches tall." % my_height
print "He's %d cm tall." % my_height * 2.54
print "He's %d pounds heavy." % my_weight
print "He's %d kg heavy." % my_weight * 0.4535924
print "Actually that's not too heavy."
print "He's got %s eyes and %s hair." %(my_eyes, my_hair)
print "His teeth are usually %s depending on the coffee." % my_teeth

# this line is tricky,try to get it exactly right
print "If I add %d, %d, and %d I get %d." % (my_age, my_height, my_weight, my_age + my_height + my_weight)
"ex5-4.py" 19L, 689C written
[root@lc test]# 

运行该程序:

 

[root@lc test]# python ex5-4.py 
Let's talk about Zed A. Shaw.
He's 74 inches tall.
Traceback (most recent call last):
  File "ex5-4.py", line 11, in <module>
    print "He's %d cm tall." % my_height * 2.54
TypeError: can't multiply sequence by non-int of type 'float'
[root@lc test]#


返回错误,修改如下:


[root@lc test]# vi ex5-4.py     

my_name = 'Zed A. Shaw'
my_age = 35 # not a lie
my_height = 74 # inches
my_weight = 180 # lbs
my_eyes = 'Blue'
my_teeth = 'White'
my_hair = 'Brown'

print "Let's talk about %s." % my_name
print "He's %d inches tall." % my_height
print "He's %d cm tall." % (my_height * 2.54)
print "He's %d pounds heavy." % my_weight
print "He's %d kg heavy." % (my_weight * 0.4535924)
print "Actually that's not too heavy."
print "He's got %s eyes and %s hair." %(my_eyes, my_hair)
print "His teeth are usually %s depending on the coffee." % my_teeth

# this line is tricky,try to get it exactly right
print "If I add %d, %d, and %d I get %d." % (my_age, my_height, my_weight, my_age + my_height + my_weight)
"ex5-4.py" 19L, 693C written
[root@lc test]#

 

再次运行

[root@lc test]# python ex5-4.py 
Let's talk about Zed A. Shaw.
He's 74 inches tall.
He's 187 cm tall.
He's 180 pounds heavy.
He's 81 kg heavy.
Actually that's not too heavy.
He's got Blue eyes and Brown hair.
His teeth are usually White depending on the coffee.
If I add 35, 74, and 180 I get 289.
[root@lc test]# 

 

成功

至此,这一小节的学习结束了。

 

[root@lc test]# python ex5-2.py 
The 1st test Hello, World!.
The 2nd test 'Hello, World!'.
[root@lc test]# 

 

[root@lc test]# python ex5-1.py 
Let's talk about Zed A. Shaw.
He's 74 inches tall.
He's 180 pounds heavy.
Actually that's not too heavy.
He's got Blue eyes and Brown hair.
His teeth are usually White depending on the coffee.
If I add 35, 74, and 180 I get 289.
[root@lc test]# 

新手学python-笨方法学python-ex4-变量variable和命名

LC 2015-10-27 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

跟着笨方法学python个教程学习,边学变做习题边记录。

笨方法学英语-ex4-变量(variable)和命名 - 学习记录

跟着练习:

[root@lc test]# vi ex4.py 
cars = 100
space_in_a_cat = 4.0
drivers = 30
passengers = 90
cars_not_driven = cars - drivers
cars_driven = drivers
carpool_capacity = cars_driven * space_in_a_car
average_passengers_per_car = passengers / cars_driven

print "There are", cars, "cars available."
print "There are only", drivers, "drivers available."
print "There will be", cars_not_driven, "empty cars today."
print "We can transport", carpool_capacity, "people today."
print "We have", passengers, "to carpool today."
print "We need to put about", average_passengers_per_car, "in each car."
"ex4.py" 15L, 558C written
[root@lc test]#

运行该程序:

[root@lc test]# python ex4.py 
Traceback (most recent call last):
  File "ex4.py", line 7, in <module>
    carpool_capacity = cars_driven * space_in_a_car
NameError: name 'space_in_a_car' is not defined
[root@lc test]#

 

啊?!又出错了! 提示第七行的name 'space_in_a_car' is not defined,没有定义space_in_a_car。心想,不对啊,前面定义了。
回到原来的文件里面找,原来是写错了单词,space_in_a_car 写成了space_in_a_cat。
将space_in_a_cat 改成 space_in_a_car,再次运行该程序,得到结果:

[root@lc test]# python ex4.py 
There are 100 cars available.
There are only 30 drivers available.
There will be 70 empty cars today.
We can transport 120.0 people today.
We have 90 to carpool today.
We need to put about 3 in each car.
[root@lc test]# 


更多的加分习题:

1.我在程序里用了 4.0 作为 space_in_a_car 的值,这样做有必要吗?如果只用 4 会有什么问题?
个人觉得没有必要,改成4试了一下,没有发现什么问题。

[root@lc test]# vi ex4-1.py 

cars = 100
space_in_a_car = 4
drivers = 30
passengers = 90
cars_not_driven = cars - drivers
cars_driven = drivers
carpool_capacity = cars_driven * space_in_a_car
average_passengers_per_car = passengers / cars_driven

print "There are", cars, "cars available."
print "There are only", drivers, "drivers available."
print "There will be", cars_not_driven, "empty cars today."
print "We can transport", carpool_capacity, "people today."
print "We have", passengers, "to carpool today."
print "We need to put about", average_passengers_per_car, "in each car." 
"ex4-1.py" 15L, 556C written
[root@lc test]# 

 

运行该程序,得到结果:

[root@lc test]# python ex4-1.py 
There are 100 cars available.
There are only 30 drivers available.
There will be 70 empty cars today.
We can transport 120 people today.
We have 90 to carpool today.
We need to put about 3 in each car.
[root@lc test]# 

2.记住 4.0 是一个“浮点数”,自己研究一下这是什么意思。

3.在每一个变量赋值的上一行加上一行注解。

[root@lc test]# vi ex4-3.py 

#define space_in_a_car as 4.0
#define cars as 100
cars = 100
#define space_in_a_car as 4.0
space_in_a_car = 4.0
#define drivers as 30
drivers = 30
#define passengers as 90
passengers = 90
#define cars_not_driven as cars - drivers,the result is 100 - 30 = 70
cars_not_driven = cars - drivers
#define cars_driven as as drivers ,the result is 30
cars_driven = drivers
#define carpool_capacity as cars_driven * space_in_a_car,the result is 30 * 4.0 = 120.0
carpool_capacity = cars_driven * space_in_a_car
#define average_passengers_per_car as passengers / cars_driven,the result is 90 / 30 = 3
average_passengers_per_car = passengers / cars_driven

print "There are", cars, "cars available."
print "There are only", drivers, "drivers available."
print "There will be", cars_not_driven, "empty cars today."
print "We can transport", carpool_capacity, "people today."
print "We have", passengers, "to carpool today."
print "We need to put about", average_passengers_per_car, "in each car."
"ex4-3.py" 23L, 954C written
[root@lc test]# 

 

4.记住 = 的名字是等于(equal),它的作用是为东西取名。

5.记住 _ 是下划线字符(underscore)。

6.将 python 作为计算器运行起来,就跟以前一样,不过这一次在计算过程中使用变量名来做计算,常见的变量名有 i, x, j 等等。

[root@lc test]# vi ex4-6.py 

i = 10
j = 100
k = i + j

print "i =", i
print "j =", j
print "k =", k
print "i + j =", i + j
print "j - i =", j - i
print "i * j =", i * j
"ex4-6.py" 11L, 141C written
[root@lc test]# 

 

运行该程序:

[root@lc test]# python ex4-6.py 
i = 10
j = 100
k = 110
i + j = 110
j - i = 90
i * j = 1000
[root@lc test]# 

 

至此,这一小节的学习结束了。

 

新手学python-笨方法学Python-ex3-数字和数字运算

LC 2015-10-27 Python

写给某人:有一位同学天天在我耳边念叨语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

跟着笨方法学python个教程学习,边学变做习题边记录。

笨方法学英语-ex3-数字和数字运算 - 学习记录


数学运算符号:
+ plus 加号
- minus 减号
/ slash 斜杠
* asterisk 星号
% percent 百分号
< less-than 小于号
> greater-than 大于号
<= less-than-equal 小于等于号
>= greater-than-equal 大于等于号

照着教程输入:

[root@lc test]# vi ex3.py 

print "I will now count my chickens:"

print "Hens", 25 + 30 / 6
print "Roosters", 100 - 25 * 3 % 4

print "Now I will count the eggs:"

print 3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6

print "Is it true that 3 + 2 < 5 - 7?"

print 3 + 2 < 5 - 7

print "What is 3 + 2?", 3 + 2
print "What is 5 - 7?" 5 - 7

print "Oh, that's why it's False."

print "How about some more."

print "Is it greater?", 5 > -2
print "Is it greater or equal?",5 >= -2
print "Is it less or equal?", 5 <= -2
"ex3.py" 23L, 474C written
[root@lc test]# 

 

然后执行这个脚本:

[root@lc test]# python ex3.py 
  File "ex3.py", line 15
    print "What is 5 - 7?" 5 - 7
                           ^
SyntaxError: invalid syntax
[root@lc test]# 

啊?!出错了,看看错误原因,提示第15行 print "What is 5 - 7?" 5 - 7 引号外的5附近有语法错误;
仔细对照自己敲的内容和原教程的内容,发现少了一个逗号,加上逗号:

[root@lc test]# vi ex3.py     

print "I will now count my chickens:"

print "Hens", 25 + 30 / 6
print "Roosters", 100 - 25 * 3 % 4

print "Now I will count the eggs:"

print 3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6

print "Is it true that 3 + 2 < 5 - 7?"

print 3 + 2 < 5 - 7

print "What is 3 + 2?", 3 + 2
print "What is 5 - 7?", 5 - 7

print "Oh, that's why it's False."

print "How about some more."
"ex3.py" 23L, 475C written
[root@lc test]# 

执行该代码,成功:

[root@lc test]# python ex3.py 
I will now count my chickens:
Hens 30
Roosters 97
Now I will count the eggs:
7
Is it true that 3 + 2 < 5 - 7?
False
What is 3 + 2? 5
What is 5 - 7? -2
Oh, that's why it's False.
How about some more.
Is it greater? True
Is it greater or equal? True
Is it less or equal? False
[root@lc test]# 

 

加分习题:
1.使用 # 在代码每一行的前一行为自己写一个注解,说明一下这一行的作用。

[root@lc test]# vi ex3-1.py 

#This will print "I will now count my chickens:"
print "I will now count my chickens:"
#This will print Hens and a space and the result of "25 + 30 / 6 = 25 + 5 = 30"
print "Hens", 25 + 30 / 6
#This will print Roosters and a space and the result of " 100 - 25 * 3 % 4 = 100 - 75 % 4 = 100 - 3 = 97"
print "Roosters", 100 - 25 * 3 % 4
#This will print "Now I will count the eggs:"
print "Now I will count the eggs:"
#This will print the result of "3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6 = 6 - 5 + 0 - 0 + 6 = 7"
print 3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
#This will print " Is thar true 3 + 2 < 5 - 7?"
print "Is it true that 3 + 2 < 5 - 7?"
#This is print the result of 3 + 2 < 5 - 7
print 3 + 2 < 5 - 7
#This will print "What is 3 + 2?" and a space and the result of "3 + 2 = 5"
print "What is 3 + 2?", 3 + 2
#This will print "What is 5 - 7?" and a space and the result of "5 - 7 = -2"
print "What is 5 - 7?", 5 - 7
#This is print "Oh, that's why it's False."
print "Oh, that's why it's False."
#This will print "How about some more."
print "How about some more."
#This will print "Is it greater?" and a space and the excute result of "5 > -2 : True"
print "Is it greater?", 5 > -2
#This will print "Is it greater or equal?" and a space and the excute result of "5 >= -2 : True"
print "Is it greater or equal?",5 >= -2
#This will print "Is it less or equal?" and a space and the excute resultl of "5 <= -2 :False"
print "Is it less or equal?", 5 <= -2
"ex3-1.py" 28L, 1446C written
[root@lc test]#

 

2.记得开始时的 <练习 0> 吧?用里边的方法把 Python 运行起来,然后使用刚才学到的运算符号,把Python当做计算器玩玩。

>>> 3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
7
>>> 100 - 25 * 3 % 4
97
>>> 3.0 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
7.0
>>> 3.0 + 2 + 1 - 5 + 4 % 2 - 1.0 / 4 + 6
6.75
>>>

 

3.自己找个想要计算的东西,写一个 .py 文件把它计算出来。

[root@lc test]# vi ex2-3.py 
print "1 + 2 =",1 + 2
"ex2-3.py" 1L, 22C written
[root@lc test]# python ex2-3.py 
1 + 2 = 3
[root@lc test]# 

 

4.有没有发现计算结果是”错”的呢?计算结果只有整数,没有小数部分。研究一下这是为什么,搜索一下“浮点数(floating point number)”是什么东西。
浮点数是属于有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学计数法。

5.使用浮点数重写一遍 ex3.py,让它的计算结果更准确(提示: 20.0 是一个浮点数)。

[root@lc test]# vi ex3-5.py 

print "I will now count my chickens:"

print "Hens", 25.0 + 30.0 / 6
print "Roosters", 100.0 - 25.0 * 3.0 % 4

print "Now I will count the eggs:"

print 3.0 + 2.0 + 1.0 - 5.0 + 4.0 % 2 - 1.0 / 4 + 6

print "Is it true that 3 + 2 < 5 - 7?"

print 3 + 2 < 5 - 7

print "What is 3 + 2?", 3 + 2
print "What is 5 - 7?", 5 - 7

print "Oh, that's why it's False."

print "How about some more."

print "Is it greater?", 5 > -2
print "Is it greater or equal?",5 >= -2
print "Is it less or equal?", 5 <= -2                                                                                                                                  
"ex3-5.py" 23L, 497C written

 

执行该代码:

[root@lc test]# python ex3-5.py 
I will now count my chickens:
Hens 30.0
Roosters 97.0
Now I will count the eggs:
6.75
Is it true that 3 + 2 < 5 - 7?
False
What is 3 + 2? 5
What is 5 - 7? -2
Oh, that's why it's False.
How about some more.
Is it greater? True
Is it greater or equal? True
Is it less or equal? False
[root@lc test]# 

 

这一小节学习结束。注意到print中逗号的使用方法。

新手学python-笨方法学python-ex2-注释和#号

LC 2015-10-27 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

跟着笨方法学python个教程学习,边学变做习题边记录。

笨方法学英语-ex2-注释和#号 - 学习记录

[root@lc test]# vi ex2.py 

# A comment, this is so you can read your program later.
# Anything after the # is ignored by python.

print "I could have code like this." # and the comment after is ignored

# You can also use a comment to "disable" or comment out a piece od code:
# print "This won't run."

print "This will run." 
"ex2.py" 9L, 300C written
[root@lc test]# 


执行该程序,得到以下结果:

[root@lc test]# python ex2.py 
I could have code like this.
This will run.
[root@lc test]# 


弄清楚”#”符号的作用。而且记住它的名字。(中文为井号,英文为 octothorpe 或者 pound character)。

新手学python-笨方法学python-ex1

LC 2015-10-27 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

借口就不再找了,总之过完双休之后,昨天礼拜一没有坚持学习,今天继续。找到个学习的教程,笨方法学,打算跟着这个教程学习,边学变做习题边记录。

笨方法学英语-ex1 - 学习记录

[root@lc test]# vi ex1.py     

print "Hello World!"
print "Hello Again"
print "I like typing this."
print "This is fun."
print 'Yay! Printing.'
print "I'd much rather you 'not'."
print 'I "said" do not touch this.'                                    
"ex1.py" 7L, 184C written
[root@lc test]# 


执行该代码,输入python ex1.py:

[root@lc test]# python ex1.py
Hello World!
Hello Again
I like typing this.
This is fun.
Yay! Printing.
I'd much rather you 'not'.
I "said" do not touch this.
[root@lc test]# 


习题:
1.让你的脚本再多打印一行。

[root@lc test]# vi ex1-1.py 

print "Hello World!"
print "Hello Again"
print "I like typing this."
print "This is fun."
print 'Yay! Printing.'
print "I'd much rather you 'not'."
print 'I "said" do not touch this.'
print "Let your script print one more line."                                        
"ex1-1.py" 8L, 229C written
[root@lc test]# python ex1-1.py 
Hello World!
Hello Again
I like typing this.
This is fun.
Yay! Printing.
I'd much rather you 'not'.
I "said" do not touch this.
Let your script print one more line.
[root@lc test]# 

 

2.让你的脚本只打印一行。

[root@lc test]# vi ex1-2.py 

print "Let your script print only one line."
                                                                                                                                
"ex1-2.py" 1L, 45C written
[root@lc test]# python ex1-2.py 
Let your script print only one line.
[root@lc test]# 


3.在一行的起始位置放一个 ‘#’ (octothorpe) 符号。它的作用是什么?自己研究一下。

[root@lc test]# vi ex1-3.py 

print "Hello World!"
#print "Hello Again"
print "I like typing this."
#print "This is fun."
print 'Yay! Printing.'
print "I'd much rather you 'not'."
print 'I "said" do not touch this.'
#print "Let your script print one more line."
"ex1-3.py" 8L, 232C written
[root@lc test]# python ex1-3.py 
Hello World!
I like typing this.
Yay! Printing.
I'd much rather you 'not'.
I "said" do not touch this.
[root@lc test]# 

由练习结果可得知:
1.print打印字符串时使用英文的单引号''或者双引号“”,如果本身打印内容里面有单引号则用print" ",如果打印内容本身含有双引号则用print''。
2.‘#’ (octothorpe) 符号的作用是注释。后面的内容不执行。

新手学python-输入-raw_input

LC 2015-10-23 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

 

上次学习了python的输入,当时用的是input(),输入的时候比较多的问题。

还有一个内建函数raw_input(),通过读取控制台的输入与用户实现交互,跟input()有些区别。

>>> input_A = input("Please input: ")
Please input: 123
>>> type(input_A)
<type 'int'>
>>> raw_input_A = raw_input("Please input: ")
Please input: 123
>>> type(raw_input_A)
<type 'str'>
>>> 


raw_input() 将所有输入作为字符串看待,返回字符串类型。而 input() 在对待纯数字输入时具有自己的特性,它返回所输入的数字的类型( int, float );

非对 input() 有特别需要,否则一般情况下推荐使用 raw_input() 来与用户交互。

学到这里,玩一下第一个Hello,World程序:

>>> name = raw_input("Please input your name: ")
Please input your name: World
>>> print "Hello,",name
Hello, World
>>> 

 

 

 

新手学python-输入-Input

LC 2015-10-23 Python

新手学python-输入-Input


写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

前一次学习的print,或者直接在交互式命令行下直接输入代码接着执行并直接得到结果,这些都是程序在向屏幕“输出”。
现在,已经可以用print输出想要的结果了。但是,如果要让用户从电脑输入一些字符怎么办呢?
对的,这个问题提的很好,有“输出”,就得有“输入”,我们必须有向程序“输入”信息,才能和程序对话,进行所谓的“人机交互”。

提供了一个接受命令行下输入的方法:input(),可以让用户输入字符串,并存放到一个变量里。
注意,input()和print不同的地方在于,input()必须加上括号,而且必须是英文符号的括号()。
比如我们输入一个用户的年纪:

输入age = input()并按下回车后,Python交互式命令行就在等待你的输入了。这时,你可以输入任意字符,然后按回车后完成输入。

 

 

输入完成后,不会有任何提示,Python交互式命令行又回到>>>状态了。那我们刚才输入的内容到哪去了?
答案是存放到age变量里了。可以直接输入age查看变量内容:

>>> age
12

要打印出name变量的内容,除了直接写age然后按回车外,还可以用print函数:

>>> print age
12
>>> 

 

使用 input 的话,当输入的时候,如果不是数字的话,必须要加引号,否则会报错。
例如:

>>> name = input()
LC
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'LC' is not defined
>>> name = input()
'LC'
>>> name
'LC'
>>> print name
LC
>>> 


新手学python-输出-Print

LC 2015-10-22 Python

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

前一次学了如何启动和退出python的交互式环境,今天将学习python的输出-Print。

世界上第一个程序就是Hello World,由Brian Kernighan创作。

所以,我这里也不免俗,学习Python,从Hello World做起。

 

首先,进入Python的交互式环境。

如果要让Python打印出指定的文字,可以用print函数:

>>> print 'Hello,World!'
Hello,World!
>>> print "Hello,World!"
Hello,World!
>>> 

print除了打印字符串以外,还可以输出各种数字、运算结果、比较结果等等。

>>> print 1
1
>>> print 1+2
3
>>> print 1>2
False
>>> print 2>1
True
>>> 

 

交互式命令行下,还可以直接输入代码,然后执行,并立刻得到结果。

>>> 1
1
>>> 1+2
3
>>> 1>2
False
>>> 2>1
True

 输入单行直接用print"",如果需要输入多行,需要使用""" """:

>>> print """ This is 1st line
... This is 2nd line
... This is 3rd line
... Thie is the last line"""
 This is 1st line
This is 2nd line
This is 3rd line
Thie is the last line
>>> 

print语句也可以跟上多个字符串,用逗号“,”隔开,就可以连成一串输出:

>>> print 'I know', 'how to', 'output one line'
I know how to output one line
>>> 

print会依次打印每个字符串,遇到逗号“,”会输出一个空格

那如果我们要打印1+1=2这个算式的话,就按照如下操作: 

>>> print ' 1 + 1 = ',1+1
 1 + 1 =  2
>>> 

 

注意,对于1 + 1,Python解释器自动计算出结果2,但是,'1 + 1 ='是字符串而非数学公式,Python把它视为字符串。 

到这里,输出学习告一个段落。下次我将学习python的输入-input

新手学python-启动和退出Python交互式环境

LC 2015-10-21 Python

新手学python-启动和退出Python交互式环境

写给某人:有一位同学天天在我耳边念叨Python语言如何如何好(请恕我词穷不知如何复述那个如何如何到底是有多如何如何),所以下定决心要从头开始学习Python了。写代码一直是我的软肋,希望这次能坚持学习,边学边记。

初学代码首先要安装程序,之前写过一篇如何在CentOS下升级Python的文章,我的环境从2.4升级到2.7了,升级完成后,就可以开始使用python环境了。其他操作系统下的安装暂时没有研究,网上搜索有很多教程。

我自己这次学习,首先是启动和退出的交互式环境。以ContOS为例,在命令行中输入python,然后按下回车。结果如下:

[root@lc ~]# python
Python 2.7.2 (default, Mar 18 2014, 13:15:24)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>  

看到提示符>>>就表示我已经在Python交互式环境中了。

接着想退出该交互式环境,习惯性敲了 exit ,然后按下回车:

[root@lc ~]# python
Python 2.7.2 (default, Mar 18 2014, 13:15:24) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit
>>> 

还在交互式环境中,且有提示,用 exit() 或者 Ctrl-D (i.e. EOF) 来退出。

接着敲 exit() 然后按下回车,退出成功。

[root@lc ~]# python
Python 2.7.2 (default, Mar 18 2014, 13:15:24)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit
>>>
>>> exit()
[root@lc ~]#

 

然后试了另外一种方式退出,先启动,然后按Ctrl-D,退出成功。

[root@lc ~]# python
Python 2.7.2 (default, Mar 18 2014, 13:15:24)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
[root@ ~]#

至此,启动和退出的交互式环境算是学完了。

 

下一次将学习Python的输出-Print

初识awk-获取当前机器的global ipv6地址

LC 2015-10-19 IPv6 Networking

获取当前机器的global ipv6地址

使用方法
awk 'pattern {action}' {filenames}

首先,用ifconfig命令可以查看当前机器的所有ip地址
[root@lc ~]# ifconfig
eth0      Link encap:Ethernet  HWaddr 38:83:45:F1:33:33
          inet addr:192.168.1.13  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fc00:0:190::13/64 Scope:Global
          inet6 addr: fe80::3a83:45ff:fef1:3333/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3097 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3404 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:380337 (371.4 KiB)  TX bytes:400481 (391.0 KiB)
          Interrupt:10 Base address:0xe000


eth1      Link encap:Ethernet  HWaddr 50:E5:49:CF:97:BE 
          inet addr:192.168.106.239  Bcast:192.168.106.255  Mask:255.255.255.0
          inet6 addr: fc00:0:190::221/64 Scope:Global
          inet6 addr: fe80::52e5:49ff:fecf:97be/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:74167 errors:0 dropped:0 overruns:0 frame:0
          TX packets:25655 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:8107031 (7.7 MiB)  TX bytes:25823486 (24.6 MiB)
          Interrupt:97

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:13416 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13416 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:6212889 (5.9 MiB)  TX bytes:6212889 (5.9 MiB)

[root@lc ~]#

然后,用awk搜索Global所在的行:
[root@lc ~]# ifconfig | awk -F: '/Global/'
          inet6 addr: fc00:0:190::13/64 Scope:Global
          inet6 addr: fc00:0:190::221/64 Scope:Global
[root@lc ~]#

接着以"addr:"或者"/64"为分隔符,打印第二列:

$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。
[root@lc ~]# ifconfig |awk -F: '/Global/'| awk -F'addr:|/64' '{print $2}'
  fc00:0:190::13
  fc00:0:190::221
[root@lc ~]#

成功!!

VoIP全面详解(转)

LC 2015-10-18 Networking

VoIP全面详解

  一、定义
  VoIP即Voice Over IP,是把话音或传真转换成数据,然后与数据一起共享同一个IP网络(Internet互联网)。
  由于话音和传真在Internet上免费搭乘了"顺风车",所以点对点(网关---网关)国际或国内长途通讯是完全免费的。
IP网络可以是Internet、IPLC(国际专线)、无线网络等,只要是采用IP协议( Internet Protocol ) 就[被屏蔽广告]可以了。VoIP系统就是把传统的电话网与互联网组合搭配在一起。

  二、基本原理及其应用
1995年以色列VocalTec公司所推出的Internet Phone,不但是VoIP网络电话的开端,也揭开了电信IP化的序幕。人们从此不但可以享受到更便宜、甚至完全免费的通话及多媒体增值服务,电信业的服务内容及面貌也为之剧变。
2.1 实现形式
  一开始的网络电话是以软件的形式呈现,同时仅限于PC to PC间的通话,换句话说,人们只要分别在两端不同的PC上,安装网络电话软件,即可经由IP网络进行对话。随着宽频普及与相关网络技术的演进,网络电话也由单纯PC to PC的通话形式,发展出IP to PSTN(公共开关电话网络)、PSTN to IP、PSTN to PSTN及IP to IP等各种形式,当然他们的共通点,就是以IP网络为传输媒介,如此一来,电信业长久以PSTN电路交换网网络为传输媒介的惯例及独占性也逐渐被打破。

  2..2VoIP的原理、架构及要求
  由Voice over IP的字面意义,可以直译为透过IP网络传输的语音讯号或影像讯号,所以就是一种可以在IP网络上互传模拟音讯或视讯的一种技术。简单地说,它是藉由一连串的转码、编码、压缩、打包等程序,好让该语音数据可以在IP网络上传输到目的端,然后再经由相反的程序,还原成原来的语音讯号以供接听者接收。
进一步来说,VoIP大致透过5道程序来互传语音讯号:
(1)语音—数据转换。语音信号是模拟波形,通过IP 方式来传输语音,不管是实时应用业务还是非实时应用业务,首先要对语音信号进行模拟数据转换,也就是对模拟语音信号进行 8位或6位的量化,然后送入到缓冲存储区中,缓冲器的大小可以根据延迟和编码的要求选择。许多低比特率的编码器是采取以帧为单位进行编码。典型帧长为 10~30ms。考虑传输过程中的代价,语音包通常由 60、120或240ms的语音数据组成。数字化可以使用各种语音编码方案来实现,目前采用的语音编码标准主要有 ITU-T G.711。源和目的地的语音编码器必须实现相同的算法,这样目的地的语音设备才可以还原模拟语音信号。
(2)原数据到IP 转换。一旦语音信号进行数字编码,下一步就是对语音包以特定的帧长进行压缩编码。大部份的编码器都有特定的帧长,若一个编码器使用 15ms 的帧,则把每次60ms的语音包分成4帧,并按顺序进行编码。每个帧合120个语音样点(抽样率为8kHz)。编码后,将4个压缩的帧合成一个压缩的语音包送入网络处理器。网络处理器为语音添加包头、时标和其他信息后通过网络传送到另一端点。语音网络简单地建立通信端点之间的物理连接(一条线路),并在端点之间传输编码的信号。IP 网络不像电路交换网络,它不形成连接,它要求把数据放在可变长的数据报或分组中,然后给每个数据报附带寻址和控制信息,并通过网络发送,一站一站地转发到目的地。
(3)传送。在这个通道中,全部网络被看成一个从输入端接收语音包,然后在一定时间t内将其传送到网络输出端。t可以在某个范围内变化,反映了网络传输中的抖动。网络中的每个节点检查每个IP 数据附带的寻址信息,并使用这个信息把该数据报转发到目的地路径上的下一站。网络链路可以是支持 IP 数据流的任何拓扑结构或访问方法。
(4)IP 包—数据的转换。目的地VoIP 设备接收这个 IP 数据并开始处理。网络级提供一个可变长度的缓冲器,用来调节网络产生的抖动。该缓冲器可容纳许多语音包,用户可以选择缓冲器的大小。小的缓冲器产生延迟较小,但不能调节大的抖动。其次,解码器将经编码的语音包解压缩后产生新的语音包,这个模块也可以按帧进行操作,完全和解码器的长度相同。若帧长度为 15ms,60ms 的语音包被分成4 帧,然后它们被解码后还原成60ms的语音数据流送入解码缓冲器。在数据报的处理过程中,去掉寻址和控制信息,保留原始的数据,然后把这个数据提供给解码器。
(5)数字语音转换为模拟语音。播放驱动器将缓冲器中的语音样点(480 个)取出送入声卡,通过扬声器按预定的频率(例如 8kHz)播出。 
在一个基本的VoIP架构之中,大致包含4个基本元素:
  媒体网关器(Media Gateway):主要扮演将语音讯号转换成为IP封包的角色。
  媒体网关控制器(Media Gateway Controller):又称为Gate Keeper或Call Server。主要负责管理讯号传输与转换的工作。
  语音服务器:主要提供电话不通、占线或忙线时的语音响应服务。
  信号网关器(Signaling Gateway):主要工作是在交换过程中进行相关控制,以决定通话建立与否,以及提供相关应用的增值服务。
虽然VoIP拥有许多优点,但绝不可能在短期内完全取代已有悠久历史并发展成熟的PSTN电路交换网,所以现阶段两者势必会共存一段时间。为了要让两者间能相互沟通,势必要建立一个互通的接口及管道,而媒体网关器与网关管理器即扮演了中介的色角,因为他们具备将媒体数据流及IP封包转译成不同网络所支持的各类协议。
其运作原理是,媒体网关器先将语音转换为IP封包,然后交由媒体网关控制器加以控制管理,并决定IP封包在网络中的传送路径。至于信号网关器则负责将SS7信号格式转换为IP封包。
  网络电话若要走向符合企业级营运标准,必须达到以下几个基本要求:
  服务品质(QoS)之保证:这是由PSTN过渡到、IP PBX取代PBX(专用小型交换机)的最基本要求。所谓QoS就是要保证达到语音传输的最低延迟率(400毫秒)及封包遗失率(5-8%),如此通话品质才能达到现今PSTN的基本要求及水准,否则VoIP的推行将成问题。
  99.9999%的高可用性(High Available;HA):虽然网络电话已成今后的必然趋势,但与发展已久的PSTN相较,其成熟度、稳定度、可用性、可管理性,乃至可扩充性等方面,仍有待加强。尤其在电信级的高可用性上,VoIP必须像现今PSTN一样,达到6个9(99.9999%)的基本标准。目前VoIP是以负载平衡、路由备份等技术来解决这方面的要求及问题,总而言之,HA是VoIP必须达到的目标之一。
   开放性及兼容性:传统PSTN是属封闭式架构,但IP网络则属开放式架构,如今VoIP的最大课题之一就是如何在开放架构下,而能达到各家厂商VoIP产品或建设的互通与兼容,同时地造成各家产品在整合测试及验证上的困难度。目前的解决方法是透过国际电信组织不断拟定及修改的标准协议,来达到不同产品间的兼容性问题,以及IP电话与传统电话的互通性。   
  可管理性与安全性问题:电信服务包罗万象,包括用户管理、异地漫游、可靠计费系统、认证授权等等,所以管理上非常复杂,VoIP营运商必须要有良好的管理工具及设备才能因应。同时IP网络架构技术完全不同于过去的PSTN电路网,而且长久以来具开放性的IP网络一直有着极其严重的安全性问题,所以这也形成网络电话今后发展上的重大障碍与首要解决的目标。   
多媒体应用:与传统PSTN相比,网络电话今后发展上的最大特色及区别,恐怕就在多媒体的应用上。在可预见的未来,VoIP将可提供交互式电子商务、呼叫中心、企业传真、多媒体视讯会议、智能代理等应用及服务。过去,VoIP因为价格低廉而受到欢迎及注目,但多媒体应用才是VoIP今后蓬勃发展的最大促因,也是各家积极参与的最大动力。
三、VoIP系统协议
在VoIP 系统中,主要包括提供会话建立的信令协议和提供数据流传输的传输协议两类协议。
  3.1主宰VoIP走向的三大主流信令协议
  在浩瀚的IP网络中要如何正确的寻找到要通话的对方并建立对答,同时也能依照彼此资料的处理能力来传送语音数据,这中间必须藉由国际电信组织所拟定的标准协议才能达到。如今,市面上的网络电话大致都会遵循H.323、MGCP及SIP等3种标准协议。虽然目前产品仍以支持H.323为多,但SIP的支持将会成为今后主流。
  1、H.323
  ITU-T 国际电联第16研究组首先在1996年通过H.323第一版的制定工作,同时并在1998年完成第二版协议的拟定。原则上,该协议提供了基础网络(Packet Based Networks;PBN)架构上的多媒体通讯系统标准,并为IP网络上的多媒体通讯应用提供了技术基础。
  H.323并不依赖于网络结构,而是独立于操作系统和硬件平台之上,支持多点功能、组播和频宽管理。H.323具备相当的灵活性,可支持包含不同功能节点之间的视讯会议和不同网络之间的视讯会议。
  H.323并不支持群播(Multicast)协议,只能采用多点控制单元(MCU)构成多点会议,因而同时只能支持有限的多点用户。H.323也不支持呼叫转移,且建立呼叫的时间也比较长。
  早期的视讯会议多半支持H.323协议,例如微软NetMeeting、Intel Internet Video Phone等都是支持H.323协议的视讯会议软件,亦为现今的前辈。
  不过H.323协议本身具有一些问题,例如采用H.323协议的IP电话网络在接入端仍要经过当地的PSTN电路交换网。而之后制定出的MGCP等协议,目的即在于将H.323网关进行功能上的分解,也就是划分成负责媒体流处理的媒体网关(MG),以及掌控呼叫建立与控制的媒体网关控制器(MGC)两个部分。
 虽然如今微软的Windows Mesenger则已改采SIP标准,且SIP标准隐隐具有取代H.323的势头。但目前仍有许多网络电话产品依旧支持H.323协定。

  2、SIP(Session Initiation Protocol)
  SIP是由IETF所制定,其特性几乎与H.323相反,原则上它是一种比较简单的会话初始化协议,也就是只提供会话或呼叫的建立与控制功能。SIP协议可支持多媒体会议、远程教学及Internet电话等领域的应用。
  SIP同时支持单点播送(Unicast)及群播功能,换句话说,使用者可以随时加入一个已存在的视讯会议之中。在网络OSI属性上,SIP属于应用层协议,所以可透过UDP或TCP协议进行传输。
  SIP另一个重要特点就是它属于一种基于文本的协议,采用SIP规则资源定位语言描述(SIP Uniform Resource Locators),因此可方便地进行撰改或测试作业,所以比起H.323来说,其灵活性与扩展性的表现较好。
  SIP的URL甚至可以嵌入到Web页面或其它超文本连结之中,用户只需用鼠标一点即可发出呼叫。所以与H.323相比,SIP具备了快速建立呼叫快与支持电话号码之传送等特点。

  3、MGCP
  原则上,MGCP协定与前两者皆不同,H.323和SIP协议是专门针对网络电话及IP网络所提出的两套各自独立的标准,两者间并不兼容及互通。反观MGCP协议,则与IP电话网络无关,而只牵涉到网关分解上的问题,也因为如此,该协议可同时适用于支持H.323或SIP协议的网络电话系统。
  MGCP协议制定的主要目的即在于将网关功能分解成负责媒体流处理的媒体网关(MG),以及掌控呼叫建立与控制的媒体网关控制器(MGC)两大部分。同时MG在MGC的控制下,实现跨网域的多媒体电信业务。
  由于MGCP更加适应需要中央控管的通讯服务模式,因此更符合电信营运商的需求。在大规模网络电话网中,集中控管是件非常重要的事情,透过MGCP则可利用MGC统一处理分发不同的服务给MG。

  4、其它重要协议及技术
  除了上述3大协议之外,还有许多左右VoIP通话品质及传输效率的重要协议与技术。在语音压缩编码技术方面,主要有ITU-T定义的G.729、G.723等技术,其中G.729提供了将原有64Kbit/s PSTN模拟语音,压缩到只有8Kbit/s,而同时符合不失真需求的能力。
  在实时传输技术方面,目前网络电话主要支持RTP传输协议。RTP协议是一种能提供端点间语音数据实时传送的一种标准。该协议的主要工作在于提供时间标签和不同数据流同步化控制作业,收话端可以藉由RTP重组发话端的语音数据。除此之外,在网络传输方面,尚包括了TCP、UDP、网关互联、路由选择、网络管理、安全认证及计费等相关技术。 
 

3.2 传输协议
1 RTP  

2、RTSP
四、VOIP的关键技术
  传统的IP网络主要是用来传输数据业务,采用的是尽力而为的、无连接的技术,因此没有服务质量保证,存在分组丢失、失序到达和时延抖动等情况。数据业务对此要求不高,但话音属于实时业务,对时序、时延等有严格的要求。因此必须采取特殊措施来保障一定的业务质量。VOIP的关键技术包括信令技术、编码技术、实时传输技术、服务质量(QOS)保证技术、以及网络传输技术等。
  4.1 信令技术
  信令技术保证电话呼叫的顺利实现和话音质量,目前被广泛接受的VOIP控制信令体系包括ITU-T的H.323系列(华为公司产品采用)和IETF的会话初始化协议SIP。
  ITU的H.323系列建议定义了在无业务质量保证的因特网或其它分组网络上多媒体通信的协议及其规程。H.323标准是局域网、广域网、Intranet和Internet上的多媒体提供技术基础保障。H.323是ITU-T有关多媒体通信的一个协议集,包括用于ISND的H.320,用于B-ISDN的H.321和用于PSTN终端的H.324等建议。其编码机制,协议范围和基本操作类似于ISDN的Q.931信令协议的简化版本,并采用了比较传统的电路交换的方法。相关的协议包括用于控制的H.245,用于建立连接的H.225,用于大型会议的H.332,用于补充业务的H.450.1、H.450.2和H.450.3,有关安全的H.235,与电路交换业务互操作的H.246等。H.323提供设备之间、高层应用之间和提供商之间的互操作性。它不依赖于网络结构,独立于操作系统和硬件平台,支持多点功能、组播和带宽管理。H.323具备相当的灵活性,支持包含不同功能的节点之间的会议和不同网络之间的会议。H.323建议的多媒体会议系统中的信息流包括音频、视频、数据和控制信息。信息流采用H.225建议方式来打包和传送。
  H.323呼叫建立过程涉及到三种信令:RAS(Registration Admission Status)信令,H.225呼叫信令和H.245控制信令。
  RAS信令用来完成终端与网守之间的登记注册、授权许可、带宽改变、状态和脱离解除等过程;
  H.225呼叫信令用来建立两个终端之间的连接,这个信令使用Q.931消息来控制呼叫的建立和拆除,当系统中没有网守时,呼叫信令信道在呼叫涉及的两个终端之间打开;当系统中包括一个网守时,由网守决定在终端与网守之间或是在两个终端之间开辟呼叫信令信道;
  H.245控制信令用来传送终端到终端的控制消息,包括主从判别、能力交换、打开和关闭逻辑信道、模式参数请求、流控消息和通用命令与指令等。H.245控制信令信道建立于两个终端之间,或是一个终端与一个网守之间。
  此外,H.323不支持多点发送(Multicast)议,只能采用多点控制单元(MCU)构成多点会议,因而同时只能支持有限的多点用户。H.323也不支持呼叫转移,且建立呼叫的时间比较长。
  4.2 编码技术
  话音压缩编码技术是IP电话技术的一个重要组成部分。目前,主要的编码技术有ITU-T 定义的G.729、G.723等。其中G.729可将经过采样的64Kbit/s话音以几乎不失真的质量压缩至8Kbit/s。由于在分组交换网络中,业务质量不能得到很好保证,因而需要话音的编码具有一定的灵活性,即编码速率、编码尺度的可变可适应性。G.729原来是8Kbit/s的话音编码标准,现在的工作范围扩展至6.4-11.8Kbit/s,话音质量也在此范围内有一定的变化,但即使是6.4Kbit/s,话音质量也还不错,因而很适合在VOIP系统中使用。G.723.1采用5.3/6.3kbit/s双速率话音编码,其话音质量好,但是处理时延较大,它是目前已标准化的最低速率的话音编码算法。
  此外,静音检测技术和回声消除技术也是VOIP中十分关键的技术。静音检测技术可有效剔除静默信号,从而使话音信号的占用带宽进一步降低到3.5kbit/s左右;回声消除技术主要利用数字滤波器技术来消除对通话质量影响很大回声干扰,保证通话质量。这点在时延相对较大的IP分组网络中尤为重要。
  4.3 实时传输技术
  实时传输技术主要是采用实时传输协议RTP。RTP是提供端到端的包括音频在内的实时数据传送的协议。RTP包括数据和控制两部分,后者叫RTCP。RTP提供了时间标签和控制不同数据流同步特性的机制,可以让接收端重组发送端的数据包,可以提供接收端到多点发送组的服务质量包馈。
  4.4 QOS保障技术
  VOIP中主要采用资源预留协议(RSVP)以及进行服务质量监控的实时传输控制协议RTCP来避免网络拥塞,保障通话质量。
  4.5 网络传输技术
VOIP中网络传输技术主要是TCP和UDP,此外还包括网关互联技术、路由选择技术、网络管理技术以及安全认证和计费技术等。由于实时传输协议RTP提供具有实时特征的、端到端的数据传输业务,因此VOIP可用RTP来传送话音数据。在RTP报头中包含装载数据的标识符、序列号、时间戳以及传送监视等,通常RTP协议数据单元是用UDP分组来承载,而且为了尽量减少时延,话音净荷通常都很短。IP、UDP和RTP报头都按最小长度计算。VOIP话音分组开销很大,采用RTP协议的VOIP格式,在这种方式中将多路话音插入话音数据段中,这样提高了传输效率。

五、VoIP各项产品及设备的类型
  和许多早期网络设备一样,VoIP最早是以软件的形态问世的,也就是纯粹PC to PC功能的产品。为了能贴近过去传统模拟电话的使用习惯及经验,之后才渐渐有电话形态的产品出现。对于企业而言,为了追求成本、语音及网络的整合、多媒体增值功能、更方便的集中式管理,而陆续出现了VoIP网关、IP PBX或其它整合型的VoIP设备等解决方案。以下就这几种类型的VoIP产品做一简单介绍。
  1、VoIP软件
  软件不但是网络电话的原始形态,更是开启免费通话新世纪到来的开路先锋。对于熟悉计算机及网络操作的人而言,只要发收双方计算机上安装VoIP软件,即可穿越因特网相互通话,这实在是件既神奇又方便的事。更重要的是,透过VoIP软件,不论是当地PC to PC的对话,抑或跨国交谈都几乎免费,同时网上并有许多免费的VoIP软件提供下载,也因为如此,.VoIP才能紧紧锁住一般消费者乃至企业用户的目光。
  但对于绝大多数的使用者而言,必须克服计算机软件安装及操作的门坎,还要安插耳机及麦克风,更要面对系统不稳定或当机的可能性,所以透过PC来打电话不但是件麻烦事,而且是一种与既有通话习惯不符的奇怪行径。
  不论如何,VoIP软件背后所潜藏的无限商机,不但吸收了许多人的目光,同时成为VoIP兵家必争的焦点。从早期的视讯会议软件,到实时通讯软件,再到今日造成风潮的Skype都是明显的例子。不论是Wintel阵营中的微软、Intel,抑或Yahoo、AOL、Google、PC Home Online等入口网站、甚或ISP厂商,全都卯足全劲进行各种抢摊作业。
  其中,许多ISP并推出整合VoIP软件及USB话机的销售方案,例如SEEDNet的Wagaly Walk及PC Home Online的「PChome Touch-1」USB话机。至于外型上与一般电话无异的USB话机,就是为营造出一种与传统电话外观及使用习性相同的一种解决方案。
  2、VoIP网络电话
  一般而言VoIP网络电话的又分成有线、无线VoIP网络电话,以及提供影像输出的VoIP视讯会议设备等不同类型的产品。由于VoIP网络电话机上具备RJ45网络接口端口,所以不需藉由计算机主机,即可透过宽频、连结IP网络进行通话,同时使用习性上与传统电话一样,一般人很难分辨出其中的差异。
  VoIP网络电话较少用于个人家庭或SOHO市场,但却经常做为企业VoIP网络建设中的终端设备。但由于目前VoIP网络电话的价格仍高,所以仍不普遍,虽然之前,拜SARS之赐,促进了些VoIP视讯会议设备的销售业绩,但整体而言成长幅并不太大。 此外,微软特别在Win CE 5.0中新增VoIP功能,除了强化与Exchange Server的整合性外,并提供讯息整合及身份管理等功能,届时藉由WinCE开发出来的VoIP电话,将提供多人共享,但每人皆有私人专属账号的功能。
  3、VoIP网关器
除了VoIP软件之外,VoIP网关器可说是最普遍常见的网络电话设备。不论是家用或商用领域中,VoIP网关器可说扮演了由传统PSTN网络转输到IP网络的接口,换句话说,透过它即可用传统的电话设备(乃至PBX交换系统)来打网络电话。
目前市场上主要有两类IP电话网关。第一类是在某些型号的路由器上插话音板,路由器本身成为IP电话网关。这类路由器上有三种典型的端口:局域网口连接本地网络,广域网口连接广域网另一端的路由器,话音口连接电话或程控交换设备。第二类是单独的IP电话网关,这类网关只有两种接口,一种是局域网口连接集线器,一种是话音口连接电话或程控交换设备
比较而言,第一类设备如果直接连接广域网,则在传输话音/传真时不再经过本地网络(LAN),减少一个环节,时延会少一点。但是LAN上传输速率一般为10Mbps~100Mbps,因此实际情况会有差异。第一类网关也有弱点,一是有单点故障,二是将复杂的话音采样后的一切工作全部交给一台中小型路由器,负荷可能稍重,三是这类网关的安装配置工作稍复杂。相比之下,第二类网关设备更灵活,且消除了单点故障
  4、VoIP PBX
  在电信级的网络电话架构中,IP PBX语音交换机扮演了相当重要的角色,其不但需要接手传统语音交换机的位置及功能,还要居中成为语音与信息整合的媒介。IP PBX功能强大且多样化,能透过Web-Based接口提供使用者一个简单容易的操作环境。
  依据思科常久在IP PBX的经验指出,在IP电话网络架构中,IP PBX是一个可促使语音流量顺利传至所指定终端的设备。IP电话将语音讯号转换为IP封包后,由IP PBX透过讯号控制决定其封包的传输方向。当此通电话终点为一般电话时,其IP PBX便将IP封包送至网关器,然后由VoIP网关器转换IP封包,再回传到一般TDM的PSTN电路交换网。
  总之,对于企业而言,IP PBX具备降低基础建设成本、减低管理成本及增加工作效率之综合运用、降低转移至IP电话系统的风险等优点。

 

如何指定Freeswitch绑定IP地址

LC 2015-10-17 Networking

前一篇我们介绍了Freeswitch的安装与配置

使用过程中发现有server上有多个网卡,监听freeswitch进程的IP地址并不是我想要的,于是上网查找了一下如何指定Freeswitch绑定IP地址,找到解决办法。记录如下:

关于如何指定FreeSWITCH使用多网卡服务器上的某一个IP地址,FS官网给了新的方法,如下:


设置方法:


1、修改文件internal.xml和external.xml


位置:/usr/local/freeswitch/conf/sip_profiles/internal.xml


修改内容:


<param name="rtp-ip" value="192.168.1.3"/>
 <param name="sip-ip" value="192.168.1.3"/>


注:192.168.1.3为指定的IP地址


2、修改文件sofia.conf.xml


位置:/usr/local/freeswitch/conf/autoload_configs/sofia.conf.xml


修改内容:


<param name="auto-restart" value="false"/>


该属性设置的目的是防止FS在检测到IP地址发生改变后,自动重启sofia模块。


3、重启FreeSWITCH,开始测试。


over.

 


下面是旧的设置方法,不担保是否有问题----------------------------------------------------------


本篇教程基于Centos 5.5下面的FreeSWITCH1.0.6,使用的是自带的样例配置文件。
服务器网络配置如下:
        eth0:连接公网,拥有动态IP(使用DHCP获取)
        eth1:连接内网,拥有静态IP
该教程假设已经有一个号码为1000的sip话机连接到系统上,用于呼入呼出。系统默认配置文件
 位于/usr/local/freeswitch/conf.


下面为具体的设置步骤:
1、打开conf目录下的vars.xml文件,并做如下修改:
    1)查找变量domain,并修改为公网IP地址或DNS地址
            <X-PRE-PROCESS cmd="set" data="domain=(公网IP)"/>
            
     2)移动到文件末尾,增加如下变量
        其中,$${local_ip_v4}代表系统所在的公网地址,192.168.100.1是用于连接内网的私有IP地址
            <X-PRE-PROCESS cmd="set" data="external_sip_ip=$${local_ip_v4}"/>
             <X-PRE-PROCESS cmd="set" data="external_rtp_ip=$${local_ip_v4}"/>


             <X-PRE-PROCESS cmd="set" data="internal_sip_ip=192.168.100.1"/>
             <X-PRE-PROCESS cmd="set" data="internal_rtp_ip=192.168.100.1"/>


 2、修改sip的external与internal配置文件
    打开sip_profile/external.xml文件,反注释下面的行:
        <param name="force-register-domain" value="$${domain}"/>
         <param name="force-register-db-domain" value="$${domain}"/>
         <param name="dbname" value="share_presence"/>
         <param name="presence-hosts" value="$${domain}"/>
            
     打开sip_profile/internal.xml文件,反注释相同的行:
        <param name="force-register-domain" value="$${domain}"/>
         <param name="force-register-db-domain" value="$${domain}"/>
         <param name="dbname" value="share_presence"/>
         <param name="presence-hosts" value="$${domain}"/>


 3、向sip profile中添加网关配置           
打开文件sip_profile/external/example.xml,进行必要的修改,以便连接到sip服务提供商那。具体的配置教程很多,不再详述。需要注意的是要将网关名称改为“multi-example”,后面会用到。
    <gateway name="multi-example">


 4、添加由上一步添加的网关呼入的路由
 为了让系统可以正确的路由DID,需要修改拨号方案文件:dialplan/public/00_inbound_did.xml。根据sip provider传递过来的目标号码,修改destination_number表达式的值,如下:
 修改前:  <condition field="destination_number" expression="^(phonenumber)$">
修改后:  <condition field="destination_number" expression="^(4075551234)$">


 5、修改呼出路由,应用上面添加的网关配置
 为了能让系统跑起来并运行正常,最后要修改的配置是在呼叫路由中添加第三步中配置的sip provider。修改文件dialplan/default/01_example.com.xml,并做如下修改:
 找到<extension name="domestic.example.com"> 所在的块,
    修改前: <action application="bridge" data="sofia/gateway/${default_gateway}/$1"/>
     修改后: <action application="bridge" data="sofia/gateway/multi-example /$1"/>


 6、最后一步,重新加载配置文件和sip模块
    >reloadxml
     >reload mod_sofia
    或者,直接重启FreeSWITCH。
   所有的操作完成后,就可以拨打你所配置的DID号码,紧接着你的sip话机就会开始振铃。同样,也可以通过sip话机拨打外线电话。

Install and configure freeswitch server

LC 2015-10-16 Networking

一 安装freeswitch

环境centos6

1.安装前需要用到的RPM包和一些基础的软件包。

#rpm -ivh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm

#yum install git gcc-c++ autoconf automake libtool wget python ncurses-devel zlib-devel libjpeg-devel openssl-devel e2fsprogs-devel sqlite-devel libcurl-devel pcre-devel speex-devel ldns-devel libedit-devel
----------------------------------------------------------
2.使用git源去获取freeswitch的软件源代码。(注意在目录/usr/src下)
#cd /usr/src
###通过以下命令是获取最新版本的freeswitch
#git clone https://freeswitch.org/stash/scm/fs/freeswitch.git
###如果知道版本可以通过以下命令
git clone -b v1.4 https://freeswitch.org/stash/scm/fs/freeswitch.git

3.初始化安装freeswitch的某些编译环境,配置环境,以及编译安装。
#./bootstrap.sh -j
#./configure -C
#make && make install
----------------------------------------------------------
3.通过压缩源码安装包来安装

 1)使用wget获取源代码安装包
  1.获取代码
  wget http://files.freeswitch.org/freeswitch-1.4.0.beta6.tar.bz2
  2.解压包
  chmod 777 freeswitch-1.4.0.beta6.tar.bz2
  tar xvjf freeswitch-1.4.0.beta6.tar.bz2
  3.配置和安装
  cd freeswitch-1.4.0
  ./configure
  make install

(用get源代码到安装好一部到位可以是用此命令:wget http://www.freeswitch.org.cn/Makefile && make install)

FreeSWITCH使用make install安装完成后,会显示一个有用的帮助,它会提示你接下来可以用哪些make命令执行一些其他的操作(如我们刚才安装声音文件的命令,在这里就可以看到)。下面笔者在默认的帮助信息后增加了一些中文的注释,读者可以在学习中自行练习一下。
 
1. +---------- FreeSWITCH install Complete ----------+ 
2. + FreeSWITCH has been successfully installed.     + 
3. +                                                 + 
4. +       Install sounds:                           +  安装声音文件 
5. +       (uhd-sounds includes hd-sounds, sounds)   + 
6. +       (hd-sounds includes sounds)               + 
7. +       ------------------------------------      + 
8. +                make cd-sounds-install           +  CD音质的声音文件 
9. +                make cd-moh-install              + 
10. +                                                 + 
11. +                make uhd-sounds-install          +  超高清声音文件 
12. +                make uhd-moh-install             + 
13. +                                                 + 
14. +                make hd-sounds-install           +  高清声音文件 
15. +                make hd-moh-install              + 
16. +                                                 + 
17. +                make sounds-install              +  标准声音文件 
18. +                make moh-install                 + 
19. +                                                 + 
20. +       Install non english sounds:               +  安装其他语言的声音文件 
21. +       replace XX with language                  + 
22. +       (ru : Russian)                            +  如ru代表俄语 
23. +       ------------------------------------      + 
24. +                make cd-sounds-XX-install        + 
25. +                make uhd-sounds-XX-install       + 
26. +                make hd-sounds-XX-install        + 
27. +                make sounds-XX-install           + 
28. +                                                 + 
29. +       Upgrade to latest:                        +  升级到最新版本 
30. +       ----------------------------------        + 
31. +                make current                     + 
32. +                                                 + 
33. +       Rebuild all:                              +  重新编译 
34. +       ----------------------------------        + 
35. +                make sure                        + 
36. +                                                 + 
37. +       Install/Re-install default config:         +  安装(或重新安装)配置文件 
38. +       ----------------------------------        + 
39. +                make samples                     + 
40. +                                                 + 
41. +       Additional resources:                     + 
42. +       ----------------------------------        + 
43. +       http://www.freeswitch.org                 +  官方网站 
44. +       http://wiki.freeswitch.org                +  官方Wiki 
45. +       http://jira.freeswitch.org                +  官方的缺陷跟踪工具 
46. +       http://lists.freeswitch.org               +  邮件列表 
47. +                                                 + 
48. +       irc.freenode.net / #freeswitch            +  IRC聊天室 
49. +-------------------------------------------------+

 

4.安装声音文件
#pwd

make cd-sounds-install
make cd-moh-install
此过程需要一段时间。

至此,FreeSWITCH就已经安装完了。在UNIX类操作系统上,其默认的安装位置是/usr/local/freeswitch(下文所述的路径全部相对于该路径)。两个常用的命令是 bin/freeswitch 和 bin/fs_cli(我们下面会讲到它们的用法),为了便于使用,建议将这两个命令做符号链接放到你的搜索路径中,如:
 
ln -sf /usr/local/freeswitch/bin/freeswitch /usr/bin/ 
ln -sf /usr/local/freeswitch/bin/fs_cli /usr/bin/

 

不管FreeSWITCH运行在前面还是后台,都可以使用客户端软件fs_cli连接到它并对它进行控制。使用方法为:

  /usr/local/freeswwitch/bin/fs_cli
当然,如果上面已经做了符号连接也可以直接运行fs_cli。任何时间想退出fs_cli客户端,都可以输入/exit或按Ctrl + D组合键,也可以直接关掉终端窗口。

 

关闭freeswitch的命令是
freeswitch -stop
 
freeswitch -nc #freeswitch在后台启nc:no console


二 连接SIP电话
在这里用软电话x-lite为例。

环境在同一个局域网上安装x-lite并且保证麦克风和听筒能够正常工作。
 
当然,如果你没有多余的机器做这个实验,也可以在同一台机器上安装。只是需要注意,软电话不要占用 UDP 5060 端口,因为 FreeSWITCH 默认要使用该端口,你可以通过先启动 FreeSWITCH 再启动软电话来避免该问题(后者如果在启动时发现5060端口已被占用,一般会尝试选择其他端口),另外有些软电话允许你修改本地监听端口。

通过以下命令可以知道freeswitch监听的IPaddress
 
netstat -an | grep 5060 

FreeSWITCH 默认配置了1000 ~ 1019共 20 个用户,你可以随便选择一个用户进行配置,配置过程如下:

    1)在 X-Lite 上右击,选“Sip Account Settings...”,单击“Add”添加一个账号,填入以下参数:
 
1. Display Name: 1000 
2. User name: 1000 
3. Password: 1234 
4. Authorization user name: 1000


Domain: 你的IP地址,就是安装freeswitch机器的动态地址。

     2)其他项默认设置即可,而后单击“OK”.关闭setting窗口。接着可以在x-lite显示窗口上看到类似与“Ready. Your username is 1000”,并且拨打号码键也变为绿色。

     3)用sip电话拨打9664按下绿色拨打键,看是否能听到声音。
           如果没有声音就检查听筒是否坏了,如果正常检查声音安装文件是否成功。
      测试声音拨打号码参考如下网站
http://wiki.freeswitch.org/wiki/Default_Dialplan_QRF

注册另外一个sip软电话,用于两电话之间互相接通。
最好是在同一个局域网中的另外一台机器上启动另一个X-Lite ,并使用 1001 注册,注册完毕后就可以在1000上呼叫 1001,或在1001上呼叫1000 。也可以在同一台机器上安装,但是可以回影响通话质量,因为只有一张声卡。

 


三 配置freeswitch
Freeswitch的配置文件默认放置在conf/下,最顶层文件是freeswitch.xml

一.添加一个简单的用户。
FreeSWITCH默认设置了20个用户(1000~1019),如果添加其其他的用户只需要执行下面三个步骤即可:
1)在 /conf/insideout/directory/default中增加一个用户配置文件。
2)修改拨号计划(Dialplan)使其他用户可以呼叫到它。
3)重新加载配置使其生效。
例如廷加joy 用户分机号为123456,只需要到 conf/directory/default 目录下,将 1000.xml 复制到 ,123456.xml中。打开123456.xml,将所有1000都改为123456。
<include>
  <user id="1000" mailbox="1000">
    <params>
      <param name="password" value="1234"/>
      <param name="vm-password" value="1000"/>
    </params>
    <variables>
      <variable name="toll_allow" value="domestic,international,local"/>
      <variable name="accountcode" value="1000"/>
      <variable name="user_context" value="default"/>
      <variable name="effective_caller_id_name" value="Extension 1000"/>
      <variable name="effective_caller_id_number" value="1000"/>
      <variable name="outbound_caller_id_name" value="$${outbound_caller_name}"/>
      <variable name="outbound_caller_id_number" value="$${outbound_caller_id}"/>
      <variable name="callgroup" value="techsupport"/>
    </variables>
  </user>
</include>


并把 effective_caller_id_name 的值改为joy,然后存盘退出,命令如下:

1. <variable name="effective_caller_id_name" value="Jack"/>

接下来,打开 conf/dialplan/default.xml,找到下面一行
 
1. <condition field="destination_number" expression="^(10[01][0-9])$">
将其改为
 
1. <condition field="destination_number" expression="^(10[01][0-9]|1234)$">
注释:正则表达式“^(10[01][0-9])$”匹配被叫号码1000~1019。因此我们修改之后的表达式就多匹配了一个123456。

然后,回到控制台或启动fs_cli,执行reloadxml命令或按快捷F6,使新的配置生效。

Configure Asterisk Server for MTA

LC 2015-10-15 Networking

配置Asterisk Server
1. 添加MTA
2. 设置拨号规则
3. 进入astersk的cli
4. 重启Server
[root@sipserver ~]# vim /etc/asterisk/mgcp.conf (添加MTA)    
;
; MGCP Configuration for Asterisk
;
[general]
;port = 2727
;bindaddr = 10.12.7.92
;bindaddr = 10.15.7.15
bindaddr = 0.0.0.0
disallow = all
allow = alaw
allow = ulaw
;tos=lowdelay


;typical NCS cable modem definition
;[x1-6-00-50-bf-b8-18-67.mtt.com]
;[x1-6-00-22-2d-62-cd-97.mtt.com]
;host=10.15.51.36
;dtmfmode= inband;rfc2833
;context = default
;
;ncs=1
;;nat=no
;wcardep= aaln/*
;callerid ="David_1" <85592926>
;;"Anonymous" <Anonymous>;"Private" <Private>;"David_1" <85592926>
;line => aaln/1
;callwaiting=yes
;cancallforward=yes
;canreinvite=no
;transfer=yes
;;callerid ="David_23" <85592272>
;line => aaln/2

[DUT1-112233.sh.useasp.net]     -------------[HostName+DomainName]
host=dynamic
dtmfmode= inband;rfc2833
context = default
ncs=1
;nat=no
wcardep= aaln/*
callerid ="dut1-112233"
line => aaln/1
callwaiting=yes
cancallforward=yes
canreinvite=no
transfer=yes
line => aaln/2

;;;;;;;;;;;;;;;;;;;;;;
; Custom patch for "template" cable modem.
; Any undefined NCS gateway can register with *
; It will get this template definition after first RSIP (or any other message)
; warning - this setup has no security ACLs !
; 'mgcp reload' deletes all 'template cloned' entries that are not in use
;[template]
;host=dynamic
;dtmfmode=rfc2833
;ncs=1
;nat=no
;canreinvite=no
;wcardep= aaln/*

;context = default
;immediate= no
;line => aaln/1

;context = default
;immediate= no
;line => aaln/2

;;;kb add below
;;[001ceaa51302]
;;;context=ext-local
;;context=default
;;host=dynamic
;;dtmfmode=rfc2833
;;line => aaln/1
;;callwaiting=yes
;;cancallforward=yes
;;canreinvite=no
;;transfer=yes
;;line => aaln/2
;;;end kb add
;
;
;;kb add below
;;[10.15.80.12]
;[10.15.81.185]
;;context=ext-local
;wcardep=aaln/*
;;context=default
;;host=dynamic
;host=10.15.81.185
;dtmfmode=rfc2833
;line => aaln/1
;callwaiting=yes
;cancallforward=yes
;canreinvite=no
;transfer=yes
;line => aaln/2
;;end kb add


[root@sipserver ~]#vim /etc/asterisk/sip.conf 配置sip

;[pre14-asterisk]
;type=friend
;secret=digium
;host=dynamic
;rfc2833compensate=yes          ; Compensate for pre-1.4 DTMF transmission from another Asterisk machine.
                                ; You must have this turned on or DTMF reception will work improperly.
;t38pt_usertpsource=yes         ; Use the source IP address of RTP as the destination IP address for UDPTL packets
                                ; if the nat option is enabled. If a single RTP packet is received Asterisk will know the
                                ; external IP address of the remote device. If port forwarding is done at the client side
                                ; then UDPTL will flow to the remote device.

 

[11112]
type=friend                     ; Friends place calls and receive calls
context=from-sip                ; Context for incoming calls from this user
secret=11112
host=dynamic                    ; This peer register with us
dtmfmode=rfc2833                ; Choices are inband, rfc2833, or info
                                 ; Normally you do NOT need to set this parameter
disallow=all
allow=ulaw                      ; dtmfmode=inband only works with ulaw or alaw!
progressinband=no               ; Polycom phones don't work properly with "never"
 

[11111]
type=friend                     ; Friends place calls and receive calls
context=from-sip                ; Context for incoming calls from this user
secret=11111
host=dynamic                    ; This peer register with us
dtmfmode=rfc2833                ; Choices are inband, rfc2833, or info
                                 ; Normally you do NOT need to set this parameter
disallow=all
allow=ulaw                      ; dtmfmode=inband only works with ulaw or alaw!
progressinband=no               ; Polycom phones don't work properly with "never

[root@sipserver ~]# vim /etc/asterisk/extensions.conf(设置拨号规则)
; extensions.conf - the Asterisk dial plan
;
; Static extension configuration file, used by
; the pbx_config module. This is where you configure all your
; inbound and outbound calls in Asterisk.
;
; This configuration file is reloaded
; - With the "dialplan reload" command in the CLI
; - With the "reload" command (that reloads everything) in the CLI

;
; The "General" category is for certain variables. 
;
[general]
;
; If static is set to no, or omitted, then the pbx_config will rewrite
; this file when extensions are modified.  Remember that all comments
; made in the file will be lost when that happens.
;
; XXX Not yet implemented XXX
;
static=yes
;
; if static=yes and writeprotect=no, you can save dialplan by
; CLI command "dialplan save" too
;
writeprotect=no
;
; If autofallthrough is set, then if an extension runs out of
; things to do, it will terminate the call with BUSY, CONGESTION
; or HANGUP depending on Asterisk's best guess. This is the default.
;
; If autofallthrough is not set, then if an extension runs out of
; things to do, Asterisk will wait for a new extension to be dialed
; (this is the original behavior of Asterisk 1.0 and earlier).
;
;autofallthrough=no
;
;
;
; If extenpatternmatchnew is set (true, yes, etc), then a new algorithm that uses
; a Trie to find the best matching pattern is used. In dialplans
; with more than about 20-40 extensions in a single context, this
; new algorithm can provide a noticeable speedup.
; With 50 extensions, the speedup is 1.32x
; with 88 extensions, the speedup is 2.23x
; with 138 extensions, the speedup is 3.44x
; with 238 extensions, the speedup is 5.8x
; with 438 extensions, the speedup is 10.4x
; With 1000 extensions, the speedup is ~25x
; with 10,000 extensions, the speedup is 374x
; Basically, the new algorithm provides a flat response
; time, no matter the number of extensions.
;
; By default, the old pattern matcher is used.
;
; ****This is a new feature! *********************
; The new pattern matcher is for the brave, the bold, and
; the desperate. If you have large dialplans (more than about 50 extensions
; in a context), and/or high call volume, you might consider setting
; this value to "yes" !!
; Please, if you try this out, and are forced to return to the
; old pattern matcher, please report your reasons in a bug report
; on bugs.digium.com. We have made good progress in providing something
; compatible with the old matcher; help us finish the job!
;
; This value can be switched at runtime using the cli command "dialplan set extenpatternmatchnew true"
; or "dialplan set extenpatternmatchnew false", so you can experiment to your hearts content.
;
;extenpatternmatchnew=no
;
; If clearglobalvars is set, global variables will be cleared
; and reparsed on a dialplan reload, or Asterisk reload.
;
; If clearglobalvars is not set, then global variables will persist
; through reloads, and even if deleted from the extensions.conf or
; one of its included files, will remain set to the previous value.
;
; NOTE: A complication sets in, if you put your global variables into
; the AEL file, instead of the extensions.conf file. With clearglobalvars
; set, a "reload" will often leave the globals vars cleared, because it
; is not unusual to have extensions.conf (which will have no globals)
; load after the extensions.ael file (where the global vars are stored).
; So, with "reload" in this particular situation, first the AEL file will
; clear and then set all the global vars, then, later, when the extensions.conf
; file is loaded, the global vars are all cleared, and then not set, because
; they are not stored in the extensions.conf file.
;
clearglobalvars=no
;
; If priorityjumping is set to 'yes', then applications that support
; 'jumping' to a different priority based on the result of their operations
; will do so (this is backwards compatible behavior with pre-1.2 releases
; of Asterisk). Individual applications can also be requested to do this
; by passing a 'j' option in their arguments.
;
;priorityjumping=yes
;
; User context is where entries from users.conf are registered.  The
; default value is 'default'
;
;userscontext=default
;
; You can include other config files, use the #include command
; (without the ';'). Note that this is different from the "include" command
; that includes contexts within other contexts. The #include command works
; in all asterisk configuration files.
;#include "filename.conf"

; The "Globals" category contains global variables that can be referenced
; in the dialplan with the GLOBAL dialplan function:
; ${GLOBAL(VARIABLE)}
; ${${GLOBAL(VARIABLE)}} or ${text${GLOBAL(VARIABLE)}} or any hybrid
; Unix/Linux environmental variables can be reached with the ENV dialplan
; function: ${ENV(VARIABLE)}
;
[globals]
CONSOLE=Console/dsp                             ; Console interface for demo
;CONSOLE=DAHDI/1
;CONSOLE=Phone/phone0
IAXINFO=guest                                   ; IAXtel username/password
;IAXINFO=myuser:mypass
TRUNK=DAHDI/G2                                  ; Trunk interface
;
; Note the 'G2' in the TRUNK variable above. It specifies which group (defined
; in dahdi.conf) to dial, i.e. group 2, and how to choose a channel to use in
; the specified group. The four possible options are:
;
; g: select the lowest-numbered non-busy DAHDI channel
;    (aka. ascending sequential hunt group).
; G: select the highest-numbered non-busy DAHDI channel
;    (aka. descending sequential hunt group).
; r: use a round-robin search, starting at the next highest channel than last
;    time (aka. ascending rotary hunt group).
; R: use a round-robin search, starting at the next lowest channel than last
;    time (aka. descending rotary hunt group).
;
TRUNKMSD=1                                      ; MSD digits to strip (usually 1 or 0)
;TRUNK=IAX2/user:pass@provider

;
; Any category other than "General" and "Globals" represent
; extension contexts, which are collections of extensions. 
;
; Extension names may be numbers, letters, or combinations
; thereof. If an extension name is prefixed by a '_'
; character, it is interpreted as a pattern rather than a
; literal.  In patterns, some characters have special meanings:
;
;   X - any digit from 0-9
;   Z - any digit from 1-9
;   N - any digit from 2-9
;   [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9)
;   . - wildcard, matches anything remaining (e.g. _9011. matches
;       anything starting with 9011 excluding 9011 itself)
;   ! - wildcard, causes the matching process to complete as soon as
;       it can unambiguously determine that no other matches are possible
;
; For example the extension _NXXXXXX would match normal 7 digit dialings,
; while _1NXXNXXXXXX would represent an area code plus phone number
; preceded by a one.
;
; Each step of an extension is ordered by priority, which must
; always start with 1 to be considered a valid extension.  The priority
; "next" or "n" means the previous priority plus one, regardless of whether
; the previous priority was associated with the current extension or not.
; The priority "same" or "s" means the same as the previously specified
; priority, again regardless of whether the previous entry was for the
; same extension.  Priorities may be immediately followed by a plus sign
; and another integer to add that amount (most useful with 's' or 'n'). 
; Priorities may then also have an alias, or label, in
; parenthesis after their name which can be used in goto situations
;
; Contexts contain several lines, one for each step of each
; extension, which can take one of two forms as listed below,
; with the first form being preferred.  One may include another
; context in the current one as well, optionally with a
; date and time.  Included contexts are included in the order
; they are listed.
;
;[context]
;exten => someexten,{priority|label{+|-}offset}[(alias)],application(arg1,arg2,...)
;
; Timing list for includes is
;
;   <time range>,<days of week>,<days of month>,<months>
;
; Note that ranges may be specified to wrap around the ends.  Also, minutes are
; fine-grained only down to the closest even minute.
;
;include => daytime,9:00-17:00,mon-fri,*,*
;include => weekend,*,sat-sun,*,*
;include => weeknights,17:02-8:58,mon-fri,*,*
;
; ignorepat can be used to instruct drivers to not cancel dialtone upon
; receipt of a particular pattern.  The most commonly used example is
; of course '9' like this:
;
;ignorepat => 9
;
; so that dialtone remains even after dialing a 9.
;

;
; Sample entries for extensions.conf
;
;
[dundi-e164-canonical]
;
; List canonical entries here
;
;exten => 12564286000,1,Gosub(stdexten,s,1(6000,IAX2/foo))
;exten => 12564286000,n,Goto(default,s,1)       ; exited Voicemail
;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7})

[dundi-e164-customers]
;
; If you are an ITSP or Reseller, list your customers here.
;
;exten => _12564286000,1,Dial(SIP/customer1)
;exten => _12564286001,1,Dial(IAX2/customer2)

[dundi-e164-via-pstn]
;
; If you are freely delivering calls to the PSTN, list them here
;
;exten => _1256428XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Expose all of 256-428
;exten => _1256325XXXX,1,Dial(DAHDI/G2/${EXTEN:7}) ; Ditto for 256-325

[dundi-e164-local]
;
; Context to put your dundi IAX2 or SIP user in for
; full access
;
include => dundi-e164-canonical
include => dundi-e164-customers
include => dundi-e164-via-pstn

[dundi-e164-switch]
;
; Just a wrapper for the switch
;
switch => DUNDi/e164

[dundi-e164-lookup]
;
; Locally to lookup, try looking for a local E.164 solution
; then try DUNDi if we don't have one.
;
include => dundi-e164-local
include => dundi-e164-switch
;
; DUNDi can also be implemented as a Macro instead of using
; the Local channel driver.
;
[macro-dundi-e164]
;
; ARG1 is the extension to Dial
;
; Extension "s" is not a wildcard extension that matches "anything".
; In macros, it is the start extension. In most other cases,
; you have to goto "s" to execute that extension.
;
; For wildcard matches, see above - all pattern matches start with
; an underscore.
exten => s,1,Goto(${ARG1},1)
include => dundi-e164-lookup

;
; Here are the entries you need to participate in the IAXTEL
; call routing system.  Most IAXTEL numbers begin with 1-700, but
; there are exceptions.  For more information, and to sign
; up, please go to www.gnophone.com or www.iaxtel.com
;
[iaxtel700]
exten => _91700XXXXXXX,1,Dial(IAX2/${GLOBAL(IAXINFO)}@iaxtel.com/${EXTEN:1}@iaxtel)

;
; The SWITCH statement permits a server to share the dialplan with
; another server. Use with care: Reciprocal switch statements are not
; allowed (e.g. both A -> B and B -> A), and the switched server needs
; to be on-line or else dialing can be severly delayed.
;
[iaxprovider]
;switch => IAX2/user:[key]@myserver/mycontext

[trunkint]
;
; International long distance through trunk
;
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

[trunkld]
;
; Long distance context accessed through trunk
;
exten => _91NXXNXXXXXX,1,Macro(dundi-e164,${EXTEN:1})
exten => _91NXXNXXXXXX,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

[trunklocal]
;
; Local seven-digit dialing accessed through trunk interface
;
exten => _9NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

[trunktollfree]
;
; Long distance context accessed through trunk interface
;
exten => _91800NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
exten => _91888NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
exten => _91877NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
exten => _91866NXXXXXX,1,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})

[international]
;
; Master context for international long distance
;
ignorepat => 9
include => longdistance
include => trunkint

[longdistance]
;
; Master context for long distance
;
ignorepat => 9
include => local
include => trunkld

[local]
;
; Master context for local, toll-free, and iaxtel calls only
;
ignorepat => 9
include => default
include => trunklocal
include => iaxtel700
include => trunktollfree
include => iaxprovider

;Include parkedcalls (or the context you define in features conf)
;to enable call parking.
include => parkedcalls
;
; You can use an alternative switch type as well, to resolve
; extensions that are not known here, for example with remote
; IAX switching you transparently get access to the remote
; Asterisk PBX
;
; switch => IAX2/user:password@bigserver/local
;
; An "lswitch" is like a switch but is literal, in that
; variable substitution is not performed at load time
; but is passed to the switch directly (presumably to
; be substituted in the switch routine itself)
;
; lswitch => Loopback/12${EXTEN}@othercontext
;
; An "eswitch" is like a switch but the evaluation of
; variable substitution is performed at runtime before
; being passed to the switch routine.
;
; eswitch => IAX2/context@${CURSERVER}

[macro-trunkdial]
;
; Standard trunk dial macro (hangs up on a dialstatus that should
; terminate call)
;   ${ARG1} - What to dial
;
exten => s,1,Dial(${ARG1})
exten => s,n,Goto(s-${DIALSTATUS},1)
exten => s-NOANSWER,1,Hangup
exten => s-BUSY,1,Hangup
exten => _s-.,1,NoOp

[stdexten]
;
; Standard extension subroutine:
;   ${ARG1} - Extension
;   ${ARG2} - Device(s) to ring
;   ${ARG3} - Optional context in Voicemail (if empty, then "default")
;
; Note that the current version will drop through to the next priority in the
; case of their pressing '#'.  This gives more flexibility in what do to next:
; you can prompt for a new extension, or drop the call, or send them to a
; general delivery mailbox, or...
;
; The use of the LOCAL() function is purely for convenience.  Any variable
; initially declared as LOCAL() will disappear when the innermost Gosub context
; in which it was declared returns.  Note also that you can declare a LOCAL()
; variable on top of an existing variable, and its value will revert to its
; previous value (before being declared as LOCAL()) upon Return.
;
exten => s,1,NoOp(Start stdexten)
exten => s,n,Set(LOCAL(ext)=${ARG1})
exten => s,n,Set(LOCAL(dev)=${ARG2})
exten => s,n,Set(LOCAL(cntx)=${ARG3})

exten => s,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""])
exten => s,n,Dial(${dev},20)                    ; Ring the interface, 20 seconds maximum
exten => s,n,Goto(s-${DIALSTATUS},1)            ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)

exten => s-NOANSWER,1,Voicemail(${mbx},u)       ; If unavailable, send to voicemail w/ unavail announce
exten => s-NOANSWER,n,NoOp(Finish stdexten NOANSWER)
exten => s-NOANSWER,n,Return()                  ; If they press #, return to start

exten => s-BUSY,1,Voicemail(${mbx},b)
                                                ; If busy, send to voicemail w/ busy announce
exten => s-BUSY,n,NoOp(Finish stdexten BUSY)
exten => s-BUSY,n,Return()                      ; If they press #, return to start

exten => _s-.,1,Goto(s-NOANSWER,1)              ; Treat anything else as no answer

exten => a,1,VoicemailMain(${mbx})              ; If they press *, send the user into VoicemailMain
                                                ; does this ever return?

[stdPrivacyexten]
;
; Standard extension subroutine:
;   ${ARG1} - Extension
;   ${ARG2} - Device(s) to ring
;   ${ARG3} - Optional DONTCALL context name to jump to (assumes the s,1 extension-priority)
;   ${ARG4} - Optional TORTURE context name to jump to (assumes the s,1 extension-priority)`
;   ${ARG5} - Context in voicemail (if empty, then "default")
;
; See above note in stdexten about priority handling on exit.
;
exten => s,1,NoOp(Start stdPrivacyexten)
exten => s,n,Set(LOCAL(ext)=${ARG1})
exten => s,n,Set(LOCAL(dev)=${ARG2})
exten => s,n,Set(LOCAL(dontcntx)=${ARG3})
exten => s,n,Set(LOCAL(tortcntx)=${ARG4})
exten => s,n,Set(LOCAL(cntx)=${ARG5})

exten => s,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""])
exten => s,n,Dial(${dev},20,p)                  ; Ring the interface, 20 seconds maximum, call screening
                                                ; option (or use P for databased call screening)
exten => s,n,Goto(s-${DIALSTATUS},1)            ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)

exten => s-NOANSWER,1,Voicemail(${mbx},u)       ; If unavailable, send to voicemail w/ unavail announce
exten => s-NOANSWER,n,NoOp(Finish stdPrivacyexten NOANSWER)
exten => s-NOANSWER,n,Return()                  ; If they press #, return to start

exten => s-BUSY,1,Voicemail(${mbx},b)           ; If busy, send to voicemail w/ busy announce
exten => s-BUSY,n,NoOp(Finish stdPrivacyexten BUSY)
exten => s-BUSY,n,Return()                      ; If they press #, return to start

exten => s-DONTCALL,1,Goto(${dontcntx},s,1)     ; Callee chose to send this call to a polite "Don't call again" script.

exten => s-TORTURE,1,Goto(${tortcntx},s,1)      ; Callee chose to send this call to a telemarketer torture script.

exten => _s-.,1,Goto(s-NOANSWER,1)              ; Treat anything else as no answer

exten => a,1,VoicemailMain(${mbx})              ; If they press *, send the user into VoicemailMain
                                                ; does this ever return?

[macro-page];
;
; Paging macro:
;
;       Check to see if SIP device is in use and DO NOT PAGE if they are
;
;   ${ARG1} - Device to page

exten => s,1,ChanIsAvail(${ARG1},js)                    ; j is for Jump and s is for ANY call
exten => s,n,GoToIf([${AVAILSTATUS} = "1"]?autoanswer:fail)
exten => s,n(autoanswer),Set(_ALERT_INFO="RA")                  ; This is for the PolyComs
exten => s,n,SIPAddHeader(Call-Info: Answer-After=0)    ; This is for the Grandstream, Snoms, and Others
exten => s,n,NoOp()                                     ; Add others here and Post on the Wiki!!!!
exten => s,n,Dial(${ARG1})
exten => s,n(fail),Hangup


[demo]
;
; We start with what to do when a call first comes in.
;
exten => s,1,Wait(1)                    ; Wait a second, just for fun
exten => s,n,Answer                     ; Answer the line
exten => s,n,Set(TIMEOUT(digit)=5)      ; Set Digit Timeout to 5 seconds
exten => s,n,Set(TIMEOUT(response)=10)  ; Set Response Timeout to 10 seconds
exten => s,n(restart),BackGround(demo-congrats) ; Play a congratulatory message
exten => s,n(instruct),BackGround(demo-instruct)        ; Play some instructions
exten => s,n,WaitExten                  ; Wait for an extension to be dialed.

exten => 2,1,BackGround(demo-moreinfo)  ; Give some more information.
exten => 2,n,Goto(s,instruct)

exten => 3,1,Set(LANGUAGE()=fr)         ; Set language to french
exten => 3,n,Goto(s,restart)            ; Start with the congratulations

exten => 1000,1,Goto(default,s,1)
;
; We also create an example user, 1234, who is on the console and has
; voicemail, etc.
;
exten => 1234,1,Playback(transfer,skip)         ; "Please hold while..."
                                        ; (but skip if channel is not up)
exten => 1234,n,Gosub(stdexten,s,1(1234,${GLOBAL(CONSOLE)}))
exten => 1234,n,Goto(default,s,1)               ; exited Voicemail

exten => 1235,1,Voicemail(1234,u)               ; Right to voicemail

exten => 1236,1,Dial(Console/dsp)               ; Ring forever
exten => 1236,n,Voicemail(1234,b)               ; Unless busy

;
; # for when they're done with the demo
;
exten => #,1,Playback(demo-thanks)      ; "Thanks for trying the demo"
exten => #,n,Hangup                     ; Hang them up.

;
; A timeout and "invalid extension rule"
;
exten => t,1,Goto(#,1)                  ; If they take too long, give up
exten => i,1,Playback(invalid)          ; "That's not valid, try again"

;
; Create an extension, 500, for dialing the
; Asterisk demo.
;
exten => 500,1,Playback(demo-abouttotry); Let them know what's going on
exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default)        ; Call the Asterisk demo
exten => 500,n,Playback(demo-nogo)      ; Couldn't connect to the demo site
exten => 500,n,Goto(s,6)                ; Return to the start over message.

;
; Create an extension, 600, for evaluating echo latency.
;
exten => 600,1,Playback(demo-echotest)  ; Let them know what's going on
exten => 600,n,Echo                     ; Do the echo test
exten => 600,n,Playback(demo-echodone)  ; Let them know it's over
exten => 600,n,Goto(s,6)                ; Start over

;
;       You can use the Macro Page to intercom a individual user
exten => 76245,1,Macro(page,SIP/Grandstream1)
; or if your peernames are the same as extensions
exten => _7XXX,1,Macro(page,SIP/${EXTEN})
;
;
; System Wide Page at extension 7999
;
exten => 7999,1,Set(TIMEOUT(absolute)=60)
exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)

; Give voicemail at extension 8500
;
exten => 8500,1,VoicemailMain
exten => 8500,n,Goto(s,6)
;
; Here's what a phone entry would look like (IXJ for example)
;
;exten => 1265,1,Dial(Phone/phone0,15)
;exten => 1265,n,Goto(s,5)

;
;       The page context calls up the page macro that sets variables needed for auto-answer
;       It is in is own context to make calling it from the Page() application as simple as
;       Local/{peername}@page
;
[page]
exten => _X.,1,Macro(page,SIP/${EXTEN})

;[mainmenu]
;
; Example "main menu" context with submenu
;
;exten => s,1,Answer
;exten => s,n,Background(thanks)                ; "Thanks for calling press 1 for sales, 2 for support, ..."
;exten => s,n,WaitExten
;exten => 1,1,Goto(submenu,s,1)
;exten => 2,1,Hangup
;include => default
;
;[submenu]
;exten => s,1,Ringing                                   ; Make them comfortable with 2 seconds of ringback
;exten => s,n,Wait,2
;exten => s,n,Background(submenuopts)   ; "Thanks for calling the sales department.  Press 1 for steve, 2 for..."
;exten => s,n,WaitExten
;exten => 1,1,Goto(default,steve,1)
;exten => 2,1,Goto(default,mark,2)

[default]
;
; By default we include the demo.  In a production system, you
; probably don't want to have the demo there.
;
include => demo

;
; An extension like the one below can be used for FWD, Nikotel, sipgate etc.
; Note that you must have a [sipprovider] section in sip.conf
;
;exten => _41X.,1,Dial(SIP/${EXTEN:2}@sipprovider,,r)

; Real extensions would go here. Generally you want real extensions to be
; 4 or 5 digits long (although there is no such requirement) and start with a
; single digit that is fairly large (like 6 or 7) so that you have plenty of
; room to overlap extensions and menu options without conflict.  You can alias
; them with names, too, and use global variables

;add for useasp test
exten => 8101,1,Dial(MGCP/aaln/1@dut1-112233.sh.useasp.net)
exten => 8102,1,Dial(MGCP/aaln/2@dut1-112233.sh.useasp.net)

exten => 8888,1,Dial(MGCP/aaln/1@jerry-pc)
exten => 8899,1,Dial(MGCP/aaln/1@lc-pc)

exten => 11112,1,Dial(SIP/11112)
exten => 11111,1,Dial(SIP/11111)

;exten => 6245,hint,SIP/Grandstream1&SIP/Xlite1(Joe Schmoe) ; Channel hints for presence
;exten => 6245,1,Dial(SIP/Grandstream1,20,rt)   ; permit transfer
;exten => 6245,n(dial),Dial(${HINT},20,rtT)     ; Use hint as listed
;exten => 6245,n,Voicemail(6245,u)              ; Voicemail (unavailable)
;exten => 6245,s+1,Hangup                       ; s+1, same as n
;exten => 6245,dial+101,Voicemail(6245,b)       ; Voicemail (busy)
;exten => 6361,1,Dial(IAX2/JaneDoe,,rm)         ; ring without time limit
;exten => 6389,1,Dial(MGCP/aaln/1@192.168.0.14)
;exten => 6390,1,Dial(JINGLE/caller/callee) ; Dial via jingle using labels
;exten => 6391,1,Dial(JINGLE/asterisk@digium.com/mogorman@astjab.org) ;Dial via jingle using asterisk as the transport and calling mogorman.
;exten => 6394,1,Dial(Local/6275/n)             ; this will dial ${MARK}

;exten => 6275,1,Gosub(stdexten,s,1(6275,${MARK}))
                                                ; assuming ${MARK} is something like DAHDI/2
;exten => 6275,n,Goto(default,s,1)              ; exited Voicemail
;exten => mark,1,Goto(6275,1)                   ; alias mark to 6275
;exten => 6536,1,Gosub(stdexten,s,1(6236,${WIL}))
                                                ; Ditto for wil
;exten => 6536,n,Goto(default,s,1)              ; exited Voicemail
;exten => wil,1,Goto(6236,1)

;If you want to subscribe to the status of a parking space, this is
;how you do it. Subscribe to extension 6600 in sip, and you will see
;the status of the first parking lot with this extensions' help
;exten => 6600,hint,park:701@parkedcalls
;exten => 6600,1,noop
;
; Some other handy things are an extension for checking voicemail via
; voicemailmain
;
;exten => 8500,1,VoicemailMain
;exten => 8500,n,Hangup
;
; Or a conference room (you'll need to edit meetme.conf to enable this room)
;
;exten => 8600,1,Meetme(1234)
;
; Or playing an announcement to the called party, as soon it answers
;
;exten = 8700,1,Dial(${MARK},30,A(/path/to/my/announcemsg))
;

; example of a compartmentalized company called "acme"


[root@sipserver ~]# asterisk 启用

[root@sipserver ~]# asterisk –r (进入asterisk的cli)
Asterisk 1.6.0.1, Copyright (C) 1999 - 2008 Digium, Inc. and others.
Created by Mark Spencer <markster@digium.com>
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type 'core show license' for details.
=========================================================================
Connected to Asterisk 1.6.0.1 currently running on sipserver (pid = 17802)
Verbosity is at least 3
sipserver*CLI>
sipserver*CLI> restart now(重启 Server)
sipserver*CLI> mgcp show endpoints

Asterisk安装配置(转)

LC 2015-10-14 Networking

Asterisk安装
(红色字体部分为需要键入或修改的部分)

下载准备
系统环境:

    Linux CentOS 5.0,安装开发工具以及开发库。
    Asterisk 源代码包 asterisk-1.6.1.20.tar.gz,版本:1.6.1.20。
    SIP 软电话使用 eyebeam 版本:1.5.8。
1. 切换用户(需要输入管理员密码),执行
su root
2. 进入源码包存放文件夹
[root@asterisk-test1 ~]#cd /usr/local/src
3. 下载
[root@asterisk-test1 ~]#wget http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-1.6.1.20.tar.gz

编译安装
1.解压源代码包
[root@asterisk-test1 ~]# tar -zxvf asterisk-1.6.1.20.tar.gz
2.进入包目录
[root@asterisk-test1 ~]# cd asterisk-1.6.1.20
3.环境检测和预配置
[root@asterisk-test1 asterisk-1.4.5]# ./configure
(其实这样直接进行configure并非十分规范。应当先使用“./configure –help”命令来查看一些可用的选项和参数,然后根据实际情况才进行定制操作。)当环境预检测和预配置工作做完时,最后会显示以上反馈信息。并且建立好Makefile。
注意:系统如果缺少安装必须的包,此步骤可能会出现configure: error错误,解决方案见后文可能遇到的问题
---------------------------------------------------------------
configure: creating ./config.status
config.status: creating build_tools/menuselect-deps
config.status: creating makeopts
config.status: creating channels/h323/Makefile
config.status: creating include/asterisk/autoconfig.h
.$$$$$$$$$$$$$$$=..
.$7$7.. .7$$7:.
.$$:. ,$7.7
.$7. 7$$$$ .$$77
..$$. $$$$$ .$$$7
..7$ .?. $$$$$ .?. 7$$$.
$.$. .$$$7. $$$$7 .7$$$. .$$$.
.777. .$$$$$$77$$$77$$$$$7. $$$,
$$$~ .7$$$$$$$$$$$$$7. .$$$.
.$$7 .7$$$$$$$7: ?$$$.
$$$ ?7$$$$$$$$$$I .$$$7
$$$ .7$$$$$$$$$$$$$$$$ $$$.
$$$ $$$$$$7$$$$$$$$$$$$ .$$$.
$$$ $$$ 7$$$7 .$$$ .$$$.
$$$$ $$$$7 .$$$.
7$$$7 7$$$$ 7$$$
$$$$$ $$$
$$$$7. $$ (TM)
$$$$$$$. .7$$$$$$ $$
$$$$$$$$$$$$7$$$$$$$$$.$$$$$$
$$$$$$$$$$$$$$$$.
configure: Package configured for:
configure: OS type : linux-gnu
configure: Host CPU : i686
---------------------------------------------------------------
4.清除陈旧的已编译文件
[root@asterisk-test1 asterisk-1.4.5]# make clean
5.重新编译 程序
[root@asterisk-test1 asterisk-1.4.5]# make
编译完成后会显示以下反馈提示信息,提示用户进行下一步可选的操作。
---------------------------------------------------------------
+--------- Asterisk Build Complete ---------+
+ Asterisk has successfully been built, and +
+ can be installed by running: +
+ +
+ make install +
+-------------------------------------------+
这里提示用户下一步可以使用“make install”命令,来进行安装了。
---------------------------------------------------------------
6.安装Asterisk 程序
[root@asterisk-test1 asterisk-1.4.5]# make install
当安装完成后就会显示以下反馈提示信息,提示用户进行进一步可选的操作。
---------------------------------------------------------------
+---- Asterisk Installation Complete -------+
+ +
+ YOU MUST READ THE SECURITY DOCUMENT +
+ +
+ Asterisk has successfully been installed. +
+ If you would like to install the sample +
+ configuration files (overwriting any +
+ existing config files), run: +
+ +
+ make samples +
+ +
+----------------- or ---------------------+
+ +
+ You can go ahead and install the asterisk +
+ program documentation now or later run: +
+ +
+ make progdocs +
+ +
+ **Note** This requires that you have +
+ doxygen installed on your local system +
+-------------------------------------------+
这里提示用户还能够有2种可选的操作分别是通过“make samples”来安装配置模版,以及通过“make progdocs”来安装一些程序文档。
---------------------------------------------------------------
7.安装配置模版:
[root@asterisk-test1 asterisk-1.4.5]# make samples
通过这个命令会安装Asterisk的配置文件模版,当然不会有强大的现成的配置,但确实是相当有帮助的,是配置过程中的重要参考。
8.还可以安装网页语音信箱:(这里暂时没有用到,可以不安装)
[root@asterisk-test1 asterisk-1.4.5]# make webvmail
安装页面语音信箱,会试图和Apache这种网站服务进行配合,当然还需要许多定制配置。这里暂时不会用到,但还是觉得应该提一下。
---------------------------------------------------------------
+--------- Asterisk Web Voicemail ----------+
+ +
+ Asterisk Web Voicemail is installed in +
+ your cgi-bin directory: +
+ /var/www/cgi-bin
+ IT USES A SETUID ROOT PERL SCRIPT, SO +
+ IF YOU DON'T LIKE THAT, UNINSTALL IT! +
+ +
+ Other static items have been stored in: +
+ /var/www/html
+ +
+ If these paths do not match your httpd +
+ installation, correct the definitions +
+ in your Makefile of HTTP_CGIDIR and +
+ HTTP_DOCSDIR +
+ +
+-------------------------------------------+
---------------------------------------------------------------
编辑Asterisk 的配置文件
Asterisk 的体系比较巨大,目前只是稍微的了解一下,所以只是做了最最最简单的测试配置,为了通过SIP协议使两个终端注册上来并互相呼叫通话而已,因此配置相当有 限,仅仅是为了初步的测试而已。还有一个地方要注意的是在Asterisk配置文件中的注释符是采用“;”分号的,而不是其他符号。
1.编辑Asterisk 的主配置文件:
[root@asterisk-test1 ~]# vi /etc/asterisk/asterisk.conf
主配置文件是Asterisk的关键部分,这个主配置文件大多数都是为Asterisk指定了环境、调用的路径。一般情况下不需要去改动它,这里贴出来先看看。
---------------------------------------------------------------
[directories]
小节directories主要记录Asterisk的几个重要调用路径
astetcdir => /etc/asterisk
指定了配置文件路径。
astmoddir => /usr/lib/asterisk/modules
指定了模块调用路径。
astvarlibdir => /var/lib/asterisk
astdatadir => /var/lib/asterisk
指定了本地数据库以及一些重要相关部件的路径。
astagidir => /var/lib/asterisk/agi-bin
指定了AGI程序的调用路径。
astspooldir => /var/spool/asterisk
指定了呼叫信息记录存放的路径。
astrundir => /var/run
指定了PID文件路径。
astlogdir => /var/log/asterisk
指定了日志路径。
;[options]
;internal_timing = yes
;systemname = my_system_name ; prefix uniqueid with a system name for global uniqueness issues
; Changing the following lines may compromise your security.
;[files]
;astctlpermissions = 0660
;astctlowner = root
;astctlgroup = apache
;astctl = asterisk.ctl
小节options中记录的都是一些可选的设置信息,务必要根据实际情况修改,这里我就先不做变动了。
---------------------------------------------------------------
2.配置SIP 对象配置文件:
[root@asterisk-test1 ~]# vi /etc/asterisk/sip.conf
---------------------------------------------------------------
;
; SIP Configuration example for Asterisk
;
; Syntax for specifying a SIP device in extensions.conf is
; SIP/devicename where devicename is defined in a section below.
;
; You may also use
; SIP/username@domain to call any SIP user on the Internet
; (Don't forget to enable DNS SRV records if you want to use this)
;
; If you define a SIP proxy as a peer below, you may call
; SIP/proxyhostname/user or SIP/user@proxyhostname
; where the proxyhostname is defined in a section below
;
; Useful CLI commands to check peers/users:
; 这里注释的部分中还提供一些关于SIP部分的调试命令。用户将可以在Asterisk控制台当中使用。
;
; sip show peers Show all SIP peers (including friends)
显示所有的SIP对端,包括友端。
; sip show users Show all SIP users (including friends)
显示所有的SIP用户端,包括友端。
; sip show registry Show status of hosts we register with
显示所有注册主机的信息。
; sip debug Show all SIP messages
显示所有SIP消息。
;
; reload chan_sip.so Reload configuration file
Active SIP peers will not be reconfigured
重新载入SIP的配置文件(也可以通过“sip reload”来实现),而已在线的活动用户将不会受到影响。
以下就是SIP配置文件中的定义小节了,每个小节都由[小节名]带起来一段。一个小节就可以是一套独立的配置信息,多个小节可以使得Asterisk同时 拥有并且运行好几套配置,为不同的需求和对象组进行服务。这里我已经删去很多默认的配置,只留下一些清洗简短地条目做做说明。
[general]
这段默认的小节名就是“general”。直到下一个小节名出线,这些都是“general”小节的配置内容。与其他不同的是“general”小节是 sip.conf配置文件中的“全局配置”段,也就是说其他的小节没有明确定义的、缺省的属性及配置项都将继承参考该段内的配置。
context=default ; Default context for incoming calls
此项指定该配置段将在拨号规则文件当中(extensions.conf)使用的哪一套拨号规则。如这里的“default”就是对应指定了 extensions.conf文件中的[default]段的拨号规则。

extension.conf拨号配置文件中也可以同时定义不同的段。
allowguest=yes ; Allow or reject guest calls (default is
yes)
allowoverlap=yes ; Disable overlap dialing support.
(Default is yes)
videosupport=yes ;支持视频传输(如果要支持视频general小节一定要将此行注;释去掉,否则视频无法传输)
bindport=5060 ; UDP Port to bind to (SIP standard port is 5060)
; bindport is the local UDP port that Asterisk will listen on
指定了Asterisk对SIP协议的监听端口,默认为标准的5060,并且这个端口是UDP端口。
bindaddr=0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all)
指定了Asterisk监听SIP协议的网络接口,这里设定为系统上全部的网络接口。
srvlookup=yes ; Enable DNS SRV lookups on outbound calls
设定启用域名检索功能。在针对一些IP不确定但是域名确定的对象时候,可以在配置当中直接写入对象的域名,然后Asterisk遇到这种情况就会去DNS解析。否则,将不会解析。
以下为设定编解码部分了
disallow=all ; First disallow all codecs
首先关闭掉所有编解码。
allow=g729
然后启用G.729的编解码。先全部关闭再开启指定编解码的原因是要明确指定Asterisk使用的编解码。这里也可以允许多个编解码,然后在呼叫过程中终端就会进行编解码协商,这里我先指定好就是用G.729的编解码。
用户定义小节:以下就是自定义的SIP配置段了。
[9001] ;定义了名字为“9001”的小节
videosupport=yes ;支持视频
type=friend ;指定类型为Friend“友端”,即可以对Asterisk进行呼叫也可以被
;Asterisk 呼叫的这种双向类型终端。其他的还有Peer“对端”,
;即只能作为被Asterisk呼叫的类型终端。以及还有
;User“用户端”,即只能作为呼叫Asterisk的类型终端。
username=9001 ;指定该对象的用户名
secret=9001 ;指定该对象的密码
host=dynamic ;指定终端主机位置。这里可以取2种值:
;static“静态”表示服务的终端对象的IP是固定已知的;
;dynamic“动态”表示服务的终端对象IP是动态的不确定的,
;每次要联系Asterisk的话就必须要注册上来。
context=demo ;指定该段内的对象所使用的拨号规则,全部对应 extensions.conf
;文件中的[demo]小节内定义的规则
disallow=all ;首先关闭掉所有编解码
allow=h264,g729 ;然后启用H.264(视频)和G.729(音频)的编解码。
;先全部关闭再开启指定编解码的原因是要明确指定Asterisk 使用的编
;解码。这里允许多个编解码,然后在呼叫过程中终端就会进行编解码协
;商
dtmfmode=rfc2833 ;Set default dtmfmode for sending DTMF. Default: rfc2833
; Other options:
; info : SIP INFO messages (application/dtmf-relay)
; shortinfo : SIP INFO messages (application/dtmf)
;inband:Inband audio (requires 64 kbit codec-alaw, ulaw)
; auto : Use rfc2833 if offered, inband otherwise
canreinvite=no ;设定是否允许终端发起重新邀请。大体上来讲,终端从开始呼叫直到切
;断,当中第一次邀请对方进行呼叫请求之后的任何请求动作都视为“重
;新邀请”, 一般都对这种行为做到严格控制而设定为no
maxcallbitrate=384; Maximum bitrate for video calls (default 384 kb/s)
; Videosupport and maxcallbitrate is settable
; for peers and users as well
[9002] ;定义了名字为“9002”的小节
videosupport=yes
第8页
type=friend
username=9002
secret=9002
host=dynamic
context=demo
disallow=all
allow=h264,g729
dtmfmode=rfc2833
canreinvite=no
maxcallbitrate=384
--------------------------------------------------------------
3.配置拨号规则配置文件
[root@asterisk-test1 ~]# vi /etc/asterisk/extensions.conf
---------------------------------------------------------------
配置方式也是同样,通过定义每一个小节,再在每一个小节中定义详细的属性。
这里比较重要的是“general”和“globals”这两个默认就有的小节,也是起到“全局属性”的作用,请根据实际情况确定,但请不要删除这两个小节。其他的小节都是可以订制、删除修改的。
[general]
static=yes
writeprotect=no
autofallthrough=no
clearglobalvars=no
priorityjumping=no
[globals]
CONSOLE=Console/dsp ; Console interface for demo
IAXINFO=guest ; IAXtel username/password
TRUNK=Zap/g2 ; Trunk interface
TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0)
在“demo”中自定义一个简单的拨号规则,与sip.conf里面的context项中指定的规则小节名对应。
[demo]
exten => _9.,1,Dial(SIP/${EXTEN},20,r)
说明:
(1)规则就一条,使得9001和9002可以互相拨打。当中的格式简要讲述一下。更多的请参考Asterisk的手册,这里不详细展开。
(2)开头部分“exten =>”表示,也可以用“exten =”表示。并且在一个小节内可以定义多条exten语句。
(3)之后的“_9”表示匹配上所有“9”开头的拨号,“.”表示不限制长度的任意字符。
(4)然后的“1”表示优先级,我喜欢称作为“执行次序”。“1”表示第一步执行的意思,如果后续还需要执行其他动作的话,可以继续写多条exten语句,并且用递增执行次序依次设计下去。
(5)接着的“Dail()”表示“执行动作”,这里是表示拨号的执行动作。更规范的说,这个是APP应用程序。
(6)括号当中又分成3个部分。第一个SIP表示拨号动作中拨向的通道是SIP协议的通道。${EXTEN}则一个变量,其值就是用户实际拨打的号码。如果你拨打9001那么${EXTEN}的值就是
9001。
(7)括号内的“20”,表示等待时间单位秒,如果有多个执行次序,即一组拨号规则的话,如果过了20秒,就跳跃执行次序(跳跃的幅度是101个优先级)。
(最后的“r”表示强行播放振铃。在拨打对方等待对方接通的时候,就能听到回振铃音。
---------------------------------------------------------------
对asterisk 服务的操作
1.手动启动Asterisk
[root@asterisk-test1 ~]# /usr/sbin/safe_asterisk
也可运行[root@asterisk-test1 ~]# asterisk -gcrvvvvvv直接启动后连接到Asterisk
控制台
注意,启动脚本是“safe_asterisk”,当启动起来后察看进程也能看到这个名字的进程。
不同系统路径可能不一样,如果提示找不到命令可运行find / -name safe_asterisk 进行查找在Ubuntu系统中可能会出现sh: Syntax error: Bad fd number 错误,解决方案见后文可能遇到的问题
2.查看Asterisk 进程
[root@asterisk-test1 ~]# ps -A|grep asterisk
---------------------------------------------------------------
2454 pts/1 00:00:00 safe_asterisk
2459 pts/1 00:00:14 asterisk
---------------------------------------------------------------
当Asterisk正常启动后,应该可以看到这两个进程。
3.关闭Asterisk 进程
这种方式比较土,比较不建议采用。
[root@asterisk-test1 ~]# killall safe_asterisk
[root@asterisk-test1 ~]# killall asterisk
4.也可以通过/etc/init.d/的方式对服务进行操作
[root@asterisk-test1 init.d]# service asterisk stop
Shutting down asterisk: Asterisk ended with exit status 0
Asterisk shutdown normally.
[ OK ]
[root@asterisk-test1 init.d]# service asterisk start
Starting asterisk: [ OK ]
默认情况下1.4.5版本的Asterisk会自动安装启动脚本,但是请务必确认Asterisk执行路径。
如之前我不能使用service脚本命令就是因为路径不对:
[root@asterisk-test1 init.d]# service asterisk stop
ERROR: /usr/sbin/asterisk not found
请确认Asterisk执行路径
[root@asterisk-test1 ~]# vi /etc/init.d/asterisk
---------------------------------------------------------------
# Use this option to specify a different configuration directory
AST_CONFIG=/etc/asterisk
指定Asterisk程序对配置文件连接的路径。
# Installation directory
AST_SBIN=/usr/local/asterisk/sbin
这里就是指定Asterisk程序的执行路径。
# Uncomment the following and set them to the user/groups that you
# want to run Asterisk as. NOTE: this requires substantial work to
# be sure that Asterisk's environment has permission to write the
# files required for its operation, including logs, its comm
# socket, the asterisk database, etc.
#AST_USER="asterisk"
#AST_GROUP="asterisk"
这里就是指定Aseterisk的运行用户。为了让系统更加的安全,自己添加Asterisk运行用户
和组,并让Asterisk指定它。
---------------------------------------------------------------
控制台操作
1.进入Asterisk 监控台
[root@asterisk-test1 ~]# /usr/sbin/asterisk -crvvvvvvv
控制台是对Asterisk进行调试的重要工具,在里面可以看到重要的信息,已经可以对
Asterisk采取必要的操作。
---------------------------------------------------------------
Asterisk 1.4.5, Copyright (C) 1999 - 2007 Digium, Inc. and others.
Created by Mark Spencer <markster@digium.com>
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for
details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type 'core show license' for details.
=========================================================================
== Parsing '/etc/asterisk/asterisk.conf': Found
== Parsing '/etc/asterisk/extconfig.conf': Found
Connected to Asterisk 1.4.5 currently running on asterisk-test1 (pid = 2459)
Verbosity is at least 14
-- Remote UNIX connection
asterisk-test1*CLI>
这个就是控制台的命令提示符。
---------------------------------------------------------------
2.察看Asterisk 命令的用法
[root@asterisk-test1 ~]# /usr/sbin/asterisk -help
---------------------------------------------------------------
Asterisk 1.4.5, Copyright (C) 1999 - 2007, Digium, Inc. and others.
Usage: asterisk [OPTIONS]
语法: asterisk [选项]
Valid Options:
可用选项(这里只交代一些常用的)
-V Display version number and exit
显示版本号以及各种数据信息,可以跟加多个v参数以显示更加详细信
息。
-C <configfile> Use an alternate configuration file
连接指定配置文件。注意这个C是大写的。
-c Provide console CLI
提供命令行接口。进控制台当然要使用命令行,所以这个参数是必要的。
注意这个c是小写的。
-r Connect to Asterisk on this machine
连接服务器本地的Asterisk。
-R Connect to Asterisk, and attempt to reconnect if
disconnected
连接到Asterisk,并且在断开连接的时候尝试重新连接。
-x <cmd> Execute command <cmd> (only valid with -r)
与-r参数连用,后面跟上命令名称,可以执行命令。比如asterisk
-rx "restart now"。
---------------------------------------------------------------
3.一些控制台经常使用的命令:
---------------------------------------------------------------
sip reload 重新载入sip.conf配置文件。
extensions reload 重新载入extensions.conf配置文件。
sip show peers 察看SIP对端,友端对象信息。
sip show users 察看SIP用户端,友端对象信息。
等等...还有很多,这里就不详细讲了,可以在控制台中输入help查看更多命令
---------------------------------------------------------------
测试
使用eyebeam注册9001和9002这两个SIP用户到Asterisk上去,并且使其互相呼叫并通话。
1.首次注册成功
---------------------------------------------------------------
[Oct 25 10:39:47] NOTICE[2490]: chan_sip.c:14586 handle_request_subscribe:
Received SIP subscribe for peer without mailbox: 9002
这里表示接收到SIP用户9002的注册信息。
[Oct 25 10:40:26] NOTICE[2490]: chan_sip.c:14586 handle_request_subscribe:
Received SIP subscribe for peer without mailbox: 9002
[Oct 25 10:41:35] NOTICE[2490]: chan_sip.c:14586 handle_request_subscribe:
Received SIP subscribe for peer without mailbox: 9001
这里表示接收到SIP用户9001的注册信息。
[Oct 25 10:41:44] NOTICE[2490]: chan_sip.c:14586 handle_request_subscribe:
Received SIP subscribe for peer without mailbox: 9002
[Oct 25 10:43:32] NOTICE[2490]: chan_sip.c:14586 handle_request_subscribe:
Received SIP subscribe for peer without mailbox: 9001
---------------------------------------------------------------
2.检查注册状况:
asterisk-test1*CLI> sip show peers
---------------------------------------------------------------
Name/username Host Dyn Nat ACL Port Status
9002/9002 192.168.0.20 D N 17900
Unmonitored
用户9002已经注册上来,并且主机地址为192.168.0.20,发起端口是17900,非监视。
9001/9001 192.168.0.199 D N 35028
Unmonitored
用户9001已经注册上来,并且主机地址为192.168.0.199,发起端口是35028,非监视。
2 sip peers [Monitored: 0 online, 0 offline Unmonitored: 2 online, 0
offline]
提示2个SIP对端在线,处于非监视状态。
asterisk-test1*CLI>
---------------------------------------------------------------
3.从控制台中察看该2 个用户的正常注册信息:
---------------------------------------------------------------
[Oct 25 11:13:50] NOTICE[2490]: chan_sip.c:14586 handle_request_subscribe:
-- Unregistered SIP '9001'
-- Registered SIP '9001' at 192.168.0.199 port 57090 expires 60
用户9001从地址192.168.0.199端口57090登入,超时时间为60秒。
-- Saved useragent "eyeBeam release 1004p stamp 31962" for peer 9001
用户代理程序是eyeBeam。
-- Unregistered SIP '9002'
-- Registered SIP '9002' at 192.168.0.20 port 59236 expires 60
用户9002从地址192.168.0.20端口59236登入,超时时间为60秒。
-- Saved useragent "eyeBeam release 1004p stamp 31962" for peer 9002
用户代理程序是eyeBeam。
---------------------------------------------------------------
4.成功呼叫接通:
从9001呼叫9002,并且我这里做一些简单的信息分析。
---------------------------------------------------------------
-- Executing [9002@demo:1] Dial("SIP/9001-09a56000", "SIP/9002|20|r"
in new stack
执行呼叫,拨打9002。
-- Called 9002
被叫方9002。
-- SIP/9002-09a17100 is ringing
通过SIP通道呼叫9002,并且正在震铃。
-- SIP/9002-09a17100 answered SIP/9001-09a56000
SIP的9002终端应答了SIP的9001终端。
-- Packet2Packet bridging SIP/9001-09a56000 and SIP/9002-09a17100
在SIP9001和SIP9002之间建立了P2P通道。
== Spawn extension (demo, 9002, 1) exited non-zero on 'SIP/9001-
09a56000'
9001挂断。
---------------------------------------------------------------
从9002呼叫9001,并且我这里做就不重复做相同的分析了。
---------------------------------------------------------------
-- Executing [9001@demo:1] Dial("SIP/9002-09a54548", "SIP/9001|20|r"
in new stack
-- Called 9001
-- SIP/9001-09a56000 is ringing
-- SIP/9001-09a56000 answered SIP/9002-09a54548
-- Packet2Packet bridging SIP/9002-09a54548 and SIP/9001-09a56000
== Spawn extension (demo, 9001, 1) exited non-zero on 'SIP/9002-
09a54548'
9001挂断。
---------------------------------------------------------------
5.视频测试
由于我们配置的视频编码只有H.264所以客户端必须有H.264编码,所以测试前必须检查
eyeBeam是否支持H.264(在高级设置中),如果不支持可以将前面配置账号的地方改为客户端支
持的编码,例如allow=h263,g729
可能遇到的问题
问题1:运行./configure时出现错误:
 错误:
configure: error: no acceptable C compiler found in $PATH
原因:缺少gcc cpp glibc-headers glibc-devel glibc-kernheaders 包
解决:Centos系统运行: yum install gcc
Ubuntu系统运行:apt-get install gcc
注:Ubuntu系统安装用apt-get install,只需将yum换为ap-get,下面就不再列出
 错误:
configure: error: C++ preprocessor "/lib/cpp" fails sanity check
原因:缺少gcc-c++ libstdc++-devel 包
解决:Centos系统运行: yum install gcc-c++
Ubuntu系统运行:apt-get install gcc-c++
 错误:
configure: error: *** termcap support not found
原因:缺少libtermcap-devel 包
解决:Centos系统运行: yum install libtermcap-devel
Ubuntu系统运行:apt-get install libtermcap-devel
问题2:Ubuntu系统中运行safe_asterisk时出现 sh: Syntax error: Bad fd number
原因:在Ubuntu系统中sh 是个符号连接! dash可能对某些符号无法解释,尽量用bash
解决:将safe_asterisk脚本文件中的第一行 #!/bin/sh 改为 #!/bin/bash
问题3:呼叫失败。提示为在extension中没有“Dail”这个应用程序。
原因:在extensions.conf中“Dial”误写成“Dail”。
---------------------------------------------------------------
[Oct 25 10:21:01] WARNING[3363]: pbx.c:1797 pbx_extension_helper: No
application 'Dail' for extension (demo, 9002, 1)
== Spawn extension (demo, 9002, 1) exited non-zero on 'SIP/9001-
09a547d0'
---------------------------------------------------------------
问题4:呼叫失败(但是反向呼叫却可以成功。)
原因:用户9001和9002的编码不统一,在sip.conf中强行指定使用相同编解码后呼叫以及通
话功能正常。
---------------------------------------------------------------
-- Executing [9002@demo:1] Dial("SIP/9001-09a17100", "SIP/9002|20|r"
in new stack
-- Called 9002>
-- SIP/9002-09a56000 is circuit-busy
== Everyone is busy/congested at this time (1:0/1/0)
[Oct 25 11:25:10] WARNING[2490]: chan_sip.c:12428 handle_response: Remote
host can't match request BYE to call
'768cfe882651862a21c804946cb8dc43@192.168.0.148'. Giving up.
---------------------------------------------------------------
问题5:电话单向打通,并且提示使用未知编码。
原因:用户9001和9002的编码不统一,在sip.conf中强行指定使用相同编解码后呼叫以及通
话功能正常。
---------------------------------------------------------------
-- Executing [9001@demo:1] Dial("SIP/9002-09a17100", "SIP/9001|20|r"
in new stack
-- Called 9001>
-- SIP/9001-09a56000 is ringing
[Oct 25 11:22:25] WARNING[2490]: channel.c:2947 set_format: Unable to find
a codec translation path from g729 to gsm
---------------------------------------------------------------
关键提示:找不到一个能够将G.729转成GSM的编解码途径。
[Oct 25 11:22:25] WARNING[2490]: channel.c:2947 set_format: Unable to find
a codec translation path from g729 to gsm
-- SIP/9001-09a56000 answered SIP/9002-09a17100
-- Packet2Packet bridging SIP/9002-09a17100 and SIP/9001-09a56000
-- Started music on hold, class 'default', on SIP/9001-09a56000
[Oct 25 11:22:35] WARNING[3892]: channel.c:2947 set_format: Unable to find
a codec translation path from g729 to slin
[Oct 25 11:22:35] WARNING[3892]: res_musiconhold.c:247 ast_moh_files_next:
Unable to open file '/var/lib/asterisk/moh/fpm-calm-river': No such file
or directory
-- Stopped music on hold on SIP/9001-09a56000
[Oct 25 11:22:43] NOTICE[3892]: rtp.c:1274 ast_rtp_read: Unknown RTP codec
126 received from '192.168.0.20'
---------------------------------------------------------------
关键提示:从192.168.0.20上收到未知的RTP编码。
[Oct 25 11:22:50] NOTICE[3892]: rtp.c:1274 ast_rtp_read: Unknown RTP codec
126 received from '192.168.0.20'
Internal RTCP NTP clock skew detected: lsr=2324207771, now=2324324243,
dlsr=176881 (2:698ms), diff=60409
Internal RTCP NTP clock skew detected: lsr=2324207771, now=2324534751,
dlsr=401014 (6:118ms), diff=74034
Internal RTCP NTP clock skew detected: lsr=2324535463, now=2324702191,
dlsr=223805 (3:414ms), diff=57077
---------------------------------------------------------------
根据关键提示,很明显,是和编解码有关的问题。

VNC server 安装配置详解

LC 2015-10-13 Networking

一、安装相应桌面环境与vnc服务端和客户端:

# yum groupinstall "GNOME Desktop Environment"(CentOS 5.x安装GNOME桌面环境)
# yum groupinstall "X Window System" "Desktop"(CentOS 6.x安装GNOME桌面环境)
# yum groupinstall Xfce(CentOS安装Xfce桌面环境,可选)
# yum install vnc-server vnc* (CentOS 5.x里)
# yum install tigervnc-server tigervnc (CentOS 6.x里)

说明:Xfce与KDE,Gnome都是图形桌面环境,其特点是占用资源更小资源占用情况大致为:Gnome>KDE>Xfce。具体情况与版本有关。一般版本越新,资源占用越大。

二、VNC的启动和重启:
# /etc/init.d/vncserver restart
注:有时候上面的命令启动会报错,直接运行就可以:
# vncserver
注:关闭具体的vncserver命令:vncserver -kill :1 vncserver -kill :2

第一次启动会提示需要用户名和密码,设置即可:
[root@localhost /]$ vncserver
You will require a password to access your desktops.
Password:      输入vnc 连接密码
Verify:        确认vnc密码

三、设置远程登陆到gnome桌面的配置:
# vim /etc/sysconfig/vncservers(SUSE企业版不用配置此文件)
再最后面加入如下两行:

VNCSERVERS="1:root"
VNCSERVERARGS[1]="-geometry 1024x768 -alwaysshared -depth 24"

说明:

1、-alwaysshared表示同一个显示端口允许多用户同时登录 -depth代为色深,参数有8、16、24、32;
2、这里的“用户名”是指linux系统用户的名称;
3、上面三行中第一行是设定可以使用VNC服务器的帐号,可以设定多个,但中间要用空格隔开。注意前面的数字“1”或是“2”,当你要从其它电脑来VNC服务器时,就需要用IP:1这种方法,而不能直接用IP。如假定你的VNC服务器IP是192.168.1.100,那想进入VNC服务器,并以peter用户登录时,需要在vncviewer里输入IP的地方输入:192.168.1.100:1,如果是root,那就是192.168.1.100:2;
4、下面两行[1][2]最好与上面那个相对应,后面的800X600可以换成你电脑支持的分辨率。注意中间的”x”不是“*”,而是小写字母”x”。

四、设置vnc访问密码:
# vncpasswd
说明:这里是为上面的root远程用户配密码,所以在root账户下配;依次类推,为别的账户配密码,就要在别的账户下设密码。

五:修改远程桌面显示配置文件:
# vim /root/.vnc/xstartup

#!/bin/sh
# Uncomment the following two lines for normal desktop:
unset SESSION_MANAGER
exec /etc/X11/xinit/xinitrc
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
gnome-session & #set starting GNOME desktop
#startkde & #kde desktop
#twm & #Text interface
#/usr/bin/startxfce4
#exec /usr/bin/fluxbox

说明:
1、不修改此文件你看到的远程桌面很简单,相当于命令行操作,为了远程操作如同本地操作一样,务必参考以上方式进行修改;
2、只要你启用一次VNCserver,就能自动创建,方法如下:
# vncserver
通过上面的方法,就可以在用户家目录下的.vnc目录里创建xstartup文件。

六、vnc客户端登陆:
在vnc客户端中输入:服务器端IP:1 或 服务器端IP:2
如图所示:

 


iptables防火墙默认会阻止vnc远程桌面,所以需要在iptables允许通过。当你启动vnc服务后,你可以用netstat –tunlp命令来查看vnc服务所使用的端口,可以发现有5801,5901,6001等。使用下面命令开启这些端口:
# vim /etc/sysconfig/iptables
添加:
-A RH-Firewall-l-INPUT -p tcp -m tcp –dport 5801 -j ACCEPT
-A RH-Firewall-l-INPUT -p tcp -m tcp –dport 5901 -j ACCEPT
-A RH-Firewall-l-INPUT -p tcp -m tcp –dport 6001 -j ACCEPT
重启防火墙:
# /etc/init.d/iptables restart
或者直接关闭防火墙:
# /etc/init.d/iptables stop

七、开机自启动vncserver服务:
# chkconfig vncserver on

八、vnc的反向连接设置:

在大多数情况下,vncserver总处于监听状态,vnc client主动向服务器发出请求从而建立连接。然而在
一些特殊的场合,需要让vnc客户机处于监听状态,vncsrever主动向客户机发出连接请求,此谓vnc的
反向连接。
主要步骤:
a、启动vnc client,使vncviewer处于监听状态;
# vncviewer -listen
b、启动vncserver
# vncserver
c、在vncserver端执行vncconnect命令,发起server到client的请求;
# vncconnect -display :1 192.168.80.135

九、可能遇到的问题:

a、黑屏
在Linux里安装配置完VNC服务端,发现多用户登陆会出现黑屏的情况,具体的现象为:
客户端可以通过IP与会话号登陆进入系统,但登陆进去是漆黑一片,除了一个叉形的鼠标以外,伸手不见五指。

原因:用户的VNC的启动文件权限未设置正确。
解决方法:将黑屏用户的xstartup(一般为:/用户目录/.vnc/xstartup)文件的属性修改为755(rwxr-xr-x)。
完后杀掉所有已经启动的VNC客户端:
vncserver -kill :1
vncserver -kill :2 (注意:-kill与:1或:2中间有一空格)
最后重启vncserver服务即可! # /etc/init.d/vncserver restart

注意:vncserver只能由启动它的用户来关闭,即时是root也不能关闭其它用户开启的vncserver,
除非用kill命令暴力杀死进程。

b、Windown下如何登陆VNC Server
(1)从浏览器登录(浏览器需要安装JAVA支持库,作为java applet来实现,才能登录控制VNC服务器,可以yum install java*安装)
直接从浏览器中输入如下地址:

http://xxx.xxx.xxx.xxx:5801


(2)从VNC客户端登录
在windows上安装vnc客户端,然后输入xxx.xxx.xxx.xxx:x,连接登录。

备注:
a、输入的格式为IP:号码,号码要看你自己的配置而定。如192.168.80.128:1
b、登陆提示connection refused(10061),则是因为linux防火墙的问题,请检查防火墙设置。
c、后面的尾缀”:x”也是不能少的,要不然老提示failed to connect : connection refused (10061)

Linux网卡配置多个IPv6地址

LC 2015-10-12 IPv6

前面一篇文章介绍了<a target="_blank" href="http://manager.blog.useasp.net/archive/2015/10/11/Multiple-ip-address-bind-on-one-card-in-linux.aspx">如何给linux网卡配置多个ipv4地址</a>,这里将介绍Linux网卡配置多个IPv6地址

(这里以绑定IP到eth1为例,其它网卡的话修改相应的文件名即可)

/etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1 //绑定IP段的网卡名称
BOOTPROTO=static //协议为静态,用none也可以
ONBOOT=yes //开机启用此网卡
HWADDR=00:1c:49:18:32:6a //MAC地址
NETMASK=255.255.255.0
IPADDR=192.168.1.14
TYPE=Ethernet
USERCTL=no
PEERDNS=yes
IPV6INIT=yes
IPV6ADDR=fc00:502::c0a8:10e //IPv6 address
IPV6ADDR_SECONDARIES=fc00:502::c0a8:10f //second ipv6 address
IPV6PREFIX=64 //the prefix is 64
IPV6_DEFAULTGW=fc00:502::ca8:13 //default gateway

保存退出,然后重启网络:

[root@lc /]# service network restart

用ifconfig查看是否配置成功:

eth1      Link encap:Ethernet  HWaddr 00:1C:49:18:32:6A 
          inet addr:10.15.1.14  Bcast:10.15.1.255  Mask:255.255.255.0
          inet6 addr: fe80::021c:49ff:fe18:326a/64 Scope:Link
          inet6 addr: fc00:502::a0f:10e/64 Scope:Global
          inet6 addr: fc00:502::a0f:10f/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:75150 errors:0 dropped:0 overruns:0 frame:0
          TX packets:47345 errors:0 dropped:0 overruns:0 carrier:1
          collisions:0 txqueuelen:1000
          RX bytes:7195527 (6.8 MiB)  TX bytes:4920915 (4.6 MiB)
          Interrupt:66

 

 

LINUX一网卡多IP设置

LC 2015-10-11 Networking

方法1:少量IP手动绑定(这里以绑定IP到eth1为例,其它网卡的话修改相应的文件名即可)

1.复制ifcfg-eth1的网卡配置文件并改名为ifcfg-eth1:1

[root@lc /]# cp /etc/sysconfig/network-scripts/ifcfg-eth1 /etc/sysconfig/network-scripts/ifcfg-eth1:1

2.编辑ifcfg-eth1:1文件

[root@lc /]# vim /etc/sysconfig/network-scripts/ifcfg-eth1:0

DEVICE=”eth1:0″ //这里修改为eth1:0跟文件名保持一致
BOOTPROTO=”static” //协议为静态,用none也可以
HWADDR=”50:E5:49:18:32:6A″ //MAC地址
ONBOOT=”yes” //开机启用此网卡
IPADDR=192.168.1.10 //新绑定的IP
NETMASK=255.255.255.0 //子网掩码
GATEWAY=192.168.1.1 //网关

修改好后保存退出,然后启用这张网卡

[root@lc /]# ifup eth1:0

注:有人在这一步喜欢用service network restart重启网络,其实这是没必要的,只需要启用这张网卡就可以了

3.用ifconfig查看该网卡是否启动成功
[root@lc /]# ifconfig
eth1      Link encap:Ethernet  HWaddr 50:E5:49:18:32:6A 
          inet addr:192.168.1.9  Bcast:10.15.1.255  Mask:255.255.255.0
          inet6 addr: fe80::52e5:49ff:fe18:326a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:75150 errors:0 dropped:0 overruns:0 frame:0
          TX packets:47345 errors:0 dropped:0 overruns:0 carrier:1
          collisions:0 txqueuelen:1000
          RX bytes:7195527 (6.8 MiB)  TX bytes:4920915 (4.6 MiB)
          Interrupt:66

eth1:1    Link encap:Ethernet  HWaddr 50:E5:49:18:32:6A 
          inet addr:192.168.1.10  Bcast:10.15.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:66
[root@lc /]#

4. 然后再试ping 一下,如果能ping通的话,就可以了。

方法2:自动绑定一个IP段或多个IP段(同样这里以eth1为例,其它网卡的话修改相应的文件名即可)

1.新建ifcfg-eth1-range0文件(注意这里的文件名不要调换range的位置或写错单词,不然的话绑定的IP是不会生效的,如果你还有几段IP要绑定到eth1上的话,你可以再新建ifcfg-eth1-range1, ifcfg-eth1-range2等文件,不过这里要注意每个range文件中的定义的CLONENUM_START值不能重叠,不然的话会出问题。 )

[root@lc /]# /etc/sysconfig/network-scripts/ifcfg-eth1-range0

#写入以下内容

DEVICE=eth1 //绑定IP段的网卡名称
ONBOOT=yes //开机启用此网卡
BOOTPROTO=static //协议为静态
IPADDR_START=192.168.0.101 //网段的起始
IPIPADDR_END=192.168.0.120 //网段的截止IP
NETMASK=255.255.255.255 //子网掩码
CLONENUM_START=0 //这个数字是网卡别名的开始位置,比如这里的3是指eth1:0,并且会把IPADDR_START设置的IP192.168.0.101绑定到eth1:0上,以此类推
NO_ALIASROUTING=yes //这个参数的作用是数据包始终通过eth1进出,不走网卡别名(如eth1:0),设置这个参数可以加快路由的响应速度,所以强烈建议配置。

修改好后保存退出,然后重启网络:

[root@lc /]# service network restart

再测试一下,能ping就大功告成了。

这篇文章介绍了如果在一个linux网卡上配置多个ip地址,下面一篇将介绍一个网卡上配置多个ipv6地址

A sample of DHCPv6 server

LC 2015-10-10 IPv6

# for Server
authoritative;
ddns-updates on;
ddns-update-style interim;
do-forward-updates on;
#preferred-lifetime 86400;
#default-lease-time 86400;-valid-time-should-not-less-than-preferred;
preferred-lifetime 86400;
default-lease-time 86400;
#valid-lifetime 720;
#default-lease-time 86400;
#option 58 3600;
#option 59 4800;
#    server-preference 255;
#    renew-time 60;
#    rebind-time 90;
#    prefer-life-time 130;
#    valid-life-time 200;
#    allow rapid-commit;
#    option dns_servers 2000::2 ibm.com;
# T1, the delay before Renew
#  (default is 1/2 preferred lifetime)
#  (set to 1 hour)
#option dhcp-renewal-time 3600;
#option dhcp-renewal-time 50;

# T2, the delay before Rebind (if Renews failed)
#  (default is 3/4 preferred lifetime)
#  (set to 2 hours)
#option dhcp-rebinding-time 7200;
#option dhcp-rebinding-time 80;
<global>

 


# custom Option Definition
<option-def>

 

# Global Options
<global-options>


# Classes and groups
<sub-classes>

 

# local subnet - must declaration
#PACTINST_DHCP6_NETDETAILS
subnet6 fe80::/64 {
}
#subnet6 2006:200:2:2::100/128 {
subnet6 2006:200:2:2::0/64 {
#subnet6 2006:200:2::0/49 {
        range6 2006:200:2:2::10 2006:200:2:2::fff0;
#       Prefix6 2012:150:15:: 2012:150:15:fff0:: /64;
#       Prefix6 2000:2000:2000:: 2000:2000:2000:fff0:: /60;
        Prefix6 2020:2020:2020:: 2020:2020:2020:ff00:: /56;
#       Prefix6 2030:2030:: 2030:2030:ff00:: /48;
#       Prefix6 2050:2040:: 2050:2040:ff00:: /49;
        deny unknown-clients;
        option dhcp6.domain-search "shanghai.smcbb.net";
        option dhcp6.name-servers 2003:0:190::13;
}
<subnets>
<shared-networks>

<hosts>

DHCPv6 clients get the same IPv6 addresses

LC 2015-10-09 IPv6

DHCPv6总是给客户端分配一样的地址的问题,根据抓包分析,找到问题所在
1. CMTS发给dhcpv6 server的地址里面,relay头里面带的interface-id,填的都是同样的值 00000022
2. 根据itut的文档http://tools.ietf.org/html/draft-ietf-dhc-dhcpv6-ldra-03#page-6
         Servers MAY use the Interface-ID for parameter assignment policies.
   The format of the Interface-ID is outside the scope of this
   contribution.  The Interface-ID SHOULD be considered an opaque value,
   i.e. the server SHOULD NOT try to parse the contents of the
   Interface-ID option.  The LDRA SHOULD use the same Interface-ID value
   for a given interface, and this value SHOULD be retained across
   restarts.  This is because, if the Interface-ID changes, a server
   will not be able to use it reliably in parameter assignment policies.
3. 通过查看iscdhcpv6-src发现,根据interface-id去找cache的地址。造成客户端总是拿到同样的地址。
 
 
去isc的网站上看到,新版本解决了这个问题。请升级一下
 
1. cd /PATH/iscdhcpv6-src/
2. wget http://ftp.isc.org/isc/dhcp/4.2.4-P1/dhcp-4.2.4-P1.tar.gz
3. tar -zxvf dhcp-4.2.4-P1.tar.gz
4. mv /PATH/iscdhcpv6 /PATH/iscdhcpv6.old
5. ./configure --prefix=/PATH/iscdhcpv6
6. make
7. make install

And then restart DHCP server.

Installation and sample of Tcl/tk

LC 2015-10-08 Networking

1.Download the executable file from website and install it in windows system, eg: “http://globalfilesearch.com/download.aspx?path=virtualhosts.botik.ru/rented/botik/www/download/tcl_tk_for_win/ActiveTcl8.5.0.0-win32-ix86-93230.exe”
2.Run tclsh to execute commands, here is a sample which can telnet to the DUT and set some prameters.

package require Expect
set DUTIP 192.168.0.1
set Login admin
set Password 12345678
set logfile log.txt
set dis [open $logfile w+]

puts $dis "\n"
puts $dis "##############################"
puts $dis "##          Login           ##"
puts $dis "##############################"

log_file -open $dis
spawn Telnet $DUTIP
set console_id $spawn_id
expect "Enter user:"
send -i $console_id "$Login\r"
expect "Enter password:"
send -i $console_id "$Password\r"
expect "DUT>"
#send -i $console_id "help\r"
after 1000

puts $dis "\n"
puts $dis "##############################"
puts $dis "##          Status         ##"
puts $dis "##############################"
expect "DUT>"
send -i $console_id "status\r"
expect "DUT>"
send -i $console_id "ipcable\r"
expect "DUT>"
send -i $console_id "vendor\r"
after 500


puts $dis "\n"
puts $dis "##############################"
puts $dis "##        NATmapping        ##"
puts $dis "##############################"
expect "DUT> "
send -i $console_id "setfirewallengin 1\r"
puts firewallenable
expect "DUT>"
send -i $console_id "setnat 1\r"
puts "enable NAT"
after 500
expect "DUT>"
send -i $console_id "setnatmapping 1\r"
puts "enable mapping"
after 500
expect "DUT>"
send -i $console_id "natmapping add 172.16.1.200 192.168.0.35\r"
puts "add 1 mapping"
after 1000