如何在Linux中养僵尸?Linux相信大家都不陌生,但是Linux养僵尸是怎么一回事呢,就让小编带大家一起来了解一下吧。-1-上篇文章挖了一个SIGHUP的坑,本文会尝试填上。我之前在《程序员面试指北:面试官视角》里说过,在结构化面试中,我们会从各个方向考察候选人,其中之一就是操作系统。上一篇介绍了一组问题,我还有一组,通常是这样开始的:在终端下启动一个命令,如果在命令结束前关闭终端,是否还能正常工作?-2-这其实是一个很常见的case,但是Linux或者Mac用多了就会遇到。2009年我还是个穷学生,每个月都要交20元的巨款(当时可以买3个鸭脖),通过禁止网络共享的认证客户端访问校园网。为了建设和谐宿舍,节省网络费用,我历经千辛万苦,交叉编译了开源的Linux认证客户端,集成到固件中,刷入了我的网件路由器。然后山水论坛的Linux版主把我的帖子置顶了11年。可见他对禁止共享网络的记忆有多么厌恶,觉得他的共享经济思想真是前卫。为什么当时他没有想到共享单车?扯远了,在闹事的过程中,踩了这样一个坑:当我ssh到路由器上,刚开始认证的时候,可以正常上网;但是退出ssh一段时间后,网络就断开了。一番折腾后发现,只要一退出ssh,认证程序就变冷了,而不是继续在后台与认证服务器保持通信。-3-所以对于前面的问题,我以为大部分考生都会回答“No”,没想到很多人会回答“Yes”。其实,回答“是”并没有错,因为确实有一些命令在终端关闭的时候并没有结束。问题是,当我问当时正在执行什么命令时,应聘者往往说不出原因。(借用学长的表情)然后我就感觉到了强烈的挫败感:这不是按照剧本来的,所以我不能问……我得换个问题。当然,大部分考生确实中招了,所以我可以继续追问:真的需要在后台继续执行命令怎么办?有些人只是记得在末尾添加一个&;但是很多人都知道nohup必须加在前面,像这样:$nohuppythonprocess.py&[1]1806824nohup:ignoringinputandappendingoutputto'nohup.out'注:我其实更喜欢screen(或tmux),偶尔设定。然后你就可以安全地关闭终端并开始放羊了。但是我的这组问题还没有结束:为什么用nohup进程还能在后台继续运行?(这个表情是不是很眼熟)-4-铺垫了那么多,终于可以开始填坑了。答案其实很容易找到,mannohup可以看到:nohuputilityinvokesutilitywithitsargumentsandatthistimesetsthesignalSIGHUPtobeignorednohup工具会在启动命令时将SIGHUP信号设置为忽略。关于SIGHUP,维基百科原文是这样介绍的:OnPOSIX-compliantplatforms,SIGHUP("signalhangup")是一个进程在它的控制终端关闭时发送的信号。wikipedia.org/wiki/SIGHUPiscompatiblewithPOSIXPlatforms(如Unix、Linux、BSD、Mac),当进程所在的控制终端关闭时,系统会向进程发送一个SIGHUP信号(SignalHangUp,挂断信号)。为什么叫SIGHUP?(郑重声明:本题不入题集[doge])我们知道,在古代,抓bug一直是码农的必备技能(更准确地说,是飞蛾扑火)。(我一直觉得这张图是假的)在古代,他们不再需要去机房,通过基于RS-232协议的串口线连接到主机的终端就可以开始接受祝福了。收到好消息后,程序员通知他的调制解调器挂断连接;当主机操作系统检测到连接断开时,它会向进程发送一个信号——所以这个信号叫做SIGHUP。这真是无用的知识。-5-很多同学在操作系统课上都学过“进程间通信方式包括信号、管道、消息队列、共享内存……”,但是对于什么是信号却没有一个现实的概念。课堂教学的理论和实践往往是分离的,这里特别推荐《Unix环境高级编程》(简称APUE)。APUE在1.9-Signal中写道:信号是一种通知进程某个条件已经发生的技术。在Linux/Unix下,进程对信号的处理有三种选择:根据系统默认的方法,提供回调函数或者忽略信号(除了一些信号,不允许忽略)。以SIGHUP信号为例,系统默认的处理方式是endprocess。当然,终端下第一个打开的进程一般都是shell(比如bash)。shell会为SIGHUP信号注册一个回调函数,用于向shell下的所有子进程发送SIGHUP信号,然后主动退出。对于生存需求强烈的程序(比如nohup),可以主动选择忽略这个信号。有些进程设计为在后台运行,不需要控制终端,因此它们将SIGHUP用于其他目的。一个常见的用法是重新读取配置文件(比如Apache、Nginx)。上一篇文章中提到的logrotate正是利用了这一点。终于把坑填上了。-6-说了这么多,还是纸上谈兵,实践中如何主动忽略SIGHUP?其实也很简单,使用Linux的signal系统调用即可:#include
