如何在bash中杀死后禁止终止消息?

use*_*437 54 unix bash shell

如何抑制Terminated在bash脚本中终止进程后出现的消息?

我试过了set +bm,但那不起作用.

我知道另一个解决方案涉及呼叫exec 2> /dev/null,但是可靠吗?如何重新设置它以便我可以继续查看stderr?

Mar*_*gar 124

为了使消息静音,您必须stderr 在生成消息时重定向.由于该kill命令发送一个信号,并不会等待目标进程作出回应,重定向stderr的的kill命令对你没有好.bash内置wait是专门为此目的而制作的.

这是一个非常简单的示例,可以杀死最新的后台命令.(了解更多关于$!的信息.)

kill $!
wait $! 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

因为这两个killwait接受多个的pid,你也可以做批量杀死.这是一个杀死所有后台进程(当然是当前进程/脚本)的示例.

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

我是从bash带到这里的:默默杀死后台功能进程.

  • @AlexanderShcheblikin`wait`返回后台进程的退出代码,或128 +(杀死它的信号的数量). (2认同)
  • 这应该是恕我直言的公认答案。 (2认同)

wno*_*ise 17

简短的回答是,你做不到.Bash始终打印前台作业的状态.监视标志仅适用于后台作业,仅适用于交互式shell,而不适用于脚本.

请参阅jobs.c中的notify_of_job_status().

如你所说,你可以重定向所以标准错误指向/ dev/null但是你会错过任何其他错误消息.您可以通过在运行脚本的子shell中执行重定向来使其成为临时的.这留下了原始环境.

(script 2> /dev/null)
Run Code Online (Sandbox Code Playgroud)

这将丢失所有错误消息,但只是从该脚本,而不是从该shell中运行的任何其他内容.

您可以通过将新文件描述符重定向到指向那里来保存和恢复标准错误:

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version
Run Code Online (Sandbox Code Playgroud)

但我不建议这样做 - 第一个的唯一好处是它保存了一个子shell调用,而更复杂,甚至可能改变脚本的行为,如果脚本改变了文件描述符.


编辑:

有关Mark Edgar给出的更合适的答案检查答案

  • 这个答案是对的.请参阅下面的Mark Edgar的答案. (5认同)

小智 17

灵感来自MarcH的回答.我正在使用,kill -INT因为他建议取得一些成功,但我注意到它并没有杀死一些进程.在测试了一些其他信号之后,我发现在SIGPIPE没有消息的情况下它也会被杀死.

kill -PIPE
Run Code Online (Sandbox Code Playgroud)

或者干脆

kill -13
Run Code Online (Sandbox Code Playgroud)

  • 这是完全错误的,一个过程可以为信号设置处理程序,并在它认为合适时使用它们.特别是,当使用插座时,PIPE信号经常被困住.默认的TERM信号应该用于ASK进程终止,进程可以捕获它并忽略它,或者进行清理然后干净地退出. (2认同)

Mar*_*rcH 8

解决方案:使用SIGINT(仅适用于非交互式shell)

演示:

cat > silent.sh <<"EOF"
sleep 100 &
kill -INT $!
sleep 1
EOF

sh silent.sh
Run Code Online (Sandbox Code Playgroud)

http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798


Mat*_*olz 6

也许通过调用将进程从当前的 shell 进程中分离出来disown


Jam*_*Gao 5

Terminated由 bash 3.x 和 4.x 的默认信号处理程序记录。只需在子进程的第一个处捕获 TERM 信号即可:

#!/bin/sh

## assume script name is test.sh

foo() {
  trap 'exit 0' TERM ## here is the key
  while true; do sleep 1; done
}

echo before child
ps aux | grep 'test\.s[h]\|slee[p]'

foo &
pid=$!

sleep 1 # wait trap is done

echo before kill
ps aux | grep 'test\.s[h]\|slee[p]'

kill $pid ## no need to redirect stdin/stderr

sleep 1 # wait kill is done

echo after kill
ps aux | grep 'test\.s[h]\|slee[p]'

Run Code Online (Sandbox Code Playgroud)