宣布一个事情,那就是我找到工作了!

    还是做openstack的,我比较欣慰,我不知道自己适不适合做openstack,但是我肯定不喜欢做7*24的系统运维,我一点都不喜欢加班,我更加鄙视值夜班。也许就是命吧,经历那么多次面试,能进入实习公司学习openstack,虽然我离开了99,但是我觉得做这门会比其他运维好多了,学习压力至少少了一部分,什么各种乱七八糟的数据库我也不用太花时间了,各种复杂的应用服务器软件我也许不需要管。我的重点就是openstack和python,甚至ansible或salt,再用一些Linux基本的服务软件和shell,现在对我这个应届生来说,最大的困难就是服务器硬件设备本身了,这一点我有点难搞!

   

   这次我进的是南京一个很小的创业公司,去年才成立,不是我没有野心去幻想大公司了,而是遭遇到了失败,或者说此时的心气已经没了。在面小公司之前,春招我也面过苏宁,上午很easy,下午一个是笑都不笑的面庞,表现很差,算了吧,进不去就进不去,我也不想做那种没完没完了的工作。如果小公司发展好了,我就是元老,几年后也就是技术总监,如果发展不好就会倒闭,我就又要找工作了,我一定要有随时准备面试的意识呀,我怕到时候压力一来,没做准备,容易扛不住!现在看来,运维真的是一个屌丝行业,运维开发才是主流,趁还有时间,我这python必须好好学了。

   

    有段时间没写博客了,其实这篇面经也是整理很久了,不知道为什么我比较懒,现在才发出来,签了三方协议后,说玩也没有玩,反正就是偏向实践的学习了,理论方面有些放松。以后上班了就不再是系统的学习,而是遇到问题再学习,那时候的压力和急性子就是让人失望了。

    不知道接下来还会遇到什么坎,希望勤于思考吧...


1、求10次以内的斐波那契数列,初始值是0

答:

def foo(list,num):

             if num == 1:

                     list.append(0)

             elif num == 2:          

                          foo(list,1)         

                          list.append(1) 

             elif num > 2:            

                          foo(list,num-1)  ##从10一直遍历到0为止,才执行下一句话

                          list.append(list[-1]+list[-2])  ##从倒数第1个,倒数第2个

mylist = [] 

foo(mylist,10)

print (mylist) ##输出[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]


2、合并两个有序列表?

答:思想就是制造空列表,再填数据,这个方法我记得最熟了

list1 = [1,3,5]

list2 = [2,4,6,8]

temp = []


for i in range(len(list1)):

             if list1[i] not in temp:

                          temp.append(list1[i])

for j in range(len(list2)):

             if list2[j] not in temp:

                          temp.append(list2[j])


temp.sort()  ##这里就不需要赋值了

print ("合并后的列表是",temp)


3、列表和字符串如何相互转换?

答:>>> str1 = 'abcdef'

>>> list(str1)

['a', 'b', 'c', 'd', 'e', 'f']

>>> mylist = list(str1)

>>> ''.join(list(mylist))   ##引号之间不加任何东西,结果就直接粘在一起,注意有一个点,点与单引号之间没有空格

'abcdef'

>>> '->'.join(list(mylist))  ##单引号之间加入任意字符,那么字符串结果就是以连接符构成的

'a->b->c->d->e->f'


4、分析a、b、c、d的值?

>>> a = [1, 2, 3, 4, ['a', 'b']]

>>> b = a  ##赋值,就是把a对象的引用(地址)传给b,b相当于是a的标签

>>> import copy

>>> c = copy.copy(a)  ##浅拷贝:只拷贝外围的对象的值,意思说外围值不会发生变化,以后内围对象的值随a的变化而变化

>>> d = copy.deepcopy(a)  ##深拷贝,外围对象和內围对象的值都进行拷贝,以后都不会发生变化。

>>> a.append(5)

>>> a[4].append('c')

答:>>> print ('a = ', a)

a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]

>>> print ('b = ', b)

b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]

>>> print ('c = ', c)

c =  [1, 2, 3, 4, ['a', 'b', 'c']]

>>> print ('d = ', d)

d =  [1, 2, 3, 4, ['a', 'b']]


5、select、poll、epoll之间的区别?(反正我是记不住的)

答:select的几大缺点:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

(3)select支持的文件描述符数量太小了,默认是1024

poll改善了第三个缺点,epoll改善了三个缺点。

参考文档:http://www.cnblogs.com/Anker/p/3265058.html


6、Linux系统的CPU和内存使用率比较高怎么办?(居然这个问题问开发,果然是大厂,就是叼,就算我运维我一时也拿不出最好的解决办法,这不是一件容易的事情)

答:(1)用top命令查看哪个进程占用CPU高,[root@python ~]# top -b -n 1 >top.txt ## -b bacth mode,-n 1次循环

(2)用top -H -p pid命令查看进程内各个线程占用的CPU百分比

(3)查看这个线程所有系统调用所花费时间 strace -p 【线程ID】

(4)使用nice命令降低该进程任务的优先级

参考文档:http://blog.sina.com.cn/s/blog_48eef8410101fl4p.html


7、Linux中进程A能否直接访问进行进程B?为什么?(我擦,拓麻这种问题太底层了,不过是操作系统概念,说到linux就反而觉得太高深了)

答:显然不能。(1)B进程为避免破坏数据的一致性,可能有互斥锁。(2)A与B的进程通信需要一些手段如消息队列、共享内存、socket、信号量、管道等实现。(3)A进程的三态(运行、就绪、阻塞)都需要CPU来调度,而调度又有一些算法(先来先服务、最高优先级、最短时间优先)才能来实现进程的状态转换,如果进程B在使用CPU,A进程就只能阻塞,那么A进程又怎么能访问B呢。


8、如何实现对cinder进行备份?(这个被问到过,想了半天说快照,其实错了)

答:(1)首先快照不是备份,没有冗余作用,只是用来恢复某个时间点的状态,如果原有卷挂掉,卷也是不能用的。因为快照要求卷是available的(即不能被挂载),所以一旦原有卷做了快照,是不能删除原有卷的,必须先删除其关联的快照才行。在快照的基础上,再进行创建volume(如果基于快照创建了硬盘,快照删除不掉)。快照命令:cinder snapshot-list 

参考文档:http://blog.csdn.net/hhp_hhp/article/details/49175101

(2)备份前,卷需要是available状态(即不能被挂载),备份一旦完成,对卷就不具有依赖性。cinder backup-create 

(3)使用后端驱动进行备份,比如swift或NFS共享存储,块存储节点写入数据,而后上传到NFS服务端(局域网中的另一个节点)。

(4)目前Freezer已正式引入OpenStack,能够进行数据库和nova实例、cinder卷的备份。

参考文档:http://www.aixchina.net/Article/159885



9、某公司系统突然发生访问异常,经程序员排查确定程序里没有死循环和定时任务等,该线上系统采用的是nginx+tomcat方式部署,现在让你快速分析系统最有可能的异常原因,后期防范这种异常可以采用什么方案。其他信息和答题要求如下:

(1)该线上系统周一到周五压力较高,周六周日压力较低;

(2)异常发生在周日;

(3)外界只能通过nginx访问到系统,不能通过tomcat直接访问;

(4)系统分配给tomcat的内存被耗尽了;

(5)nginx已经记录了详细的访问日志;

(6)定位异常原因的主要操作步骤和主要命令写出来;

(7)防范方案的原理和主要命令要写出来

分析:(1)周一周五压力高,说明访问量和负载比较大,用户人群多,但是周末压力很小,异常却发生在周末,说明不是并发连接数受限的问题,nginx和数据库肯定还撑得住。

(2)外界只能通过Nginx代理到tomcat,tomcat自身不开放8080端口,这一点是完全可以的,让tomcat专心处理动态页面

(3)系统分配给tomcat的内存用光了,这句话不太好理解,是说tomcat内存利用率高达95%以上吗?按理说服务器的内存一般都是够的,那么内存使用率很高,不知道CPU使用率高不高,使用top命令查看一下,另外查杀相应的僵死进程。

(4)awk '{arr[$1++]}END {for i in arr {print i ,arr[i]}}' nginx.log 统计nginx每个IP的访问人数,判断有没有恶意攻击,另外分析服务

器响应的状态码,这一点可能是排错的关键,如果都是200 OK或则304都没啥大问题,。


10、linux下的压力测试工具有哪些?注意事项有什么?

答:(1)webbench、ab:访问web服务器的压力测试 

1、压力及性能测试工作应该放到产品上线之前,而不是上线以后;

2、测试时并发应当由小逐渐加大,比如并发100时观察一下网站负载是多少、打开页面是否流畅,并发200时又是多少、网站打开缓慢时并发是多少、网站打不开时并发又是多少;

3、更详细的进行某个页面测试,如电商网站可以着重测试购物车、推广页面等,因为这些页面占整个网站访问量比重较大。

备注:webbench 做压力及性能测试时,该软件自身也会消耗CPU和内存资源,为了测试准确,建议将 webbench安装在其他的服务器上,已达到测试数据更加精确

(2)mysqlslap对数据库的并发连接测试、sysbench对磁盘IO进行压力测试,两者可以结合起来。

参考文档:http://www.cnblogs.com/chenmh/p/5866058.html

(3)除了这些之外,还可以说系统性能测试命令,如top、vmstat、free等常用命令,其实对于uptime命令我始终无法衡量它的上限达到怎样才算不合适?还有top的CPU使用率描述太混乱了!

(4)ipperf测试网络带宽和丢包率,突然想起pstree命令是个好东西 ,找父进程,多线程。[root@kvm ~]# yum -y install psmisc  依赖安装pstree


11、如何在Linux多级目录下,搜索某个关键字?

答:[root@python ppp]# grep -Rn 'mask' ./   ##用grep递归查找,但是find仅仅能够找到该关键字是否存在,暂时不知道如何打印该关键字所在的文件


12、迭代器和生成器?

答:(1)迭代器(iterator)代表一个数据流对象,不断重复调用迭代器的next()方法可以逐次地返回数据流中的每一项,当没有更多数据可用时,next()方法会抛出异常StopIteration。

(2)生成器(generator)也是一个迭代器,但是你只可以迭代他们一次,不能重复迭代,因为它并没有把所有值存储在内存中,而是实时地生成值。Yield是关键字,它类似于return,只是函数会返回一个生成器。对于类似资源的访问控制等场景,生成器显得很实用。其实最好的理解就是,每执行这个函数,yield都会保存结果值,打印的时候全部打印所有结果。


val = False

while not val:

print '这句话的意思是当val变量为假的时候死循环执行!'

def test():

yield "$1000"


13、zabbix如何去监控一个web服务器的性能?

答:监控指标:(1)打开网页的响应时间(2)每秒的下载速度(3)服务器返回的http状态码(4)验证用户密码登录是否成功

14、Python是强类型还是弱类型的语言?(这个东西我肯定要说错)

答:python是强类型。强弱是对类型而言的。强类型,你有一个值之后这个值是什么类型是确定的,比如n='1',n的类型是确定的(字符串),因此你不能在Python做n='3'm=n+1运算。而弱类型就不是这样的,值的类型可以在需要的时候再去确定,比如PHP里面你可以$n='3'; $m=$n+1,运算的时候'3'就可以当作整型来进行计算。       

参考文档:https://segmentfault.com/q/1010000002230156


15、python的动态性体现在哪?

答:(1)定义变量的时候无需指定它的数据类型,根据运行时具体情况确定。

(2)类class不提供private私有属性的关键字;无法定义常量;函数参数无类型

(3)python中的namespace是可以动态变化的,类的成员,类实例的成员都可以动态添加


16、python的namespace有几种?

答:(1)locals:函数内部的名字空间,一般包括函数的局部变量以及形式参数。

