【发布时间】:2012-10-21 10:03:02
【问题描述】:
如题——如何杀死zsh中的所有后台进程?
【问题讨论】:
标签: linux background zsh jobs
如题——如何杀死zsh中的所有后台进程?
【问题讨论】:
标签: linux background zsh jobs
一个应该使用builtin zsh 内置命令和另一个kill zsh 内置命令:
builtin kill %1
因为kill 也是位于/usr/bin/kill 的util-linuxpackage (upstream, mirror) 的一个单独的二进制文件,不支持作业 (kill: cannot find process "%1")。
使用关键字builtin 来避免名称冲突或使用enable 内置的kill 如果它被禁用。
在 shell 中有一个禁用和启用内置命令(即 shell 自己的命令,例如 cd 和 kill )的概念,而在 zsh 中,您可以启用(禁用)kill builtin如:
enable kill
发出disable 来检查内置是否被禁用(和enable 来查看启用的)。
【讨论】:
对@Zxy 的回复稍作调整...
在我的系统上,我发现挂起的作业没有被默认的终止信号正确终止。我实际上必须将其更改为 kill -KILL 才能让 suspended 后台作业正常终止。
alias killbg='kill -KILL ${${(v)jobstates##*:*:}%=*}'
请特别注意围绕此的单引号。如果切换到双引号,则需要转义每个“$”。请注意,您不能使用function 来包装此命令,因为该函数将递增$jobstates 数组,从而导致该函数尝试杀死自己...必须使用别名。
上面的killjob 脚本有点多余,因为你可以这样做:
kill %1
更少的击键次数,它已经内置在zsh 中。
【讨论】:
这适用于 ZSH 和 Bash:
: '
killjobs - Run kill on all jobs in a Bash or ZSH shell, allowing one to optionally pass in kill parameters
Usage: killjobs [zsh-kill-options | bash-kill-options]
With no options, it sends `SIGTERM` to all jobs.
'
killjobs () {
local kill_list="$(jobs)"
if [ -n "$kill_list" ]; then
# this runs the shell builtin kill, not unix kill, otherwise jobspecs cannot be killed
# the `$@` list must not be quoted to allow one to pass any number parameters into the kill
# the kill list must not be quoted to allow the shell builtin kill to recognise them as jobspec parameters
kill $@ $(sed --regexp-extended --quiet 's/\[([[:digit:]]+)\].*/%\1/gp' <<< "$kill_list" | tr '\n' ' ')
else
return 0
fi
}
@zyx 的回答对我不起作用。
更多信息在这里:https://gist.github.com/CMCDragonkai/6084a504b6a7fee270670fc8f5887eb4
【讨论】:
alias killbg='kill ${${(v)jobstates##*:*:}%=*}'
。就是zsh,不需要外部工具。
如果你想杀死工作编号N:
function killjob()
{
emulate -L zsh
for jobnum in $@ ; do
kill ${${jobstates[$jobnum]##*:*:}%=*}
done
}
killjob N
【讨论】:
man zshexpn 和man zshmodules 中:$jobstates 是一个关联数组参数,(v) 仅从该数组中选择值,# 使 zsh 从字符串的开头,选择最短的删除模式,*:*::使 zsh 删除每个值的前两个冒号分隔字段的模式(数组参数上的# 应用于每个值),% 就像 @ 987654331@,但对于字符串结尾和=*,zsh 会删除最后一个 eq 符号之后的所有内容,包括符号本身。每个$jobstates 值看起来像job-state:mark:pid=state...。
# 更改为##:这样它将删除直到最后一个冒号的所有内容,有效地只留下管道中的最后一个进程。我的工作假设最后一个永远存在,否则应该执行更复杂的计算。
alias killbg='for job in \`jobs -l | egrep -o "([0-9][0-9]+)"`;
【讨论】:
echo 123 | less 并检查它会杀死什么。提示:当你运行 kill echo 123 时,进程已经死了,它的 PID 可能已经被占用了。因此,使用带有 killbg 的挂起管道,您可能会杀死 2 个无辜的进程:进程 123(echo 参数)和碰巧重新获取 echo PID 的进程。
{echoPID}=done:{lessPID})。