常用的CentOS6.7中,默认自带的Python版本还是2.6.6,升级到2.7.11后,安装某些第三方的库提示
ImportError: No module named zlib
百度了一下,按照前辈的方法果然解决了问题。特此记录下来!
bash部分
1 | yum install zlib zlib-devel openssl |
python部分
1 | cd Python2.7.11 |
验证
1 | >>> import zlib |
没有结果就是最好的结果!
常用的CentOS6.7中,默认自带的Python版本还是2.6.6,升级到2.7.11后,安装某些第三方的库提示
ImportError: No module named zlib
百度了一下,按照前辈的方法果然解决了问题。特此记录下来!
bash部分
1 | yum install zlib zlib-devel openssl |
python部分
1 | cd Python2.7.11 |
验证
1 | >>> import zlib |
没有结果就是最好的结果!
1 | In [3]: l = list(range(100)) |
1 | In [1]: l = ['apple', 'google', 'facebook', 'microsoft', 'linkin'] |
1 | In [13]: (0, 1, 2, 3, 4, 5)[:3] |
1 | In [14]: 'apple'[:3] |
在Python中迭代是通过for ... in ...
来实现的
1 | In [15]: d = {'apple':'pages', 'google':'docs', 'microsoft':'word'} |
列表、元组、字典和字符串都是可迭代对象
判断一个对象是否是可迭代对象,通过collections模块的Iterable来判断
1 | In [22]: from collections import Iterable |
Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身
1 | In [27]: for i, value in enumerate(['A', 'B', 'C']): |
列表生成式有自己的特殊语法
把要生成的元素放到最前面
,后跟for
循环,就可以创建一个list
1 | n [29]: [i * i for i in range(1,10)] |
生成器返回一个可迭代的对象
生成器的关键字yield
,与return
的区别是
return 立即返回结果并结束函数
yield 返回结果并暂停函数,等待next()
的下一次调用
1 | In [1]: def my_fun(): |
上面介绍的列表生成式
也可以变成生成器生成式
只需把中括号
换成小括号
就变成了一个生成器
1 | In [11]: L = [x * x for x in range(10)] |
生成器保存的是算法,在使用时计算结果,节省内存空间
可以直接作用于for
循环的数据类型有以下几种:
集合数据类型。如list
tuple
dict
set
str
等
generator,包括生成器和带yield的generator function
这些可以直接作用于for
循环的对象统称为可迭代对象Iterable
可以使用isinstance()
判断一个对象是否是Iterable
可迭代对象
1 | In [20]: from collections import Iterable |
生成器不但可以作用于for
循环,还可以被next()
函数不断调用并返回下一个值,最后抛出StopIteration
异常,表示已经结束,无法返回下一个值
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
可以使用isinstance()
判断一个对象是否是Iterator
对象
1 | In [24]: from collections import Iterator |
生成器都是Iterator对象,但list
dict
等是Iterable,但不是Iterator
Iterator是迭代器,需要同时具备__iter__
和next
两个方法,它们表示一个惰性计算的序列
Iterable是可迭代对象,列表元组等数据结构同样是可迭代对象,具备__iter__
方法,但不具备next
方法
使用for循环遍历可迭代对象时,for循环自动调用next()函数,并在接收到结束异常时退出循环
1 | def my_fun(arg): |
如果没有写return
语句,函数执行之后会返回None
可以有多个返回值,但是多个返回值默认是以元组的方式返回,相当于返回了一个元组
1 | >>> def my_fun3(arg1, arg2): |
1 | def my_fun2(): |
function_name()
是调用函数的基本语法
1 | >>> def my_fun4(): |
拿一个简单的幂运算举例n=2
即为默认参数,在调用该函数时,如果只指定了一个参数,那变量n
将默认等于2
1 | >>> def my_fun6(x, n=2): |
也可以将两个参数都设置有默认变量,这样该函数即使不传参,也能正常工作
1 | >>> my_fun6() |
必选参数在前,默认参数在后,否则Python解释器会报错
当函数需要多个参数的时候,将变化较大的参数放在前面,变化小的放在后面作为默认参数
默认参数必须指向不可变对象(eg: int, string, float)
可以折衷地使用列表或元组实现可变长参数
(以下交互终端使用了ipython)
1 | In [1]: def cal(numbers): |
可变参数的关键字为*
星号。在设置函数的接收参数时,前面加上一个星号,则函数内部接收到的所有参数会自动转化为一个元组
1 | In [5]: def cal(*numbers): |
1 | In [9]: def cal(*numbers): |
可变长参数传入到函数内部会自动转换成一个元组
;而关键字参数传入到函数内部会自动转换成一个字典
关键字参数的关键字是**
两个星号
1 | In [12]: def person(name, age, **otherkeyword): |
上面提到了四种参数(必选参数、默认参数、可变参数、关键字参数),这四种参数可以一起使用。
参数定义的顺序必须是:必须参数、默认参数、可变参数、关键字参数
1 | In [21]: def func(a, b, c=0, *args, **kw): |
*args是可变参数,接收一个tuple
**kw是关键字参数,接收一个dict
在必选参数,默认参数,可变长参数和关键字参数混合使用时,默认参数在复制时不要指定参数名,如上例的c=3
否则会报错
isinstance函数判断对象类型
1 | >>> class obj1: |
Python中解析YAML文件主要使用到两个方法,load()和dump()方法,使用方式类似于Python的pickle。熟悉在Python中解析YAML文件,对使用Python做saltstack自定义插件开发时会有很大的帮助
测试
1 | [root@PolarSnow saltstack]# cat eg.yaml |
关键代码
1 | #!/usr/bin/env python |
测试
1 | [root@PolarSnow saltstack]# cat eg.yaml |
关键代码
1 | #!/usr/bin/env python |
使用-i参数
1 | $ echo "#!/usr/bin/env python |
使用 r' '
使单引号中的所有字符禁止转义
1 | >>> print 'x\ny\tz' |
使用\n
输入多行时可能不太好阅读,可以通过''' '''
三引号的方式来输出多行
1 | >>> print '''line one |
在Python中的常量也是一个变量,只不过为了显示这是个常量,约定俗成用大写表示常量
在Python中没有任何机制保证大写的变量不会被更改!
1 | >>> PI = 3.1415926 |
1 | >>> ord('L') |
1 | >>> '中文' |
1 | >>> print u'中\t文' |
1 | >>> u'ABC' |
1 | >>> '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8') |
1 | #!/usr/bin/env python |
常见的占位符:
1 | >>> print 'Hi %s' % 'ps' |
对Unicode字符串进行占位时,字符编码需要前后保持一致
1 | >>> print u'Hi %s, I have %d questions to ask you' % (u'ps', 59) |
对占位符转义%%
–>’%’
1 | >>> print "update %d%" % 59 |
1 | >>> testlist = ['Apple', 'Microsoft', 'Samaung'] |
列表中最后一个元素的位置是len(testlist) - 1
or testlist[-1]
以此类推,倒数第二个元素是testlist[-2]
1 | >>> testlist |
1 | >>> testlist |
1 | >>> testlist |
1 | >>> testlist |
1 | #直接覆盖 |
1 | >>> testtuple = ('apple') |
一般情况下元组是不可变的数据结构,如果需要实现让元组可变,可以在元组中加入列表来实现
1 | >>> testtuple = (['iPhone', 'iPad', 'iMac'], 'Microsoft', 'Google') |
1 | >>> results = 100 |
只要x
是非零数值、非空字符串、非空list等,就判断为True
,否则为False
1 | >>> x = '' |
1 | >>> testtuple = (['iPhone', 'iPad', 'iMac'], 'Microsoft', 'Google') |
1 | >>> start = 0 |
num = raw_input('please input a num:')
1 | >>> p = {'apple':'pages', 'microsoft':'word', 'google':'docs'} |
1 | >>> p = {'apple':'pages', 'microsoft':'word', 'google':'docs'} |
1 | #查找不到元素会返回None空 |
1 | >>> p.pop('google') |
1 | #判断一个元素是否包含在一个字典中 |
1 | >>> s = set([1, 2, 3]) |
1 | >>> s.add(4) |
1 | >>> s.remove(2) |
1 | >>> s1 = set([1, 2, 3]) |
子集包含集合本身,真子集不包含本身!如(1,2)的子集有:空集,(1),(2),(1,2).而真子集有:空集,(1),(2)没有(12)
1 | #子集(<=) 真子集(<) |
1 | >>> s1 |
1 | >>> s1 |
集合的应用: 去重
1 | >>> d = {'a':1, 'b':2} |
1 | >>> d = {'a':1, 'b':2} |
1 | >>> d = {'a':1, 'b':2} |
1 | >>> t = (1, 2, 3) |
1 | >>> t = (1, 2, 3) |
1 | >>> t = (1, 2, 3) |
1 | >>> l = [1, 2, 3] |
1 | >>> l = [1, 2, 3] |
1 | >>> l = [1, 2, 3] |
1 | >>> s = "[[1,2], [3,4], [5,6], [7,8], [9,0]]" |
1 | >>> s = "{1: 'a', 2: 'b'}" |
1 | >>> s = "([1,2], [3,4], [5,6], [7,8], (9,0))" |
1 | >>> s = "test" |
YAML的设计者认为在配置文件中所要表达的数据内容有三种类型
YAML(ball players)
1 | - Mark McGwire |
Python(YAML)
1 | ['Mark McGwire', 'Sammy Sosa', 'Ken Griffey'] |
YAML(player statistics)
1 | hr: 65 # Home runs |
Pyhton(YAML)
1 | {'hr':65, 'avg':0.278, 'rbi':147} |
YAML(ball clubs in each league)
1 | american: |
Python(YAML)
1 | {'american':['Boston Red Sox', 'Detroit Tigers', 'New York Yankees'], 'national':['New York Mets', 'Chicago Cubs', 'Atlanta Braves']} |
YAML(players’ statistics)
1 | - |
Python(YAML)
1 | [{'name':'Mark McGwire', 'hr':65, 'avg':0.278}, {'name':'Sammy Sosa', 'hr':63, 'avg':0.288}] |
YAML
1 | - [name , hr, avg ] |
Python(YAML)
1 | [['name', 'hr', 'avg'], ['Mark McGwire', 65, 0.278], ['Sammy Sosa', 63, 0.288]] |
YAML
1 | Mark McGwire: {hr: 65, avg: 0.278} |
Python(YAML)
1 | {'Mark McGwire':{'hr':65, 'avg':0.278}, 'Sammy Sosa':{'hr':63, 'avg':0.288}} |
YAML
1 | #ball players |
在单一一个YAML文件中
___
来分隔文档...
表示结束(一般在通信信道中使用)YAML(Two Documents in a Stream)
1 | # Ranking of 1998 home runs |
YAML
1 | --- |
YAML
1 | 用YAML来描述一本书《Linux命令行与shell脚本编程大全》 |
Python(YAML)
1 | {'书名':'Linux命令行与shell脚本编程大全', '出版社':'人民邮电出版社', '原作者':['Richard Blum', 'Christine Bresnahan'], '译者':['武海峰', '朱巍'], '前二章节':{'第一章':'初识Linux Shell', '第二章':'走进Shell'}} |
参考文档:
在使用salt进行软件管理的时候,有些节点报 No module named yum 的错误。经过排查,发现是因为升级了minion端Python版本后产生的问题
msater
1 | $ salt 'vm3.salt.com' pkg.install httpd |
服务器自带的Python版本是2.6.6 由于其他业务的需求,Python的版本升级到了2.7.10,升级后首先yum命令处于不可用的状态,通过修改/usr/bin/yum
文件的第一行#!/usr/bin/python
为#!/usr/bin/python2.6
来修复yum命令的使用
由于系统默认的Python已经由2.6.6变更到了2.7.10
1 | $ ls -l /usr/bin/python |
salt master在派发任务后,minion接收到任务并在本地使用默认的Python来执行,实际使用了升级后默认的Python2.7.10,导致Python报找不到yum模块的错误
在网上搜索了很多方案,全部是修改yum默认使用的Python版本来解决问题,貌似不能通过让yum来支持高版本的Python来解决问题。so,要解决salt minion本地调用yum不报错,就必须要保证其使用Python2.6.6来执行!解决方案和yum命令的修复方式相同:
1 | $ head /usr/bin/repoquery |
将/usr/bin/repoquery
文件第一行的#!/usr/bin/python -tt
更改为#!/usr/bin/python2.6 -tt
即可
当初始化安装 minion 启动服务启动后
/etc/salt/pki/master/minions
目录中(无扩展名);/etc/salt/pki/minion/minion_master.pub
minion 默认按照一定的顺序,试图找到一个不是localhost的值作为其ID
这里不需要知道salt是按照怎样的顺序取值的,只需要记住以下优先级即可
hostname
< /etc/salt/minion_id
< /etc/salt/minion文件中的id值
1 | /etc/salt/pki/master/master.pub |
1 | /etc/salt/pki/master/minions/ |
1 | /etc/salt/pki/minion/minion.pub |
1 | /etc/salt/pki/minion/minion_master.pub |
1 | /etc/salt/minion_id |
在实际使用过程中,minion端可能会遇到各种原因导致的密钥对儿不匹配的情况,造成在master端显示在denied keys列表中无法通过认证。
1 | rm -fr /etc/salt/pki/minion/minion_master.pub |
参考文章 salt key 认证过程
1 | rpm -ivh http://mirrors.kernel.org/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm |
1 | yum install salt-master -y |
master端安装好后一般不需要任何设置,启动服务器即可
1 | service salt-master start |
1 | yum install salt-minion |
minion端至少需要配置两项,id和master需要指定。
注意:注意冒号后面一定要有一个空格。
1 | $ vim /etc/salt/minion |
master
1 | salt-key -L #查看所有主机 |
一般情况下,master不会在配置文件中开启自动授权
master
1 | $ salt '*' test.ping |
在salt master端执行salt ‘*’ test.ping时,某一节点出现如下报错:Minion did not return. [No response]
登陆到这一节点查看minion的日志,发现如下的问题
1 | $ tail -f /var/log/salt/minion |
大概的意思就是,minion端拿到的key与master端的不符,验证无法通过。
解决方法是删除minion端的key,再重新与master进行连接和认证。
minion
1 | $ cat pki/minion/minion_master.pub |
master
1 | salt-key -A |
minion
1 | $ cat pki/minion/minion_master.pub |
至此,master与minion端的通信正常。