MrC*_*ket 4 terminal perl signals kill-process
以下代码在从终端运行时表现如预期:
perl -e 'kill -2, $$; warn HERE, $/'
Run Code Online (Sandbox Code Playgroud)
它在发送SIGINT到"HERE"之前发送并死亡:
~# perl -e 'kill -2, $$; warn HERE, $/'
~# echo $?
130
~#
Run Code Online (Sandbox Code Playgroud)
问题:从shell脚本运行时,相同的代码无法终止自身PID :
~# cat 1.sh
perl -e 'kill -2, $$; warn HERE, $/'
~#
~# sh 1.sh
HERE
~#
~# echo $?
0
~#
Run Code Online (Sandbox Code Playgroud)
另一方面,用killshell 替换perl的工作正常:
~# cat 2.sh
perl -e 'qx/kill -2 $$/; warn HERE, $/'
~#
~# sh 2.sh
~#
~# echo $?
130
~#
Run Code Online (Sandbox Code Playgroud)
不太明白这里发生了什么,请帮忙..
首先,
kill -2, $$
Run Code Online (Sandbox Code Playgroud)
写得更好
kill 2, -$$
Run Code Online (Sandbox Code Playgroud)
一个更好的选择是
kill INT => -$$
Run Code Online (Sandbox Code Playgroud)
这些发送SIGINT到指定的进程组.
您的主要问题似乎是两个炮弹表现不同的原因.本节解释了这一点.
进程组代表一个应用程序.
当您从交互式shell启动程序时,它不是更大的应用程序的一部分,因此shell会为该程序创建一个新的进程组.
但是,脚本(即非交互式shell)创建的进程是脚本本身的同一应用程序的一部分,因此shell不会为它们创建新的进程组.
您可以使用以下方法将其可视化:
sh -i <<< 'perl -e '\''system ps => -o => "pid,ppid,pgrp,comm"'\''' 输出以下内容:
$ perl -e 'system ps => -o => "pid,ppid,pgrp,comm"'
PID PPID PGRP COMMAND
8179 8171 8179 bash
14654 8179 14654 sh
14655 14654 14655 perl
14656 14655 14655 ps
$ exit
Run Code Online (Sandbox Code Playgroud)
在交互模式下,perl是perl和ps节目组的负责人.
sh <<< 'perl -e '\''system ps => -o => "pid,ppid,pgrp,comm"'\''' 输出以下内容:
PID PPID PGRP COMMAND
8179 8171 8179 bash
14584 8179 14584 sh
14585 14584 14584 perl
14586 14585 14584 ps
Run Code Online (Sandbox Code Playgroud)
在非交互模式下,sh是perl和ps程序组的负责人.
您的失败是由于未将信号发送到进程组的负责人(即应用程序)而导致的.如果你检查过,kill报告的错误是ESRCH("没有这样的过程").
ESRCHpid或进程组不存在.[...]
要终止当前进程的进程组,请替换不正确的进程
kill INT => -$$ # XXX
Run Code Online (Sandbox Code Playgroud)
同
kill INT => -getpgrp() # Kill the application
Run Code Online (Sandbox Code Playgroud)
perl只需调用以下代码,您就可以成为自己的进程组的负责人:
setpgrp();
Run Code Online (Sandbox Code Playgroud)
测试:
$ sh <<< 'perl -e '\''system ps => ( -o => "pid,ppid,pgrp,comm" )'\'''
PID PPID PGRP COMMAND
8179 8171 8179 bash
16325 8179 16325 sh
16326 16325 16325 perl
16327 16326 16325 ps
$ sh <<< 'perl -e '\''setpgrp(); system ps => ( -o => "pid,ppid,pgrp,comm" )'\'''
PID PPID PGRP COMMAND
8179 8171 8179 bash
16349 8179 16349 sh
16350 16349 16350 perl
16351 16350 16350 ps
Run Code Online (Sandbox Code Playgroud)
这不是你通常想做的事情.
最后,Perl代码
kill INT => -$pgrp
Run Code Online (Sandbox Code Playgroud)
等效于kill命令行实用程序的以下调用:
kill -s INT -$pgrp
kill -INT -$pgrp
kill -2 -$pgrp
Run Code Online (Sandbox Code Playgroud)
您-在qx//程序中缺少,因此它将SIGINT发送到已识别的进程而不是已识别的程序组.