bash:默默的杀死后台函数进程
贝壳大师,
我有一个bash shell脚本,在这个脚本中,我启动一个后台函数foo()来显示无聊和长时间命令的进度条:
foo() { while [ 1 ] do #massively cool progress bar display code sleep 1 done } foo & foo_pid=$! boring_and_long_command kill $foo_pid >/dev/null 2>&1 sleep 10
现在,当foo去世时,我看到下面的文字:
/home/user/script: line XXX: 30290 Killed foo
这完全破坏了我的迷人,否则大量的酷,进度条显示。 我如何摆脱这个信息?
tia,prmatta
kill $foo_pid wait $foo_pid 2>/dev/null
顺便说一句,我不知道你的大量酷进度栏,但你见过pipe道查看器(PV)? http://www.ivarch.com/programs/pv.shtml
刚刚遇到了这个,并意识到“失望”是我们正在寻找。
foo & foo_pid=$! disown boring_and_long_command kill $foo_pid sleep 10
正在打印死亡消息,因为该进程仍在被监视的“作业”的shell列表中。 disown命令将从该列表中删除最近生成的进程,以便即使在使用SIGKILL(-9)时也不会生成debugging消息。
这是一个解决scheme,我想出了一个类似的问题(想在长时间运行的过程中显示时间戳)。 这实现了一个killsub函数,只要你知道pid就可以让你安静地杀死任何subshell。 请注意,陷阱指令很重要,包括:脚本被中断的情况下,子shell将不会继续运行。
foo() { while [ 1 ] do #massively cool progress bar display code sleep 1 done } #Kills the sub process quietly function killsub() { kill -9 ${1} 2>/dev/null wait ${1} 2>/dev/null } foo & foo_pid=$! #Add a trap incase of unexpected interruptions trap 'killsub ${foo_pid}; exit' INT TERM EXIT boring_and_long_command #Kill foo after finished killsub ${foo_pid} #Reset trap trap - INT TERM EXIT
尝试用行代替行kill $foo_pid >/dev/null 2>&1
:
(kill $foo_pid 2>&1) >/dev/null
更新 :
这个回答在@ mklement0的解释中是不正确的:
这个答案对后台作业无效的原因是,在kill命令完成之后,Bash本身asynchronous地输出一个状态信息,这个信息是你不能直接抑制的 – 除非你使用wait,就像在接受的答案中一样。
这“黑客”似乎工作:
# Some trickery to hide killed message exec 3>&2 # 3 is now a copy of 2 exec 2> /dev/null # 2 now points to /dev/null kill $foo_pid >/dev/null 2>&1 sleep 1 # sleep to wait for process to die exec 2>&3 # restore stderr to saved exec 3>&- # close saved version
它从这里受到启发。 世界秩序已经恢复。
在函数的开头添加:
trap 'exit 0' TERM
关于使用“等待”:这是我想的最好的答案。 请参阅https://stackoverflow.com/a/10200191/1208218 ,了解其外观/工作原理的示例。
另一种方法来做到这一点:
func_terminate_service(){ [[ "$(pidof ${1})" ]] && killall ${1} sleep 2 [[ "$(pidof ${1})" ]] && kill -9 "$(pidof ${1})" }
用它来呼叫
func_terminate_service "firefox"
另一种禁用工作通知的方法是将你的命令放在sh -c 'cmd &'
结构中。
#!/bin/bash foo() { while [ 1 ] do sleep 1 done } #foo & #foo_pid=$! export -f foo foo_pid=`sh -c 'foo & echo ${!}' | head -1` # if shell does not support exporting functions (export -f foo) #arg1='foo() { while [ 1 ]; do sleep 1; done; }' #foo_pid=`sh -c 'eval "$1"; foo & echo ${!}' _ "$arg1" | head -1` sleep 3 echo kill ${foo_pid} kill ${foo_pid} sleep 3 exit