it-swarm.cn

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

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

我试过set +bm,但这不起作用。

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

50
user14437

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

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

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

(script 2> /dev/null)

这将丢失所有错误消息,但只是从该脚本,而不是在该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

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


编辑: /

更合适的答案检查答案由 Mark Edgar

16
wnoise

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

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

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

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

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

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

118
Mark Edgar

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

kill -PIPE

或者干脆

kill -13
15
Steven Penny

解决方案:使用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

8
MarcH

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

4
Matthias Kestenholz

这是我们都在寻找的吗?

不想要的:

$ 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')。因此,如果您在子shell中输入命令(如括号中所示),则不会影响当前Shell的作业控制设置。唯一的缺点是,如果要检查它是否已终止,或者需要评估返回代码,则需要将后台进程的pid恢复到当前Shell。

1
Ralph

这也适用于killall(对于喜欢它的人):

killall -s SIGINT (yourprogram) 

抑制消息......我在后台模式下运行mpg123。它只能通过发送ctrl-c(SIGINT)而不是SIGTERM(默认)来无声地被杀死。

1
Coder of Salvation

禁用作业通知的另一种方法是将命令置于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}"
'
1
phily

简单:

{ kill $! } 2>/dev/null

优点?可以使用任何信号

例如:

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

disown对我来说完全是正确的 - exec 3>&2因为很多原因而存在风险 - set + bm似乎在脚本内部不起作用,仅在命令提示符下

0
clemep

我发现将kill命令放在一个函数中然后对该函数进行后台处理会抑制终止输出

function killCmd() {
    kill $1
}

killCmd $somePID &
0
Al Joslin

将“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
0
J-o-h-n-