(2)enclosing function:在嵌套函数中外部函数的名字空间。

(3)globals:当前的模块空间,模块就是一些py文件。也就是说,globals()类似全局变量。

(4)__builtins__: 内置模块空间,也就是内置变量或者内置函数的名字空间。比如len()等函数的命名空间就是BIF命名空间

参考文档:http://www.jianshu.com/p/7f3fdd41096f


17、awk实现下列文本的转换?

[root@ssd tmp]# cat 5.sh 

1

D

2

E

3

V


[root@ssd tmp]# cat 5.sh |awk '{if(NR%2!=0)ORS=" ";else ORS="\n";print}'

1 D

2 E

3 V


18、怎么实现迭代器?迭代器比for循环有什么优势吗?(这个东西我怎么就记不住呢!)

答:迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。

next方法:返回迭代器的下一个元素

__iter__方法:返回迭代器对象本身

参考文档:http://www.cnblogs.com/kaituorensheng/p/3826911.html


19、python的三目运算符有吗? 怎么用一行代码实现三目运算?

答:python没有三目运算符。使用If-else可以模拟三目运算

>>> x, y = 50, 25

>>> small = x if x < y else y

>>> small

25

>>>


20、磁盘利用率快用尽时,如何看哪个目录使用的最多?

答:(1)find命令:find / -type d -size +2G -print 

(2)du -sh /etc   ##×××了,这个命令没记住,记成df了


21、python多线程与多进程有何区别?

答:多线程用来并行处理多个任务,以提高处理效率,在python中导入threading模块。join()方法的作用是必须在子线程运行完毕之后,父线程才能运行,即父线程被阻塞,因为如果父线程一旦运行完毕,子线程就不会再运行了。

(1)多线程可以共享全局变量(内存地址空间),当然锁问题也变成麻烦了;多进程独占资源,进程通信变得就比较麻烦了。

(2)多线程中,所有子线程的线程号相同;多进程中,不同的子进程进程号不同

(3)多线程只使用一颗CPU内核,属于IO密集型,比如在读取文件以及网络IO的时候使用多线程;多进程充分发挥多核的优势,属于计算密集型执行任务。



22、简要说明nova compute创建实例的大体步骤?(这个问题总结很多遍了,但是下面是最简单的描述)

答:(1)nova compute准备创建虚拟机实例的资源,比如根据flavor配置使用多大内存、多少颗CPU、多大磁盘?

(2)nova 从glance下载镜像文件,会对计算节点的_base目录进行缓存

(3)定义实例的XML文件,描述实例的元数据信息,以便下次可以正常启动

(4)nova请求neutron获取虚拟网卡的参数,实例得到诸如IP地址、MAC地址的信息,而后引导虚拟机。


23、虚拟机迁移如何防止调度到源节点的机制?

答:nova-compute 在做 migrate 的时候会检查目标节点,如果发现目标节点与源节点相同,会抛出 UnableToMigrateToSelf 异常。Nova-compute 失败之后,scheduler 会重新调度,由于有RetryFilter,会将之前选择的源节点过滤掉,这样就能选到不同的

计算节点了。


24、计算节点宕机,虚拟机实例还能运行吗?如果不能,怎么恢复呢?

答:虚拟机实例当然不能运行,如果只是nova-compute进程已经挂掉,Rebuild 可以恢复损坏的 instance。

但是计算节点宕机就不行,可以把虚拟机实例撤离到正常的计算节点上去。Evacuate可在 nova-compute 无法工作的情况下将节点上的instance 迁移到其他计算节点上。但有个前提: Instance 的镜像文件必须放在共享存储上。

流程:(只能在后台执行)

执行命令nova evacuate 主机名 --no-shared-storage -> 消息下发到nova-api -> nova-schedule筛选好主机 -> nova-compute分配资源,使用共享存储上的镜像文件 -> 启动instance

参考文档:http://www.mamicode.com/info-detail-1608057.html


25、网卡绑定的工作模式?(这个问题曾经在去年6月份才学过这点,现在都忘了,只记得3种,而且平衡二字又说不出来)

