GVKun编程网logo

python 模块之 ---- urllib2 模块详解(python的urllib2模块)

1

关于python模块之----urllib2模块详解和python的urllib2模块的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于ansible模块之copy模块详解、ansible模

关于python 模块之 ---- urllib2 模块详解python的urllib2模块的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于ansible 模块之 copy模块详解、ansible 模块之 cron模块详解、ansible 模块之 yum、pip、service、corn、user、group、freeswitch 模块之 event_socket等相关知识的信息别忘了在本站进行查找喔。

本文目录一览:

python 模块之 ---- urllib2 模块详解(python的urllib2模块)

python 模块之 ---- urllib2 模块详解(python的urllib2模块)

简介:
urllib2 是 python 的一个获取 url(Uniform Resource
Locators,统一资源定址器)的模块。它用 urlopen 函数的形式提供了一个非常简洁的接口。这使得用各种各样的协议获取 url 成为可能。它同时
也提供了一个稍微复杂的接口来处理常见的状况 - 如基本的认证,cookies,代理,等等。这些都是由叫做 opener 和 handler 的对象来处理的。
以下是获取 url 最简单的方式:
import urllib2
response = urllib2.urlopen(''http://python.org/'')
html = response.read()
许多 urlib2 的使用都是如此简单(注意我们本来也可以用一个以”ftp:”"file:” 等开头的 url 取代”HTTP” 开头的 url). 然
而,这篇教程的目的是解释关于 HTTP 更复杂的情形。HTTP 建基于请求和回应(requests &responses
)- 客户端制造请求服务器返回回应。urlib2 用代 表了你正在请求的 HTTP
request 的 Request 对象反映了这些。用它最简单的形式,你建立了一个 Request 对象来明确指明你想要获取的 url。调用 urlopen 函
数对请求的 url 返回一个 respons 对象。这个 respons 是一个像 file 的对象,这意味着你能用.read () 函数操作这个 respon 对象:
import urllib2
req = urllib2.Request(''http://www.voidspace.org.uk'')
response = urllib2.urlopen(req)
the_page = response.read()
注意 urlib2 利用了同样的 Request 接口来处理所有的 url 协议。例如,你可以像这样请求一个 ftpRequest:
req = urllib2.Request(''ftp://example.com/'')
对于 HTTP,Request 对象允许你做两件额外的事:第一,你可以向服务器发送数据。第二,你可以向服务器发送额外的信息(metadata),这些信息可以是关于数据本身的,或者是关于这个请求本身的–这些信息被当作 HTTP 头发送。让我们依次看一下这些。
数据:
有时你想向一个 URL 发送数据(通常这些数据是代表一些 CGI 脚本或者其他的 web 应用)。对于 HTTP,这通常叫做一个 Post。当你发送一个你
在网上填的 form(表单)时,这通常是你的浏览器所做的。并不是所有的 Post 请求都来自 HTML 表单,这些数据需要被以标准的方式 encode,然后
作为一个数据参数传送给 Request 对象。Encoding 是在 urlib 中完成的,而不是在 urlib2 中完成的。
import urllib
import urllib2
url = ''http://www.someserver.com/cgi-bin/register.cgi''
values = {''name'' : ''Michael Foord'',
          ''location'' : ''Northampton'',
          ''language'' : ''Python'' }
data = urllib.urlencode(values)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
the_page = response.read()
如果你不传送数据参数,urlib2 使用了一个 GET 请求。一个 GET 请求和 POST 请求的不同之处在于 POST 请求通常具有边界效应:它们以某种
方式改变系统的状态。(例如,通过网页设置一条指令运送一英担罐装牛肉到你家。)虽然 HTTP 标准清楚的说明 Post 经常产生边界效应,而 get 从不产生
边界效应,但没有什么能阻止一个 get 请求产生边界效应,或一个 Post 请求没有任何边界效应。数据也能被 url 自己加密(Encoding)然后通过一
个 get 请求发送出去。
这通过以下实现:
>>> import urllib2
>>> import urllib
>>> data = {}
>>> data[''name''] = ''Somebody Here''
>>> data[''location''] = ''Northampton''
>>> data[''language''] = ''Python''
>>> url_values = urllib.urlencode(data)
>>> print url_values
name=Somebody+Here&language=Python&location=Northampton
>>> url = ''http://www.example.com/example.cgi''
>>> full_url = url + ''?'' + url_values
>>> data = urllib2.open(full_url)
头:
我们将会在这里讨论一个特殊的 HTTP 头,来阐释怎么向你的 HTTP 请求中加入头。
有一些网站不希望被某些程序浏览或者针对不同的浏览器返回不同的版本。默认情况下,urlib2 把自己识别为 Python-urllib/x.y(这里的
xy 是 python 发行版的主要或次要的版本号,如,
Python-urllib/2.5),这些也许会混淆站点,或者完全不工作。浏览器区别自身的方式是通过 User-Agent 头。当你建立一个
Request 对象时,你可以加入一个头字典。接下来的这个例子和上面的请求一样,不过它把自己定义为 IE 的一个版本。
import urllib
import urllib2
url = ''http://www.someserver.com/cgi-bin/register.cgi''
user_agent = ''Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)''
values = {''name'' : ''Michael Foord'',
          ''location'' : ''Northampton'',
          ''language'' : ''Python'' }
headers = { ''User-Agent'' : user_agent }
data = urllib.urlencode(values)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
the_page = response.read()
Respons 同样有两种有用的方法。当我们出差错之后,看一下关于 info and geturl 的部分。
异常处理:
不能处理一个 respons 时,urlopen 抛出一个 urlerror(虽然像平常一样对于 python APIs,内建异常如,ValueError, TypeError 等也会被抛出。)
HTTPerror 是 HTTP URL 在特别的情况下被抛出的 URLError 的一个子类。
urlerror:
通常,urlerror 被抛出是因为没有网络连接(没有至特定服务器的连接)或者特定的服务器不存在。在这种情况下,含有 reason 属性的异常将被抛出,以一种包含错误代码和文本错误信息的 tuple 形式。
e.g.
>>> req = urllib2.Request(''http://www.pretend_server.org'')
>>> try: urllib2.urlopen(req)
>>> except URLError, e:
>>> print e.reason
>>>
(4, ''getaddrinfo failed'')
当一个错误被抛出的时候,服务器返回一个 HTTP 错误代码和一个错误页。你可以使用返回的 HTTP 错误示例。这意味着它不但具有 code 属性,而且
同时具有 read,geturl,和 info,methods 属性。>>> req =
urllib2.Request(''http://www.python.org/fish.html'')>>>
try:>>> urllib2.urlopen(req)>>> except URLError,
e:>>> print e.code>>> print
e.read()>>>404...... etc
容错:
如果你准备处理 HTTP 错误和 URL 错误这里有两种基本的方法,我更倾向于后一种:
1.
from urllib2 import Request, urlopen, URLError, HTTPError
req = Request(someurl)
try:
    response = urlopen(req)
except HTTPError, e:
    print ''The server couldn\''t fulfill the request.''
    print ''Error code: '', e.code
except URLError, e:
    print ''We failed to reach a server.''
    print ''Reason: '', e.reason
else:
    # everything is fine
注意:HTTP 错误异常必须在前面,否则 URL 错误也会捕获一个 HTTP 错误。
2
from urllib2 import Request, urlopen, URLError
req = Request(someurl)
try:
    response = urlopen(req)
except URLError, e:
    if hasattr(e, ''reason''):
        print ''We failed to reach a server.''
        print ''Reason: '', e.reason
    elif hasattr(e, ''code''):
        print ''The server couldn\''t fulfill the request.''
        print ''Error code: '', e.code
else:
    # everything is fine
注意:URL 错误是 IO 错误异常的一个子类。这意味着你能避免引入(import)URL 错误而使用:
from urllib2 import Request, urlopen
req = Request(someurl)
try:
    response = urlopen(req)
except IOError, e:
    if hasattr(e, ''reason''):
        print ''We failed to reach a server.''
        print ''Reason: '', e.reason
    elif hasattr(e, ''code''):
        print ''The server couldn\''t fulfill the request.''
        print ''Error code: '', e.code
else:
    # everything is fine
极少数环境下,urllib2 能够抛出 socket.error.
INFO and GETURL
urlopen 返回的 response(或者 HTTP 错误实例)有两个有用的方法:info 和 geturl。
geturl–它返回被获取网页的真正的 url。这是很有用的,因为 urlopen(或使用的 opener 对象)也许会伴随一个重定向。
获取的网页 url 也许和要求的网页 url 不一样。
info–它返回一个像字典的对象来描述获取的网页,尤其是服务器发送的头。它现在一般是 httplib.HTTPMessage 的一个实例。
典型的头包含 ''Content-length'', ''Content-type'', 等等。看一下 Quick Reference to HTTP Headers 中,HTTP 头列表,还有
关于他们简单的解释和使用方法。
Openers 和 Handlers
当你获取一个 URL 时,你使用一个 opener(一个可能以一个比较迷糊名字命名的实例–urllib2.OpenerDirector)。正常情况下
我们一直使用默认的 opener,通过 urlopen,但你也可以创建自定义的 openers。opener 使用操作器(handlers)。所有的重活都交给这些 handlers 来做。每一个 handler 知道
怎么打开 url 以一种独特的 url 协议(http,ftp 等等),或者怎么处理打开 url 的某些方面,如,HTTP 重定向,或者 HTTP cookie。
你将会创建 openers 如果你想要用安装特别的 handlers 获取 url,例如,获取一个处理 cookie 的 opener,或者一个不处理重定向的 opener。
枚举一个 OpenerDirector,然后多次调用.add_handler (some_handler_instance) 来创建一个 opener。
或者,你可以用 build_opener,这是一个很方便的创建 opener 对象的函数,它只有一个函数调用。build_opener 默认会加入许多
handlers,但是提供了一个快速的方法添加更多东西和 / 或使默认的 handler 失效。
其他你想要的 handlers 能够处理代理,authentication 和其他平常但是又有些特殊的情况。
install_opener 能被用于创建一个 opener 对象,(全局)默认的 opener。这意味着调用 urlopen 将会用到你刚安装的 opener。
opener 对象有一个 open 方法,它可以被直接调用来获取 url 以一种和 urlopen 函数同样的方式:没有必要调用 install_opener,除非是为了方便。
Basic Authentication:(基本验证)
为了解释创建和安装一个 handler,我们将会使用 HTTPBasicAuthHandler。更多关于这个东西的内容和详细讨论 — 包括一个
Basic Authentication 如何工作的解说–参见 Basic Authentication Tutorial.
当需要 Authentication 的时候,服务器发送一个头(同时还有 401 代码)请求 Authentication。它详细指明了一个 Authentication 和一个域。这个头看起来像:
Www-authenticate: SCHEME realm=”REALM”.
e.g.
Www-authenticate: Basic realm=”cPanel Users”
客户端然后就会用包含在头中的正确的帐户和密码重新请求这个域。这是” 基本验证”。为了简化这个过程,我们可以创建一个
HTTPBasicAuthHandler 和 opener 的实例来使用这个 handler。
HTTPBasicAuthHandler 用一个叫做密码管理的对象来处理 url 和用户名和密码的域的映射。如果你知道域是什么(从服务器发送的 authentication
头中),那你就可以使用一个 HTTPPasswordMgr。多数情况下人们不在乎域是什么。那样使用 HTTPPasswordMgrWithDefaultRealm 就很方便。它
允许你为一个 url 具体指定用户名和密码。这将会在你没有为一个特殊的域提供一个可供选择的密码锁时提供给你。我们通过提供 None 作为 add_password 方法域的参数指出
这一点。
最高级别的 url 是需要 authentication 的第一个 url。比你传递给.add_password () 的 url 更深的 url 同样也会匹配。
# create a password manager
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# Add the username and password.
# If we knew the realm, we could use it instead of “None“.
top_level_url = “http://example.com/foo/”
password_mgr.add_password(None, top_level_url, username, password)
handler = urllib2.HTTPBasicAuthHandler(password_mgr)
# create “opener” (OpenerDirector instance)
opener = urllib2.build_opener(handler)
# use the opener to fetch a URL
opener.open(a_url)
# Install the opener.
# Now all calls to urllib2.urlopen use our opener.
urllib2.install_opener(opener)
注意:在以上的示例中我们只给 build_opener 提供了 HTTPBasicAuthHandler。默认 opener 有对普通情况的操作器
(handlers)- ProxyHandler, UnknownHandler, HTTPHandler,
HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler,
HTTPErrorProcessor.
高级别 url 实际上是一个完整的 url(包括 http: 协议组件和主机名可选的端口号),如”http://example.com” 或者是一个授权(同样,主机名,可选的端口号)
如”"example.com” 或 “example.com:8080″(后一个示例包含了一个端口号)。授权,如果被呈现,一定不能包含用户信息 - 如”oe@password:example.com”
是不正确的、
代理:
urllib2 将会自动检测你的代理设置并使用它们。这是通过 ProxyHandler 实现的,它是操作器链的一部分。正常情况下,这是个好东西,但是也有它不那么有用的偶然情况。
一个做这些的方法是安装我们自己的 ProxyHandler,不用任何定义任何代理。使用一个和建立 Basic Authentication 操作器相似的步骤可以实现:
>>> proxy_support = urllib2.ProxyHandler({})
>>> opener = urllib2.build_opener(proxy_support)
>>> urllib2.install_opener(opener)
注意:
目前 urllib2 不支持通过代理获取 HTTPs 位置。这是一个问题。
sockets 和 layers
python 支持获取层叠的网页的源码。urllib2 使用 httplib library,而 httplib library 反过来使用 socket library。
对于 python2.3 你可以指明一个 socket 应该在超时之前等待 response 多久。这在这些不得不获取网页的应用中很有用。默认 socket 模块没有超时而且能够挂起。
目前,socket 超时在 urllib2 或者 httplib 水平中不可见。然而,你可以全局地为所有 socket 设置默认的超时。
import socket
import urllib2
# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)
# this call to urllib2.urlopen now uses the default timeout
# we have set in the socket module
req = urllib2.Request(''http://www.voidspace.org.uk'')
response = urllib2.urlopen(req)

ansible 模块之 copy模块详解

ansible 模块之 copy模块详解

ansible copy 模块详解

 ansible copy 模块主要用于文件或目录复制。详细如下:

 src    ansible 端源文件或目录,空文件夹不复制
 content     用来替代src 用于将指定的文件内容复制到远程文件
 dest          客户端目标目录或文件,需要绝对路径
 back_up   复制之前备份远程节点上的原始文件
 directory_code 用于复制文件夹,新建文件会被复制,旧文件不会被复制
     follow       支持link文件复制
     force         覆盖远程主机不一致的内容
     group        设定远程主机文件夹的组名
     mode         文件夹权限
     owner       设定远程主机文件夹的用户名

 ansible -i /etc/ansible/hosts all -m copy -a ''src=/etc/passwd dest=/tmp/passwd force=yes backup=yes''

 ansible -i /etc/ansible/hosts all -m copy -a ''content="hello ansible" dest=/tmp/passwd force=yes backup=yes''

总结

以上是小编为你收集整理的ansible 模块之 copy模块详解全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

原文地址:https://blog.51cto.com/5776643/2376181

ansible 模块之 cron模块详解

ansible 模块之 cron模块详解

ansible 模块之 cron模块详解

用于更新添加、删除、更新操作系统的crontab任务计划 state 指定任务计划present、absent
backup :是否备份之前的任务计划

  ansible -i /etc/ansible/hosts all -m cron -a "minute=0 hour=0 day=* month=*          weekday=* name=''test'' job=opt/shell/sms.sh"

  ansible -i /etc/ansible/hosts all -m cron -a "name=''test'' state=absent"

总结

以上是小编为你收集整理的ansible 模块之 cron模块详解全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

原文地址:https://blog.51cto.com/5776643/2386106

ansible 模块之 yum、pip、service、corn、user、group

ansible 模块之 yum、pip、service、corn、user、group

ansible 相关模块

yum

  • rpm 和 yum 的区别

    rpm:全称 redhat package manager (红帽包管理器) 不能解决包之间的依赖关系

    yum:可以解决依赖关系

  • yum 源配置

  • [root@localhost ~]# cat /etc/yum.repos.d/epel.repo
    [epel]
    name=Extra Packages for Enterprise Linux 7 - $basearch #名字
    baseurl=http://mirrors.aliyun.com/epel/7/$basearch  #rpm源的地址,可以写http,https,ftp,Samba,file:
    failovermethod=priority
    enabled=1 # 是否开启,1代表开启,0表示关闭
    gpgcheck=0  #是否校验签名,1代表校验,0表示不校验
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
    
  • yum 安装包组

    yum grouplist # 查看包组信息
    yum groupinstall 包组名 # 安装包组
    
     #ansible-doc -s yum     查看yum模块的参数信息
    
    disablerepo #禁用源
    enablerepo #启用源
    name #包名
    state  install (`present'' or `installed'', `latest''), or remove (`absent'' or `removed'')
    
    ansible web -m yum -a ''name=wget'' # 安装wget
    rpm -q wget    #查询已经安装的软件信息
    [root@localhost ~]# ansible web -m copy -a ''src=/etc/yum.repos.d/epel.repo dest=/etc/yum.repos.d/epel.repo''
    #将管控机上的epel源复制到被管控机上
    ansible web -m yum -a ''name=python2-pip'' # 安装python2-pip
    ansible web -m yum -a ''name=wget state=absent'' # 卸载软件包
    ansible web -m yum -a ''name="@Development Tools"'' # 安装包组
    

pip

pip install 安装包
pip freeze > a.txt 将python的环境打包到文件中
pip install -r a.txt 安装文件中的包
pip list 查看所有的以安装成功的包
ansible web -m pip -a ''name=flask'' # 安装flask模块

service

ps -ef|grep nginx #查看进程
ss -tnlp # 查看端口信息
systemctl start nginx # centos7启动nginx
service nginx start  # centos6启动nginx
systemctl enable nginx # centos7 开机自启动
chkconfig nginx on # centos6开机自启动
ansible web -m service -a ''name=nginx state=started'' # 启动nginx
ansible web -m service -a ''name=nginx state=stopped'' # 关闭nginx
ansible web -m service -a ''name=nginx state=started enabled=yes'' # 设置开机自启动

cron 计划任务

* * * * * job 
     任务
0 */2 *  * *  job  每隔两个小时
0 12,13 * * * job 12点和13点
0 12-17 * * * job 12点到17点
0 12-17/2 * * 1,3,6,0 周1,周3,周6,周7 12点到17点每隔两个小时 
[root@localhost ~]# cat /etc/crontab 
crontab -e # 编辑计划任务
crontab -l # 查看计划任务
crontab -r # 删除计划任务
[root@localhost ~]# ansible-doc -s cron    #查看cron模块的参数
day  #天
disabled #禁用
hour #小时
job #任务
minute #分钟
month #月
name #任务名字
weekday #周
state   #present or absent
ansible db -m cron -a ''minute=26 job="touch /tmp/xzmly.txt" name=touchfile'' # 新建一个计划任务,每小时的第26分钟在被管控机组db的/tmp下创建xzmly.txt文件
ansible db -m cron -a ''name=touchfile state=absent'' # 删除一个计划任务
ansible db -m cron -a ''minute=26 job="touch /tmp/xzmly.txt" name=touchfile disabled=yes''  # 禁用计划任务,以#表示禁用

[root@localhost ~]# crontab -l
#Ansible: touchfile
#56 * * * * touch /tmp/fengchong.txt

### 用户相关: user

用户:
	管理员  root 0
	普通用户
		系统用户  不能登录  1-999 centos7 1-499 centos6
		登录用户  可以登录  1000-65535 centos7 500-65535 centos6
用户组:
    管理员组 root 0
    系统用户组 1-999 centos7 1-499 centos6
    登录用户组 1000-65535 centos7 500-65535 centos6
    
[root@localhost ~]# useradd -h     #查看useradd的参数
 -d  #指定用户的家目录
 -g  #指定用户的组
 -G  #执行用户的附加组
 -s  #指定登录后使用的shell
 -r  #创建一个系统用户
 useradd -r wusir  #创建系统用户, 从999倒序
 useradd -s /sbin/nologin alexsb #创建的是普通用户,从1000开始升序
 useradd -d /opt/alexsb2 alexsb2 #创建用户时指定用户的家目录
 useradd -u 3000 alexsb6 # 创建用户并指定用户的uid
 userdel alex #删除用户
 userdel -r alexsb2 #删除用户并删除用户的家目录
  
  groupadd yuchao #创建用户组
  groupdel yuchao #删除用户组
#ansible中的user模块参数
group #组
groups #附加组
home #家目录
name #用户名
password #密码
remove #当remove=yes时,删除用户且删除用户的家目录
shell #用户登录后使用的shell
system #创建一个系统用户
uid #用来指定用户的id
state #状态
ansible db -m user -a ''name=wulaoshi uid=4000 home=/opt/wulaoshi groups=root shell=/sbin/nologin'' #创建一个用户,并指定用户的id,用户的家目录,用户的附加组,用户的shell
ansible db -m user -a ''name=wulaoshi state=absent'' #删除用户但是不删除用户的家目录
ansible db -m user -a ''name=wulaoshi3 state=absent remove=yes'' # 删除用户并删除用户的家目录

### 用户相关: group

[root@localhost ~]# ansible-doc -s group
#查看模块group的参数信息
gid #组的id
name #组名
system #系统组
state
ansible db -m group -a ''name=wulaoshi system=yes'' #创建系统组
ansible db -m group -a ''name=wulaoshi state=absent'' # 删除组

小练习:以下操作均在主机列表 web 上进行

1、创建一个用户组 alex10

ansible web -m group -a ''name=alex10''

2、创建一个用户 wusir10

ansible web -m user -a ''name=wusir10''

3、把 /etc/fstab 文件复制到远程主机上 /tmp/f

ansible web -m copy -a ''src=/etc/fstab dest=/tmp/f''

4、安装 nginx, 并启动,设置开机自启动

ansible web -m yum -a ''name=nginx''

ansible web -m service -a ''name=nginx enabled=yes''

ansible 剧本

###yaml 介绍:

是一个编程语言
文件后缀名 yaml yml
数据对应格式:
	字典: key: value
	列表: [] -

###ansible-playbook 命令格式

执行顺序:从上往下

特性:幂等性 不管执行多少遍,结果都是一样的

#命令格式:ansible-playbook [options] playbook.yml [playbook2 ...] 
#参数:
    -C, --check   # 检查,白跑,干跑
    -f FORKS, --forks=FORKS #用来做并发
    --list-hosts # 列出主机列表
    --syntax-check # 语法检查 
    -e         #指定参数



简单用法

#vi p1.yml   写入如下内容:

- hosts: web         #主机列表
  tasks:             #任务
  - name: creategroup     #任务名称
    group: name=alex10    #模块名:参数
  - name: cretaeuser      #任务名称
    user: name=wusir10    #模块名:参数
    
    
#检查p1.yml语法的正确性
[root@localhost ~]# ansible-playbook --syntax-check p1.yml

playbook: p1.yml
#执行
[root@localhost ~]# ansible-playbook p1.yml


hosts: gb
tasks:
- name: 第san个姑娘
  dong: 第san个姑娘
  

传参

- hosts: web
  tasks:
  - name: create{{ user }}
    user: name={{ user}}

第一种方式

ansible-playbook -e ''user=alexsb10'' p2.yml

第二种方式

[db]
192.168.107.132 user=alexsb11
192.168.107.133 user=alexsb12

第三种方式

[db:vars] #表示组的参数
user=alexsb13

第四种方式

- hosts: db
  vars:
  - user: alexsb14
  tasks:
  - name: create{{ user }}
    user: name={{ user}}

第五种传参方式

- hosts: db
  tasks:
  - name: sum
    shell: echo 7+8|bc
    register: user
  - name: createuser
    user: name={{user.stdout}}

传参方式的优先级

-e > playbook vars > hosts文件

freeswitch 模块之 event_socket

freeswitch 模块之 event_socket

这是我之前整理的关于 freeswitch mod_event_socket 的相关内容,这里记录下,也方便我以后查阅。

mod_event_socket 以 socket 的形式,对外提供控制 FS 一种途径, 缺省的 IP 是 127.0.0.1,TCP 端口是 8021,可以在外部通过 sokcet 执行 API/APP 命令。

连接模式

连接分两种模式: inbound/outbound
mod_event_socket 的默认加载模式是 inbound,outbound 模式需要在 dialplan 的配置文件中设置。

InBound 模式由于是可以主动连接并可长期稳定保持,且此通道有且只有一个,心跳、外呼和注册等动作必须通过此种连接完成;

OutBound 模式由于是在外线呼入和内线呼出的时候才会触发 socket 连接事件,所以是不稳定的,且由于同一时间呼入数量不唯一,所以此连接的数目也是动态变化的,但是由于其每个来电建立一个 socket 连接,所以在大负荷情况下不会造成命令和事件的堵塞。

使用 inbound 模式

1、修改 acl 配置:

配置 autoload_configs/acl.conf.xml 文件:

<list name="domains" default="deny">
  <!-- domain= is special it scans the domain from the directory to build the ACL -->
  <node type="allow" domain="$${domain}"/>
  <!-- use cidr= if you wish to allow ip ranges to this domains acl. -->
  <!-- <node type="allow" cidr="192.168.0.0/24"/> -->
  <node type="allow" cidr="192.168.168.0/24"/>
  <node type="allow" cidr="127.0.0.0/24"/>
</list>

2、修改 esl 配置:

配置 autoload_configs/event_socket.conf.xml 文件:

<configuration name="event_socket.conf" description="Socket Client">
  <settings>
    <param name="nat-map" value="false"/>
    <param name="listen-ip" value="0.0.0.0"/>
    <param name="listen-port" value="8021"/>
    <param name="password" value="ClueCon"/>
    <param name="apply-inbound-acl" value="domains"/>
    <!--<param name="apply-inbound-acl" value="loopback.auto"/>-->
    <!--<param name="stop-on-bind-error" value="true"/>-->
  </settings>
</configuration>

3、重启 freeswitch

4、通过 inbound 方式使用 freeswitch python 示例代码如下:

import socket
import json
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((''127.0.0.1'', 8021))
# send auth
sock.send(''auth ClueCon\r\n\r\n'')
# send command
sock.send(''event json ALL\r\n\r\n'')
#sock.send(''event plain ALL\r\n\r\n'')
while True:
    print sock.recv(10240)

使用 outbound 模式

1、编辑 conf/dialplan/default.xml,增加如下内容:

<extension name="123456789 Entrance">
    <condition field="destination_number" expression="^123456789$">           
      <action application="socket" data="127.0.0.1:9000 async full" />       
      <action application="playback" data="$${hold_music}"/>
      <action application="hangup" data="" /> 
    </condition>
</extension>

2、启动监听服务器 监听 listen-ip:listen-port(如在 Linux 下可以通过 nc -v -l 9000),

然后拨打配置的电话号码(本例中为 123456789) 即可收到 Connection from 127.0.0.1 port 9000 [tcp/*] accepted 的消息, 键入 connect\n\n 即可进入 OutBound 模式

 

通过 socket 控制 freeswitch

 

可以通过任何支持 socket 的语言控制 freeswitch,这里以 python 为例子描述怎么通过 socket 控制 freeswitch。

 

  • auth
    语法:

    auth <password>
    

    当用户第一次通过 mod_event_socket 连接到 freeswitch 时,必须进行认证,认证示例:

    sock.send(“auth ClueCon\r\n\r\n”)
    
  • api
    执行 freeswitch 的 API 命令,阻塞执行。
    语法:
    api 
    示例:

    sock.send(''api originate user/1000 &echo\r\n\r\n'')
    sock.send(''api originate user/1001 &echo\r\n\r\n'')
    

    socket 会将上述两条指令同时发送给 freeswitch,但 freeswitch 按顺序阻塞执行。

  • bgapi
    功能和 api 相同,非阻塞执行。
    语法:
    bgapi 
    示例:

    sock.send(''bgapi originate user/1000 &echo\r\n\r\n'')
    sock.send(''bgapi originate user/1001 &echo\r\n\r\n'')
    

    socket 会将上述两条指令同时发送给 freeswitch,同时执行。

  • event
    启动或停止事件流。
    语法:
    event

    format : plain、json、xml
    Event types : 参考 freeswitch 事件类型
    示例:

    sock.send(''event json ALL\r\n\r\n'')
    

    接收 freeswitch 所有事件,并以 json 格式返回。

  • noevents
    关闭上一个 event 开启的事件
    语法 :
    noevents

    示例:

    sock.send(''noevents\r\n\r\n'')
    
  • divert_events
    脚本注册接收事件的函数分转到 event socket 上。
    语法:
    divert_events

  • filter
    设置 event socket 接收事件的类型。
    语法:
    filter

    示例:
    只订阅 CHANNEL_EXECUTE 事件

    sock.send(''filter Event-Name CHANNEL_EXECUTE\r\n\r\n'')
    

    只订阅 uuid 为 34602e08-557a-494a-af47-99e9d55e26ed 的事件

    sock.send(''filter Unique-ID 34602e08-557a-494a-af47-99e9d55e26ed\r\n\r\n'')
    
  • filter delete
    取消订阅的事件。
    语法:
    filter delete

    示例:

    sock.send(''filter  delete  Event-Name CHANNEL_EXECUTE\r\n\r\n'')    
    sock.send(''filter  delete  Unique-ID 34602e08-557a-494a-af47-99e9d55e26ed\r\n\r\n'')
    
  • nixevents
    设置 event socket 禁止接收的事件类型。
    语法:

    nixevents <event types | ALL| CUSTOM custom event sub-class>         
    

    示例:
    不订阅 HEARTBEAT 事件

    sock.send(''nixevent HEARTBEAT\r\n\r\n'')   
    
  • sendevent
    发送一个事件到系统队列中。
    语法:

    sendevent  <event-name>          
    

    示例(消息内容):

    sendevent SOME_NAME
    Event-Name: CUSTOM
    Event-Subclass: albs::Section-Alarm
    Section: 33
    Alarm-Type: PIR
    State: ACTIVE
    
  • sendmsg

    给一个 uuid 发送一个消息,可以执行其他模块的应用接口,也可以挂断电话等。
    语法:

    sendmsg <uuid>       
    

    示例(消息内容):

    sendmsg <uuid>
    call-command: execute
    execute-app-name: playback
    execute-app-arg: /tmp/test.wav
    
  • execute
    执行一个拨号规则的应用。
    语法:

    sendmsg <uuid>      
    call-command: execute
    execute-app-name: <one of the applications>
    execute-app-arg: <application data>
    loops: <number of times to invoke the command, default: 1>
    
  • hangup 对活动的呼叫挂机。
    语法:

    sendmsg <uuid>
    call-command: hangup
    hangup-cause: <one of the causes listed below>
    
  • nomedia

    控制 freeswitch 是否处于实时的媒体路径,这个命令支持用户对指定的通道启用或关闭媒体处理。

    语法:

    sendmsg <uuid>
    call-command: nomedia
    nomedia-uuid: <noinfo>
    
  • log 语法:

    log <level>       
    

    设置日志级别。

  • nolog

    禁止日志。

  • linger

    告诉 freeswitch 当一个通道挂机时不要关闭 socket 连接,直到收取相关通道的最后一个事件。

  • nolinger

    关闭上次开启的 linger 命令。

 

通过 freeswitch 提供的 ESL 库进行控制 

这里以 python 为例描述下 ESL 库的基本使用及 api 接口。

安装 ESL

以 python 为例进行安装:

cd libs/esl/
make pymod
make pymod-install

ESL 示例

  • InBound 模式

    Python 示例代码:

    import ESL
    import time
    
    hostIp,port,user = "127.0.0.1","8021","ClueCon"
    
    con = ESL.ESLconnection(hostIp,port,user)
    con.events("json","all")
    for i in range(100):
        eventData = con.recvEvent()
        print eventData.getHeader("Event-Name")
    con.disconnect()
  • OutBound 模式

    配置 dialplan:

    <action application="socket" data="127.0.0.1:9000 async full"/>
    

    Python 示例代码:

    import SocketServer
    import ESL
    
    class ESLRequestHandler(SocketServer.BaseRequestHandler ):
        def setup(self):
            print self.client_address, ''connected!''
            fd = self.request.fileno()
            con = ESL.ESLconnection(fd)
            if con.connected():
                info = con.getInfo()
                uuid = info.getHeader("unique-id")
                print uuid
                con.execute("answer","", uuid)
                con.execute("playback","/tmp/sample.wav", uuid)
    
    server = SocketServer.ThreadingTCPServer(('''', 9000), ESLRequestHandler)
    server.serve_forever()

ESL 接口介绍

eslSetLogLevel 函数

该函数用于设置服务器的日志级别,使用方式如下:

eslSetLogLevel(loglevel)

其中 loglevel 是一个整数变量,从 0 到 7,含义如下:

0 是 EMERG
1 是 ALERT
2 是 CRIT
3 是 ERROR
4 是 WARNING
5 是 NOTICE
6 是 INFO
7 是 DEBUG

ESLconnection 对象

ESLconnection 对象维护与 freeswitch 之间的连接,以发送命令并进行事件处理。 成员函数列表如下:

  • socketDescriptor()
    该函数返回连接的 UNIX 文件句柄

  • connected()
    判断是否已连接,连接返回 1,否则返回 0

  • getInfo()

    当 freeswitch 使用 outbound 模式连接时,它将首先发一个 CHANNEL_DATA 事件,getInfo 会返回该事件;
    在 inbound 模式中返回 None

  • send(command)
    向 freeswitch 发送一个 command,但不会等待返回结果,需要显式调用 recvEvent 或 recvEventTimed 以接收返回的事件。

  • sendRecv(command)
    向 freeswitch 发送一个 command,并等待返回结果(一个 ESLevent 对象)。

  • api(command[,arguments])
    向 freeswitch 发送 api 命令,阻塞执行

  • bgapi(command[, arguments][,custom_job_uuid])
    向 freeswitch 发送 bgapi 命令,后台执行,非阻塞执行

  • sendEvent(event)
    向 freeswitch 发送一个事件

  • sendMSG(event,uuid)
    参考 sendmsg 命令

  • recvEvent()
    从 freeswitch 接收事件,阻塞模式

  • recvEventTimed(milliseconds)
    与 recvEvent 类似,但不会无限等待,而是在参数指定的毫秒数会返回。
    recvEventTimed (0) 会立即返回。

  • filter (header,value)
    事件过滤,类似 filter 命令。

  • events (event_type,value)
    事件订阅,类似 event 命令。

  • execute (app[,arg][,uuid])
    执行 dialplan 的 app,并阻塞等待返回。返回结果为一个 ESLevent 对象,通过 getHeader (“Reply-Text”) 可以获取返回值,”+OK” 表示成功,”-ERR” 表示失败。

  • executeAsync (app[,arg][,uuid])
    与 execute () 相同,但非阻塞执行。

  • setAsyncExecute(value)
    强制将 socket 设置为异步模式,value 为 1 是异步,0 是同步。

  • setEventLock(value)
    使用该选项后,后续所有的 execute () 调用都将带有”event-lock:true” 头域。

  • disconnect()
    主动中断与 freeswitch 的连接。

ESLevent 对象

当接收一个事件时,用户将获得一个 ESLevent 对象,这个对象包含各种帮助函数变量 来帮助解析和处理收到的事件。

con = ESL.ESLconnection("127.0.0.1", "8021", "ClueCon")
con.events("json", "all");
eventData = con.recvEvent()

eventData 即为 ESLevent 对象

ESLevent 对象成员函数列表如下:

  • serialize([format]) 

    将 event 数据转换成”name:value” 型数据,format 参数可以为:

    "xml"
    "json"
    "plain" (default)

    示例如下:

    eventData.serialize(''json'') 获取json格式数据
  • setPriority([number])
    设置事件的级别
  • getHeader(headerName)
    获取 header 对应的 value,示例如下:

    eventData .getHeader (''Event-Name'') #获取事件名称

  • getBody()
    获取事件的正文
  • getType()
    获取 event object 的事件类型
  • addBody(value)
    向事件中加入正文,可以调用多次
  • addHeader(key,value)
    向事件中加入一个头域 (ESL_STACK_BOTTOM)
  • pushHeader(key,value)
    向事件中加入一个头域 (ESL_STACK_PUSH)
  • unshiftHeader(key,value)
    向事件中加入一个头域 (ESL_STACK_UNSHIFT)
  • delHeader(key)
    从 Event 中删除头域
  • firstHeader()
    将指针指向 Event 的第一个头域,并返回它的 key 值。它必须在 nextHeader 之前调用
  • nextHeader()
    移动指针指向下一个 header,在函数调用前必须先调用 firstHeader ()

本文 github 地址:

https://github.com/mike-zhang/mikeBlogEssays/blob/master/2016/20160926_freeswitch 模块之 event_socket.md

欢迎补充  

关于python 模块之 ---- urllib2 模块详解python的urllib2模块的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于ansible 模块之 copy模块详解、ansible 模块之 cron模块详解、ansible 模块之 yum、pip、service、corn、user、group、freeswitch 模块之 event_socket等相关内容,可以在本站寻找。

本文标签: