运维开发工程师在线评测:http://www.gtalent.cn/exam/interview/nsYteJ5wFfWkMdb2

首先问的是简历的项目,用到哪些技能。后面问的是编程语言的相关知识,1、装饰器是什么,2、迭代器是什么,区别是什么;3、用过哪些python框架、4、对多线程、协程的理解;5、什么是面向对象;6、什么是容器、隔离原理是什么、隔离用到哪些技术、cgroup、命名空间、同一物理机上不同容器通信方式、不同物理机的容器通信方式、会不会虚拟化;7、ps进程中状态码 D 是什么意思?僵尸进程是如何产生的?8、磁盘df看的话剩余20%可用空间,但是写不进去数据的原因是什么?
除此之外你还懂得哪些知识,包括自学,学校学的,项目做的。
下面一一作答:
1、装饰器是什么
2、迭代器是什么,区别是什么
3、用过哪些python框架
4、对多线程、协程的理解
python 多进程/多线程/协程 同步异步
python并发编程之多进程、多线程、异步、协程、通信队列Queue和池Pool的实现和应用
python多线程协程并行并发概念解惑
5、什么是面向对象;

首先我们从存储的层面去看,1.在python里面万物皆对象,不像java里面有什么基本数据类型,而python里面不存在基本数据类型,1,2,‘a’,等都是对象;2.所有的对象在内存里面都会开辟一块空间给它存储,解释器会根据不同的类型以及大小开辟不同的空间存储,在返回空间的存储地址以便于外界对这个对象的操作,3.对于整数和短小的字符,python会对其进行缓存,不会创建多个相同的对象,4.对于集合,列表等容器对象存储的其他对象仅仅是存储的其他对象的引用,并不是对象本身
面向对象三大机制:
1、封装:由面向过程乡面向过程推进,将同种对象的属性,方法抽象成为一个类,然后通过类的方法,属性来访问类。
2、继承:在封装的基础上,将同类事物继续抽象,在继承时,子类拥有父类的性和方法,并且可以有自己特有的属性和方法
3、多态:不同种对象之间的行为抽象。
 

面向对象的一些基本特征。
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
方法:类中定义的函数。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
6、什么是容器、隔离原理是什么、隔离用到哪些技术、cgroup、命名空间、同一物理机上不同容器通信方式、不同物理机的容器通信方式、会不会虚拟化

众所周知,docker通过linux 的namespace和CGroup技术为docker上的不同容器实现资源(文件系统、网络等)的隔离;但是在隔离的基础之上,在docker的使用中,我们可能需要实现容器和外部网络或者不同容器之间的通信(基于协作等关系)。今天想开始学习一下docker中不同容器之间的通信原理。
容器之间的通信可以分为单主机容器之间的通信和跨主机容器之间的通信。
7、ps进程中状态码 D 是什么意思?僵尸进程是如何产生的?

状态码详解
ps aux查看进程stat字段含义:
D 不可中断 Uninterruptible sleep (usually IO)
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程
< 高优先级
N 低优先级
L 有些页被锁进内存
s 包含子进程
+ 位于后台的进程组;
l 多线程,克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
ps命令个参数含义:
1)ps a 显示现行终端机下的所有程序,包括其他用户的程序。
2)ps -A 显示所有程序。
3)ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
4)ps -e 此参数的效果和指定"A"参数相同。
5)ps e 列出程序时,显示每个程序所使用的环境变量。
6)ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
7)ps -H 显示树状结构,表示程序间的相互关系。
8)ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
9)ps s 采用程序信号的格式显示程序状况。
10)ps S 列出程序时,包括已中断的子程序资料。
11)ps -t <终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。
12)ps u 以用户为主的格式来显示程序状况。
13)ps x 显示所有程序,不以终端机来区分。
14)ps -l 較長,較詳細的顯示該PID的信息

僵尸进程产生原因:
一个进程在调用exit命令结束自己的生命的时候,其实他并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,他的作用是使进程退出,但是也仅仅限于一个正常的进程变成了一个僵尸进程,并不能完全将其销毁)。在linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态信息供其他进程收集,除此之外,僵尸进程不再占有任何存储空间。他需要他的父进程来为他收尸,如果他的父进程没有安装SIGCHLD信号处理函数调用wait 或 waitpid() 等待子进程结束,有没有显式忽略该信号,那么它就一直保持僵尸状态,如果这时候父进程结束了,那么init进程会自动接手这个子进程,为他收尸,他还是能被清除掉的。但是如果父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是系统中为什么有时候会有很多的僵尸进程。
避免zombie的方法
1)在svr4中,如果调用signal或是sigset将SIGCHLD的配置设置为忽略,则不会产生僵死子进程。另外,使用svr4版本sigaction,则可设置SA_NOCLDWAIT标志以避免子进程僵死。Linux中也可以使用这个,在一个程序开始调用这个函数signal(SIGCHLD,SIG_IGN);
2)调用fork两次
3)用waitpid等待子进程返回。
 