答:如果不同主机的网卡绑定的话,交换机也要进行配置链路聚合才行。总共7种,主要3种

(1)平衡模式

(2)主动备份

(3)广播

bond的好处:(1)提高整体带宽(2)负载均衡

参考文档:http://alanwu.blog.51cto.com/3652632/1095566


26、MySQL 5.5是单线程复制还是多线程复制?如果有大量的DML语句,如何解决主从延迟同步问题?(卧了个槽,这种

问题从来没思考过,又差点栽在数据库集群上了)

答:mysql从5.6才开始支持多线程复制。DML(一瞬间有点懵逼,反应好久才想起来是数据库操作语言)就是Insert、update等。

呵,我是记得到被思必驰狠狠虐过,固态硬盘做RAID阵列和分库分表记得最熟了。

MySQL的高可用知道多少?MMM、MHA架构熟悉吗?(日了狗,我又不是DBA,只听说过,又没做过)

答:只知道一主多从中,对从集群的HAProxy+Keepalived架构。



27、Linux Bridge与Open Vswitch有什么区别?(这段时间我没有全身心放在openstack上,知识尚缺,以后还会补充)

答:(1)基于vlan的隔离方式不同,ovs使用flow rule实现外部vlan以及内部vlan的转换

(2)iptables只能用于linux bridage而非OVS bridge,linux bridge 不支持GRE,但OVS支持。

(3)OVS的patch port用来连接集成网桥br-int和隧道网桥br-tun,而linux bridage使用veth对连接br-int和外部网桥br-eth1

(4)OVS的功能应该强于Linux Bridge,否则官网使用Linux Bridge,但是很多企业都用的是OVS。根据测试结果,Linux Bridge的性能(如网络吞吐量、虚拟之间的文件传输速度)略强于OVS。

(5)OVS 将各种功能都原生地实现在其中,而Linux Bridge依赖各种其他模块来实现各种功能。

参考文档:http://www.cnblogs.com/sammyliu/p/4985907.html


28、数据包流过OVS的过程?(先来个很简单的印象吧,其实OVS的很多桥还是比较麻烦的,脑壳里一定要想那个拓扑图)

答:1 VM实例instance的网络协议栈产生一个数据包并发送至实例内的虚拟网络接口VNIC,就是instance中的eth0.

2 这个数据包会传送到物理节点上的VNIC接口,就是vnet接口。

3 数据包从vnet NIC出来,到达桥(虚拟交换机)br100上.

4 数据包经过交换机的处理,从物理节点上的物理接口发出,如物理节点上的eth0.

5 数据包从eth0出去的时候,是按照物理节点上的二层交换机以及默认网关操作的,这个时候该数据包其实已经不受OVS的控制了



29、python要求输入一个列表,其中值为整数,输出为偶数,并且偶数所在的索引值也是偶数,例:输入[1,3,2,5,4,6],输出[2,4]

答:这个最大问题是要求随机输入,那么输入的列表就变成字符串型了,必须想个办法替换掉列表外边的单引号,使用eval方法


list1 = eval(input("请输入一个列表:"))  ##如果不加eval.那么list1就是<str>类型的。

list2 = []  ##eval将字符串str当成有效的表达式来求值并返回计算结果


def fun(list1):

             count = len(list1)

             for i in range(count):

                          if list1[i] % 2 == 0 and i%2 == 0:

                                                    list2.append(list1[i])

             print ('输出后的列表是:',list2)

             return list2

fun(list1)


30、分析简单代码,求输出结果。

class p(object):

             attr = 'a'

class c1(p):

             pass

class c2(p):

             attr = 'd'

class c3(p):

             pass 


print ('第1次',p.attr,c1.attr,c2.attr)

c1.attr = 'b'

print ('第2次',p.attr,c1.attr,c2.attr)

p.attr= 'c'

print ('第3次',p.attr,c1.attr,c2.attr,c3.attr)


答:#第1次 a a d

#第2次 a b d

#第3次 c b d c