在 bash 中杀死之后如何抑制终止消息?

你如何抑制 Terminated消息出现后,你杀死一个 在 bash 脚本中进行处理?

我试过 set +bm但是没用。

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

61182 次浏览

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

简而言之,你不能。Bash 总是打印前台作业的状态。监视标志只适用于后台作业,并且只适用于交互式 shell,而不适用于脚本。

请参见 jobs.c 中的 tification _ of _ job _ status ()。

正如您所说的,您可以重定向,因此标准错误指向/dev/null,但是您会错过任何其他错误消息。您可以通过在运行脚本的 subshell 中执行重定向来使其成为临时的。这样就只剩下原始环境了。

(script 2> /dev/null)

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

您可以通过将一个新的 filedescriptor 重定向到这里来保存和恢复标准错误:

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

但是我不推荐这样做——第一种方法的唯一好处是它保存了一个子 shell 调用,同时更加复杂,甚至可能改变脚本的行为,如果脚本改变了文件描述符的话。


编辑:

为了得到更恰当的答案,请检查 马克 · 埃德加给出的答案

Disown 为我做了正确的事情——由于很多原因,exec 3 > & 2是有风险的—— set + bm 似乎不能在脚本中工作,只能在命令提示符下工作

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

演示:

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


sh silent.sh

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

为了使消息静音,您必须重定向 stderr 在生成消息的时候。因为 kill命令发送一个信号并且不等待目标进程的响应,所以重定向 kill命令的 stderr对您没有任何好处。内置在 wait中的 bash 是专门为此目的制作的。

下面是一个非常简单的例子,它删除了最新的后台命令

kill $!
wait $! 2>/dev/null

因为 killwait都接受多个 pid,所以也可以执行批杀死。下面是一个杀死所有后台进程(当然是当前进程/脚本)的示例。

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

我是从 Bash: 静默杀死后台函数进程被带到这里的。

这就是我们要找的吗?

不想要:

$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+  Done                    sleep 3
$

招聘:

$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$

如您所见,没有任务结束信息。在 bash 脚本中也可以使用,对于已杀死的后台进程也是如此。

‘ set + m’禁用当前 shell 的作业控制(参见‘ help set’)。因此,如果您在 subshell 中输入命令(如在括号中所做的那样) ,则不会影响当前 shell 的作业控制设置。唯一的缺点是,如果您想检查后台进程是否已经终止,或者计算返回代码,则需要将后台进程的 pid 返回到当前 shell。

这也适用于 kill all (对于那些喜欢它的人) :

killall -s SIGINT (yourprogram)

隐藏信息... 我在运行后台模式下的 mpg123。 只能通过发送 ctrl-c (SIGINT)而不是 SIGTERM (缺省值)来悄悄地终止它。

禁用作业通知的另一种方法是将命令置于 sh -c 'cmd &'构造的背景中。

#!/bin/bash
# ...
pid="`sh -c 'sleep 30 & echo ${!}' | head -1`"
kill "$pid"
# ...


# or put several cmds in sh -c '...' construct
sh -c '
sleep 30 &
pid="${!}"
sleep 5
kill "${pid}"
'

成功地在脚本中添加了“ jobs 2>&1 >/dev/null”,不确定它是否能帮助其他人的脚本,但是这里有一个示例。

    while true; do echo $RANDOM; done | while read line
do
echo Random is $line the last jobid is $(jobs -lp)
jobs 2>&1 >/dev/null
sleep 3
done

简单:

{ kill $! } 2>/dev/null

优势? 可以使用任何信号

例如:

{ kill -9 $PID } 2>/dev/null

我发现将 kill 命令放在函数中,然后对函数进行背景处理会抑制终止输出

function killCmd() {
kill $1
}


killCmd $somePID &

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]'