如何杀死僵尸进程呢?
一般僵尸进程很难直接kill掉,不过您可以kill僵尸爸爸。父进程死后,僵尸进程成为”孤儿进程”,过继给1号进程init,init始终会负责清理僵尸进程.它产生的所有僵尸进程也跟着消失。
ps -e -o ppid,stat | grep Z | cut -d” ” -f2 | xargs kill -9
或
kill -HUP `ps -A -ostat,ppid | grep -e’^[Zz]‘ | awk ’{print $2}’`
当然您可以自己编写更好的shell脚本,欢迎与大家分享。
我将nova-novncproxy stop后再start,僵尸进程即消失,问题解决。
另外子进程死后,会发送SIGCHLD信号给父进程,父进程收到此信号后,执行waitpid()函数为子进程收尸。就是基于这样的原理:就算父进程没有调用wait,内核也会向它发送SIGCHLD消息,而此时,尽管对它的默认处理是忽略,如果想响应这个消息,可以设置一个处理函数。
如何避免僵尸进程呢?
处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下 可以简单地将 SIGCHLD信号的操作设为SIG_IGN。
signal(SIGCHLD,SIG_IGN);
这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程
或者
用两次fork(),而且使紧跟的子进程直接退出,是的孙子进程成为孤儿进程,从而init进程将负责清除这个孤儿进程。

 

8、磁盘df看的话剩余20%可用空间,但是写不进去数据的原因是什么?
在磁盘上建立文件的时候需要两个条件:
1.磁盘空间,
2.需要有inode 任何一个满了都回提示设备没有空间。
此处具体原因是由于磁盘的inode分配完了,导致提示磁盘满。
可以使用df -ia查看磁盘详细信息。

解决:/data/cache目录中存在数量非常多的小字节缓存文件,占用的Block不多,但是占用了大量的inode。删除一些无用的文件或者文件夹,释放inode。

inode译成中文就是索引节点,每个存储设备(例如硬盘)或存储设备的分区被格式化为文件系统后,应该有两部份,
一部份是inode,而inode呢,就是用来存储这些数据的信息,这些信息包括文件大小、属主、归属的用户组、读写权限等。
另一部份是Block,Block是用来存储数据用的。inode为每个文件进行信息索引,所以就有了inode的数值。操作系统根据指令,能通过inode值最快的找到相对应的文件。

正确解决方法:

1、删除/data/cache目录中的部分文件,释放出/data分区的一部分inode,特别要留意那些spool出来的文件,这种文件一般会占用比较多的节点,因为比较小而且零碎,同时要多留意日志文件信息等。
2 、用软连接将空闲分区/opt中的newcache目录连接到/data/cache,使用/opt分区的inode来缓解/data分区inode不足的问题:
ln -s /opt/newcache /data/cache
3、更换服务器,用高配置的服务器替换低配置的服务器。很多时候用钱去解决问题比用技术更有效,堆在我办公桌上5台全新的 DELL PowerEdge 2950 服务器即将运往IDC机房。一般不建议
关于磁盘的inode满100%--i节点大爆发

原因:
通常是发现磁盘没有满但是无法写入文件。提示“no space left on device”
用df -i 查看,应该会发现相应的分区是100%
一般都是crontab的job有问题,造成/var/spool/clientmqueue中产生许多的零碎文件。
处理方法:
*用rm -rf 会不能删除,并会有相应的提示,大意是参数太多。
可以用多种方法,这里提及一个我随便写的,在/var/spool/clientmqueue/下执行命令:“lsattr ./|awk -F"/" ‘{print $3}’|xargs -i rm -rf {}”用lsattr列出./下面的文件名的属性,用awk取出名字,然后rm -rf
还有一个方法比较普遍的使用:“find /var/spool/clientmqueue/ -type f -exec rm {} ;”或者在/var/spool/clientmqueue/目录下“find ./ -exec rm {} ;”
将crontab中没有定向输出的行都在最后加上“> /dev/null 2>&1”,在删除的过程中操作。或者先停止crontab,加上重定向。

【王老师说运维】:运维之linux基础入门实战(http://www.codeforest.cn/course/443)