我正在子外壳中运行一个可能会挂起或未挂起的进程,然后如果该进程在10秒钟后仍在运行,则将其终止。
这样做时,我用stdout
将stderr
和> /dev/null 2>&1
用管道输送到/ dev / null,这似乎可行。但是,无论我使用什么命令,kill命令的输出都将在我的下一个命令之后输出到stdout
。
[me@test] (Command_That_May_Hang.sh)&
[me@test] X=$!
[me@test] (sleep 10 && kill -9 $! > /dev/null 2>&1)&
[me@test] ps
> PID TTY TIME CMD
> 22741 pts/1 00:00:00 bash
> 27585 pts/1 00:00:00 ps
> [1]+ Killed Command_That_May_Hang.sh > /dev/null 2>&1
我尝试将/dev/null 2>&1
移到()
的外面,甚至移到&
之后,结果没有变化。作为参考,这些迭代看起来像:
(sleep 10 && kill -9 $!) > /dev/null 2>&1 &
(sleep 10 && kill -9 $!)& > /dev/null 2>&1
执行该过程然后将其杀死都可以成功运行,似乎我只能临时抑制输出,这是奇怪的行为。对于将输出正确发送到/dev/null
的任何帮助,将不胜感激。
答案 0 :(得分:2)
消息是由bash本身打印的,而不是由kill
命令打印的。因此,您无法通过重定向脚本中的任何输出来抑制它。
您可以执行的操作是禁用作业控制的监视模式
set +m
bash手册页中的语录:
-m 监控模式。作业控制已启用。默认情况下,此选项处于启用状态 支持它的系统上的交互式shell(请参见上面的“作业控制”)。所有 流程在单独的流程组中运行。当后台工作 完成后,shell将打印包含退出状态的行。
使用+m
时,监视模式被禁用。
答案 1 :(得分:1)
据我了解,您只想在收到终止信号后才禁止程序输出。
您无法通过重定向kill
本身的输出来做到这一点;您只能通过更改程序本身在启动时将输出定向的方式来 。
在以下示例中,我们将命令的stdout和stderr重定向到一个单独的shell进程,并告诉该shell进程在收到SIGUSR1时停止打印输出。
#!/usr/bin/env bash
case $BASH_VERSION in ''|[123].*|4.[012]) echo "ERROR: Bash 4.3 required" >&2; exit 1;; esac
process_output_until_signal() {
running=1
trap 'running=0' USR1
while IFS= read -r line; do
(( running )) && printf '%s\n' "$line"
done
}
exec 3> >(process_output_until_signal); output_loop_pid=$!
Command_That_May_Hang >&3 2>&3 & command_pid=$!
exec 3>&-
sleep 10
kill -USR1 "$output_loop_pid"
sleep 0.1
kill "$command_pid"
请参见the answer by Ralf:这是由外壳程序 而不是kill
命令,也不是被杀死的命令写的输出。 (仅当命令在默认情况下仅针对交互式外壳而不是脚本启用的配置中运行时,才会编写该命令。)