【问题标题】:kill -INT pid can not kill process inside ksh scriptkill -INT pid 不能杀死 ksh 脚本中的进程
【发布时间】:2023-03-18 14:13:01
【问题描述】:

两种情况:

  1. 在 CLI 中运行命令

    zfs 发送 rpool/fs@snap | zfs recv rpool/fs1@snap &

    [1] 139781

    ps -ef|grep zfs

        root 139783 119679   0 23:28:34 kz/term/2    0:00 grep zfs
        root 139781 119679   3 23:28:30 kz/term/2    0:02 zfs recv rpool/fs1@snap
        root 139780 119679   3 23:28:30 kz/term/2    0:03 zfs send rpool/fs@snap
    

    杀死 -INT 139780

    ps -ef|grep zfs

        root 139781 119679   7 23:28:30 kz/term/2    0:08 zfs recv rpool/fs1@snap
        root 139785 119679   0 23:28:42 kz/term/2    0:00 grep zfs
    

我们可以看到当前的shell(119679)创建了两个 children(139780&139781),并且 kill -INT 可以中断 139780成功。

  1. 现在我们编写了一个 ksh 脚本来完成几乎相同的工作

    猫 a.sh

    #!/usr/bin/ksh -p
    echo $$
    zfs send rpool/fs@snap | zfs recv rpool/fs1@snap &
    pid=$(ps -ef|grep 'zfs send rpool/fs@snap'|grep -v grep | awk '{print $2}')
    /usr/bin/kill -s INT $pid
    sleep 1
    ps -ef|grep zfs
    

    ./a.sh

    139788
        root 139791 139789   1 23:30:57 kz/term/2    0:01 zfs send rpool/fs@snap
        root 139789 139788   1 23:30:57 kz/term/2    0:01 zfs recv rpool/fs1@snap
        root 139798 139788   0 23:30:58 kz/term/2    0:00 grep zfs
    

现在 a.sh fork 139789,而 139789 fork 139791,在这种情况下, a.sh 调用 kill 命令将 SIGINT 发送到 139791,但是失败了。

为什么不 a.sh 分叉“zfs 发送”进程? (在 bash 脚本中,a.sh 分叉了发送和接收进程)? 为什么 kill -s INT 未能中断“zfs 发送”进程? 如何中断 ksh 脚本中的发送过程?

非常感谢。

【问题讨论】:

    标签: signals ksh sigint


    【解决方案1】:

    你有一个嵌套分叉的原因是因为你使用'&' - 后台处理管道进程,这意味着管道中的第一个命令分叉第二个,而不是 shell 进程。不幸的是,我目前没有 zfs 可玩,所以我无法检查 zfs 在进程组中的播放方式,但嵌套分叉是管道后台进程的默认行为。

    SIGINT 不会在您的父进程上工作,因为符合 POSIX 的父进程只会等待 SIGCHLD 后自行终止,而忽略 SIGINTSIGQUIT

    如果您使用 SIGTERM 代替:

    /usr/bin/kill -s TERM $pid 
    

    您的进程将处理信号,并优雅地终止。 在没有“zfs”的情况下,我用“tail”模拟了您的管道进程:

    #!/usr/bin/ksh -p
    echo $$
    #zfs send rpool/fs@snap | zfs recv rpool/fs1@snap &
    tail -f foo | tail -f &
    #pid=$(ps -ef|grep 'zfs send rpool/fs@snap'|grep -v grep | awk '{print $2}')
    pid=$(ps -ef|grep "t[a]il"| awk '{print $2}')
    #/usr/bin/kill -s INT $pid
    /usr/bin/kill -s TERM $pid
    echo $?
    sleep 1
    ps -ef|grep "t[a]il"
    

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 2021-09-29
      • 2017-08-04
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      相关资源
      最近更新 更多