yae*_*ael 5 linux bash kill exit
在我的 Bash 脚本中,为了退出 Bash 脚本,我使用了以下语法:
kill -PIPE $$
Run Code Online (Sandbox Code Playgroud)
我使用它是因为有时在脚本的函数或内部 shell 中,它exit 1并没有真正从 Bash 脚本中退出。
所以我用kill代替exit 1.
看起来
exit 1
Run Code Online (Sandbox Code Playgroud)
和
kill -PIPE $$
Run Code Online (Sandbox Code Playgroud)
几乎相等。我的假设是真的吗?
其次 - about kill -PIPE $$,使用该语法是否存在风险?
Sté*_*las 10
exit 1 使用退出代码 1 退出当前的子 shell 环境,例如:
sh -c '(echo 1; exit 1; echo 2); echo 3'
Run Code Online (Sandbox Code Playgroud)
这会exit 1退出运行代码的子shell,(...)因此2不会输出,并且父shell进程恢复 echoing 3。
kill -s PIPE "$$"¹ 将 SIGPIPE 信号发送到执行当前解释脚本的 shell 解释器的进程。SIGPIPE 信号默认会导致进程终止,并且该进程已被 SIGPIPE 杀死的事实反映在其退出状态中。
所以在:
sh -c '(echo 1; kill -s PIPE "$$"; echo 2); echo 3'
Run Code Online (Sandbox Code Playgroud)
SIGPIPE 信号由子shell 进程发送到其父进程(执行 的那个进程sh)。该父进程将死亡而不输出,3而子外壳进程将继续在后台运行并输出2。
如果您在bashorzsh外壳程序(以及其他一些类似 Bourne 的外壳程序)中运行该命令,这些外壳程序会将$?参数(它们对最后一个命令的退出状态的内部表示)设置为类似于 141 的值,即 128 + SIGPIPE ( 13 在大多数系统上)。
现在 SIGPIPE 是系统发送给尝试写入没有读取端的管道或套接字(损坏的管道/套接字)的进程的信号,因此将其发送到这里有点误导。为管理性终止进程保留的信号是 SIGTERM,这恰好是kill默认情况下发送的信号。
现在,您可能想要使用 SIGPIPE 而不是 SIGTERM 的一个原因是,bash当他们的一项工作被信号终止时,有类似的 shell会输出一条消息,而它们通常不会为 SIGPIPE 执行此操作(因为它很常见于SIGPIPE 终止的进程,并不一定意味着存在像cmd | head -n 1) 中的问题,因此使用 SIGPIPE 是避免这些消息的一种方法。
bash-4.4$ /bin/kill 0
Terminated
bash-4.4$ /bin/kill -s PIPE 0
bash-4.4$
Run Code Online (Sandbox Code Playgroud)
即使在非交互式时:
$ bash -c 'sh -c "kill \$\$"; exit'
bash: line 1: 6665 Terminated sh -c "kill \$\$"
$ bash -c 'sh -c "kill -s PIPE \$\$"; exit'
$
Run Code Online (Sandbox Code Playgroud)
1此处添加缺少的引号以$$确保可靠性并使用标准(POSIX 中的非可选) kill -s PIPE语法以实现可移植性(尽管kill -PIPE也应适用于大多数系统)。
| 归档时间: |
|
| 查看次数: |
1251 次 |
| 最近记录: |