两种情况:
在CLI中运行命令
[1] 139781
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
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)创建了两个 孩子(139780& 139781)和kill -INT可以打断 139780成功。
现在我们编写了一个ksh脚本来完成几乎相同的工作
#!/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
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分叉139789和139789分叉139791,在这种情况下, a.sh调用kill命令将SIGINT发送到139791,但失败了。
为什么a.sh不会发送' zfs发送'处理? (在bash脚本中,a.sh分叉发送和接收进程)? 为什么杀死-s INT未能中断' zfs发送'处理? 如何在ksh脚本中中断发送过程?
非常感谢。
答案 0 :(得分:0)
你有一个嵌套分叉的原因是因为你正在使用'&' - 管理管道进程,这意味着管道中的第一个命令分叉第二个,而不是shell进程。不幸的是,我目前没有zfs可以使用,因此我无法检查zfs在进程组中的播放方式,但嵌套分叉是管道后台进程的默认行为。
SIGINT 无法处理您的父进程,因为符合POSIX标准的父进程在终止自身之前只会等待 SIGCHLD ,而忽略 SIGINT 和 SIGQUIT 。
如果您使用 SIGTERM :
/usr/bin/kill -s TERM $pid
您的进程将处理信号,并正常终止。 在“zfs'”的缺席中,我使用'尾部模拟了您的管道流程:
#!/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"
希望有所帮助。