生人勿近之 Linux 里养僵尸 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
felix021
V2EX    推广

生人勿近之 Linux 里养僵尸

  •  
  •   felix021 2020-07-11 13:10:01 +08:00 9108 次点击
    这是一个创建于 1922 天前的主题,其中的信息可能已经有所发展或是发生改变。

    zoombie-banner.jpg

    Linux 里养僵尸是怎么回事呢? Linux 相信大家都很熟悉,但是 Linux 里养僵尸是怎么回事呢,下面就让小编带大家一起了解吧。

    - 1-

    上一篇挖了个 SIGHUP 的坑,这篇试着填一下。

    之前在《程序员面试指北:面试官视角》里面说过,在结构化面试中,我们会从各个方向去考查候选人,其中之一是操作系统。

    上篇介绍了一套题,我还有另一套,一般这么开场:

    在终端下启动一个命令,如果在命令结束前关掉终端,它还能正常运行吗?

    又是一道送分题.jpeg

    - 2-

    这其实是一个很常见的 case,但凡 Linux 或者 Mac 用得多一点,都会遇到。

    在我还是一个穷酸学生的 2009 年,每个月都需要支付 20 元巨款(当时能买 3 根鸭脖),通过一个禁止分享网络的认证客户端接入校园网。

    为了共建和谐宿舍 <del>节省网费</del> ,我历经千辛万苦,交叉编译开源的 Linux 认证客户端,集成到固件里,并刷到了我的 NETGEAR 路由器上。

    然后山水 BBS 的 Linux 版主把我的帖子置顶了 11 年。<del>可见他有多痛恨禁止共享网络</del>

    这么一回忆,感觉自己的共享经济思维真是前卫,当时怎么就没想到去搞共享单车呢?

    ofo 押金.jpeg

    扯远了,在捣腾的过程中,我就踩了这么个坑:当我 ssh 到路由器上、刚启动认证时,能够正常联网;但是退出 ssh 后一会,网就断了。

    经过一番捣腾后发现,只要一退出 ssh,认证程序就凉了,而不是继续在后台保持和认证服务器的通信。

    - 3 -

    所以前面那个问题,我以为大部分候选人应该会回答“否”,但没想到竟然还有不少人回答“是”。

    其实回答“是”也没什么错,因为确实也有些命令不会随着终端关闭而结束。

    问题是当我追问当时执行的是什么命令时,候选人往往又说不出个所以然来。

    are-you-ok.jpeg

    (借学长的表情一用)

    然后我就感到很强的挫败感:这不按剧本来,没法问了啊……只好换题。

    当然大部分候选人确实被坑过,于是我可以接着问:

    如果确实需要在后台继续执行命令怎么办呢?

    有些人只记得要在后面加个 & ;但也有不少人知道前面还得加个 nohup,就像这样:

    $ nohup python process.py & [1] 1806824 nohup: ignoring input and appending output to 'nohup.out' 

    注:其实我更喜欢 screen (或 tmux ),偶尔也用 setsid 。

    然后就可以放心地关闭终端<del>开始放羊</del> 了。

    但我的套题还没结束:为什么加上 nohup 就可以让进程在后台继续运行呢?

    王宝强.png

    (这表情熟悉吗)

    - 4 -

    铺垫了这么多,总算是可以开始填坑了。

    答案其实很好找,man nohup 就能看到:

    ThenohuputilityinvokesutilitywithitsargumentsandatthistimesetsthesignalSIGHUPtobeignored

    nohup 工具在启动命令的同时会将 SIGHUP 信号设置为忽略。 而关于 SIGHUP,Wikipedia 原文是这样介绍的:

    On POSIX-compliant platforms, SIGHUP ("signal hang up") is a signal sent to a process when its controlling terminal is closed.

    wikipedia.org/wiki/SIGHUP

    对于 POSIX 兼容的平台(如 Unix 、Linux 、BSD 、Mac ),当进程所在的控制终端关闭时,系统会给进程发送 SIGHUP 信号( Signal Hang Up,挂断信号)。

    为什么叫 SIGHUP 呢?(严正申明:这一问不在套题里[doge])

    我们知道,在上古时代,捉 bug 就已经是码农的必备技能(更准确地说是 moth )。

    first-actual-case-of-bug.jpeg

    (我总觉得这个图是假的)

    到了远古时代,他们不再需要去机房,通过基于 RS-232 协议的串行线路连接到大型机的终端上,就可以开始收福报。

    收完福报,程序员通知自己的猫( modem )挂断( Hang Up )连接;大型机的 OS 检测到连接断开,就会给进程发送信号 所以这信号被称为 SIGHUP 。

    这果然是毫无卵用的知识啊。

    然并卵.jpg

    - 5 -

    很多同学在操作系统的课程上学习了“进程间的通信方式有信号、管道、消息队列、共享内存……”,但是对信号到底是个什么东西,并没有现实的概念。

    课堂教学的理论和实践往往是割裂的,在此特别推荐《 Unix 环境高级编程》(简称 APUE )。

    APUE 在 1.9 - 信号 中写到:信号是通知进程已发生某种条件的一种技术。

    而在 Linux/Unix 下,进程对信号的处理有三种选择:

    • 按系统默认方式处理
    • 提供一个回调函数
    • 或忽略该信号(有些信号例外,不允许被忽略)

    以 SIGHUP 信号为例,系统默认处理方式就是结束进程

    当然终端下打开的第一个进程通常都是 shell (例如 bash )。shell 会给 SIGHUP 信号注册一个回调函数,用于给该 shell 下所有的子进程发送 SIGHUP 信号,然后再主动退出。

    对于求生欲很强的程序(例如 nohup ),可以主动选择忽略该信号

    sighup 抢救.png

    有一些进程本来就被设计成在后台运行,不需要控制终端,因此它们将SIGHUP 挪作它用,一个常见的用法就是重新读取配置文件(例如 Apache 、Nginx ),上篇提到的 logrotate 正是利用了这一点。

    终于填完了坑。

    - 6 -

    说了这么多都还是纸上谈兵,实操中如何主动忽略 SIGHUP 呢?

    实际上也很简单,使用 Linux 的 signal 系统调用即可:

    #include <signal.h> #include <unistd.h> int main() { signal(SIGHUP, SIG_IGN); sleep(1000); return 0; } 

    不妨试试看,编译运行起来,即使关闭终端,它也会在后台继续运行。

    signal 也可以用于指定回调函数(或重置为系统默认处理方式),这里就不展开了,感兴趣的同学可以参考 APUE 里的代码,以及阅读 signal 的 manual 。

    使用回调函数还需要注意一个坑:

    由于回调函数可能在任意时刻被触发,因此要避免调用不可重入的函数(典型如 printf )。常见的做法是 set 一个 flag,然后在程序的主循环中检测该 flag,再按需执行相应任务。

    - 7 -

    SIGHUP 只是常见的一个信号,在 Linux 下,信号还有大量其他的场景和应用。

    当你按下 Ctrl + C,就是给进程发送了一个 SIGINT 信号。

    当你执行 kill -TERM $PID,就是给进程发送了一个 SIGTERM 信号。可能和你期望有出入的是,SIGTERM 是可以被进程忽略的。所以有时候你得用 SIGKILL (kill -9) 。

    你还可以使用可自定义的 SIGUSR1 、SIGUSR2 、SIGURG 来实现一些功能,比如《踩坑记#2:Go 服务锁死》中提到 Golang 在其 goroutine 调度中使用了 SIGURG 。

    - 8 -

    这次就不总结了,最后再用一个和信号有关的 case 收尾。

    Linux 内核会为每一个进程分配一个 task_struct 结构体,用于保存进程的相关信息。

    在进程死亡后,系统会发送一个 SIGCHLD 信号给它的父进程。

    正确的父进程实现,通常应当使用 wait 系统调用来给子进程收尸 父进程往往需要知道子进程结束这个事件,而且可能还需要得知其退出原因( exit code )。

    然后内核才会将对应的 task_struct 释放。

    如果父进程没有收尸,task_struct 里的 state 会一直保持为 EXIT_ZOMBIE,这时在 ps 或 top 等命令里,就可以看到该进程的状态为 Z,而且无法被 kill 。

    这就是所谓的僵尸进程,这时候你找九叔都没用。

    林正英.jpeg

    (大半夜找这图还挺渗人的)

    所以 Linux 里养僵尸,其实就是子进程死了父进程不收尸,大家可能会很惊讶 Linux 里怎么会养僵尸呢?但事实就是这样,小编也感到非常惊讶。

    这就是关于 Linux 里养僵尸的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!


    推荐阅读

    欢迎关注

    weixin2s.png

     
    55 条回复    2020-07-13 14:19:08 +08:00
    pcbl
        1
    pcbl  
       2020-07-11 13:27:47 +08:00 via iPhone   2
    提个建议,铺垫部分比例过高,有点抓不住重点
    cjpjxjx
        2
    cjpjxjx  
       2020-07-11 13:28:48 +08:00   5
    开头就是老营销号了
    Jirajine
        3
    Jirajine  
       2020-07-11 13:30:54 +08:00 via Android   4
    felix021
        4
    felix021  
    OP
       2020-07-11 13:34:02 +08:00
    @pcbl 主要是这篇内容比较简单,就随便扯扯没什么乱用但可能有点意思的东西……
    felix021
        5
    felix021  
    OP
       2020-07-11 13:34:51 +08:00
    @cjpjxjx 结尾也是[doge]
    ochatokori
        6
    ochatokori  
       2020-07-11 13:35:24 +08:00 via Android   2
    看了开头,营销号
    拉黑了
    felix021
        7
    felix021  
    OP
       2020-07-11 13:36:49 +08:00
    @Jirajine 打开一看是订阅了好多年的技术大佬,不过“有些内容”不太合我口味……
    yangbonis
        8
    yangbonis  
       2020-07-11 13:41:55 +08:00 via iPhone
    说了僵尸,不讲下 reaper 吗
    k1z
        9
    k1z  
       2020-07-11 13:44:06 +08:00
    结尾才是精髓,一看就是老编了
    imnaive
        10
    imnaive  
       2020-07-11 13:54:17 +08:00
    写得很有趣,也有代码讲解,为啥要喷成营销号。
    felix021
        11
    felix021  
    OP
       2020-07-11 13:59:37 +08:00 via Android
    @imnaive 他们是开玩笑,开头结尾是我特地找营销号生成器生成的
    felix021
        12
    felix021  
    OP
       2020-07-11 14:01:14 +08:00 via Android
    @yangbonis 年龄太大,只看过九叔系列……
    b0ttle
        13
    b0ttle  
       2020-07-11 14:24:14 +08:00   1
    武大学长啊哈哈,现在校园网改成网页验证了
    JB18CM
        14
    JB18CM  
       2020-07-11 14:27:56 +08:00   3
    营销号...
    已拉黑了
    Nich0la5
        15
    Nich0la5  
       2020-07-11 14:32:35 +08:00 via Android
    没必要 内容挺好的开头结尾膈应人
    felix021
        16
    felix021  
    OP
       2020-07-11 14:36:45 +08:00 via Android
    @Nich0la5 哈哈哈 这是我的一点恶趣味
    viruser
        17
    viruser  
       2020-07-11 14:44:30 +08:00
    @Jirajine 不如看 APUE 和老外的文章,这个博主竟然还在相信 tor+代理能保证安全,让我对他的技术水平产生了怀疑...
    viruser
        18
    viruser  
       2020-07-11 14:46:49 +08:00
    @viruser 不是说的本帖的楼主,是那个老博客的博主...
    jydeng
        19
    jydeng  
       2020-07-11 14:52:28 +08:00
    放这么多图干嘛?
    ysmood
        20
    ysmood  
       2020-07-11 15:05:27 +08:00   1
    分享下我们处理 zombie 的库: https://github.com/ysmood/leakless

    具体用到了这个项目: https://github.com/go-rod/rod
    yujiang
        21
    yujiang  
       2020-07-11 15:15:26 +08:00 via Android
    讲技术放锤子表情包?
    raaaaaar
        22
    raaaaaar  
       2020-07-11 15:21:32 +08:00 via Android
    @yujiang #21 大概每个人都有自己的风格吧。。
    sunrsewestern
        23
    sunrisewestern  
       2020-07-11 15:21:35 +08:00
    看到 20 块钱和鸭脖就猜是我武的
    jiangzhuo
        24
    jiangzhuo  
       2020-07-11 15:26:28 +08:00   1
    发现全篇有用的跟标题有关的就最后倒数第二段半句
    “所以 Linux 里养僵尸,其实就是子进程死了父进程不收尸”
    建议把这句放到开头……
    felix021
        25
    felix021  
    OP
       2020-07-11 15:31:57 +08:00 via Android
    @jiangzhuo 原计划是放开头的,但后面就没法写了。。。标题党一次也是不容易,下次再试试其他套路。
    hxsf
        26
    hxsf  
       2020-07-11 15:38:06 +08:00
    建议发到推广节点
    reus
        27
    reus  
       2020-07-11 15:39:25 +08:00   3
    @yujiang 信不信楼主发一贴《放表情包容易被喷,不放的没热度》
    luckycatio
        28
    luckycatio  
       2020-07-11 15:51:38 +08:00
    @viruser 请问按他的使用方式哪里会出现安全隐患?
    felix021
        29
    felix021  
    OP
       2020-07-11 15:53:11 +08:00 via Android
    @reus 不信
    felix021
        30
    felix021  
    OP
       2020-07-11 15:54:12 +08:00 via Android
    @luckycatio 瞎猜,比如 tor 节点本身可能是钓鱼的,貌似有过这样的干扰。
    XanderChen
        31
    XanderChen  
       2020-07-11 16:13:43 +08:00
    前排围观。

    另外文章可以转载吗
    felix021
        32
    felix021  
    OP
       2020-07-11 16:16:01 +08:00 via Android
    @XanderChen 可以的,标明作者和出处就行
    whileFalse
        33
    whileFalse  
       2020-07-11 18:03:22 +08:00
    虽然看到最后有些不适,但还是学到了知识。
    tlday
        34
    tlday  
       2020-07-11 18:30:32 +08:00
    又是你,上次说你发的技术文章干货密度太低,这次说你发的频率太高吧,表情包太多不看,已 block 。
    lwp2070809
        35
    lwp2070809  
       2020-07-11 18:48:40 +08:00 via Android
    在 block 楼主之前可以看看楼主之前发的文章
    不过就这篇文章而言我也是非常讨厌的,看到第二张图片我就直接拉下来不看了
    reus
        36
    reus  
       2020-07-11 19:00:20 +08:00
    实话说,这种文章真的很水
    你看这本 2002 年出版的书,就有讲 nohup 了: http://www.oreilly.com.cn/index.php?func=book&isbn=7-5083-0947-2
    18 年前啊,这种根本就没什么好说的东西,还加表情包来注水
    稍微有点现代的环境都不用 nohup 的了,还拿来面试,实在是无语
    felix021
        37
    felix021  
    OP
       2020-07-11 19:05:28 +08:00 via Android
    @reus 我也觉得挺水的,但您这逻辑就有意思了,因为十几年前别人写过所以就不应该再写了?那您这辈子大概啥也不用写了。我自己写得开心就好,您看不惯的话 block 就好了,不劳烦帮我顶贴。
    felix021
        38
    felix021  
    OP
       2020-07-11 19:14:41 +08:00 via Android
    @whileFalse 最后那两句(包括开头)其实是吐槽这种风格的营销号,有些人能理解我的用意,读出了乐趣,有些人不理解,读出了不适,这个我确实没啥办法,这层意思如果写在原文里味道就不对了。
    luckycatio
        39
    luckycatio  
       2020-07-11 20:21:10 +08:00
    @felix021 钓鱼节点从 tor 发明的时候开始就一直存在,就算 3 跳连的都是蜜罐节点,也只能知道你的代理 IP,和访问的网站,这样如何抓到在国内的使用者?
    felix021
        40
    felix021  
    OP
       2020-07-11 20:33:00 +08:00
    @luckycatio 不了解,所以我说我是瞎猜。。我对 tor 不太熟悉, @viruser 同学来解个惑?
    cvbnt
        41
    cvbnt  
       2020-07-11 20:37:07 +08:00 via Android
    @viruser tor+代理只是基础中的基础,不是 tor+代理能保证安全,而是保证安全的环节中 tor+代理不可少,除此之外还有身份隔离外加虚拟环境方面的考量,真有问题人早就被抓了
    lxilu
        42
    lxilu  
       2020-07-11 22:39:51 +08:00   1
    建议缩小图片,优化用户体验。占了半屏!占几行为妥。
    eallion
        43
    eallion  
       2020-07-11 22:42:18 +08:00 via Android
    在 v2 拉黑了还出现在 feed 里…
    felix021
        44
    felix021  
    OP
       2020-07-11 22:45:09 +08:00 via Android
    @lxilu 多谢建议,下次截图弄小点,在微信里可以调整尺寸,v2 直接按原图尺寸展示确实比较蛋疼
    smilingsun
        45
    smilingsun  
       2020-07-11 22:50:08 +08:00
    有意思!
    ryd994
        46
    ryd994  
       2020-07-12 00:07:55 +08:00 via Android   2
    @livid /go/推广
    ichao1214
        47
    ichao1214  
       2020-07-12 00:20:39 +08:00 via Android
    果然难度降低,友好了很多。想看不收尸的情况。
    stevefan1999
        48
    stevefan1999  
       2020-07-12 02:02:55 +08:00   2
    什有程,情可以看看 The Collapse of the UNIX Philosophy
    https://kukuruku.co/post/the-collapse-of-the-unix-philosophy/
    ```
    This quote is from the early UNIX manual. Even then, the existence of zombie processes was considered a bug. But this bug was later simply forgotten. Needless to say, this problem was later solved anyway. So, there are tools in modern GNU/Linux for killing zombie processes, but few people know about them. You can’t get rid of a zombie with a regular kill. Everybody says about the existence of zombie processes that “It’s for design”.
    ```
    就是 bug 成了 feature
    vk42
        49
    vk42  
       2020-07-12 03:08:04 +08:00
    倒不是反对用比较调侃的方式科谱,不过文中的调侃有点生硬看着比较尬……
    另外关于最后父进程没有 wait()的,只要父进程结束了 init 进程也会回收僵尸的
    shanlanlan
        50
    shanlanlan  
       2020-07-12 04:06:26 +08:00
    Linux 养僵尸养僵尸是怎么回事呢? Linux 养僵尸相信大家都很熟悉,但是 Linux 养僵尸养僵尸是怎么回事呢,下面就让小编带大家一起了解吧。
       Linux 养僵尸养僵尸,其实就是有鬼,大家可能会很惊讶 Linux 养僵尸怎么会养僵尸呢?但事实就是这样,小编也感到非常惊讶。
      这就是关于 Linux 养僵尸养僵尸的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!
    mageemeng
        51
    mageemeng  
       2020-07-12 08:13:30 +08:00
    看了一眼地址栏,的确是 V 站啊
    felix021
        52
    felix021  
    OP
       2020-07-12 09:53:12 +08:00 via Android
    @vk42 嗯 孤儿进程的情况这篇没有展开讲
    ydpro
        53
    ydpro  
       2020-07-12 11:36:43 +08:00
    厉害了,僵尸进程水出了花
    Zien
        54
    Zien  
       2020-07-12 11:42:26 +08:00 via Android   1
    开头一看就知道是武大华科了哈哈
    viruser
        55
    viruser  
       2020-07-13 14:19:08 +08:00   1
    @cvbnt 主要是我之前看到 FBI 使用钓鱼节点来获取加密流量的流向,还有就是网上讲的 gov 可以从 ISP 那获取加密流量的流向,所以觉得只靠这两个是完全达不到匿名的。至于为什么不抓他,有和他相同思想的人在微博豆瓣上都活得好好的,不缺他一个 233
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2610 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 15:33 PVG 23:33 LAX 08:33 JFK 11:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86