V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
felix021
V2EX  ›  推广

生人勿近之 Linux 里养僵尸

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

    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 就能看到:

    The nohup utility invokes utility with its arguments and at this time sets the signal SIGHUP to be ignored

    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 大概每个人都有自己的风格吧。。
    sunrisewestern
        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   ·   实用小工具   ·   2734 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:06 · PVG 16:06 · LAX 00:06 · JFK 03:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.