【问题标题】:Background Process stdout Displays After Next Command [duplicate]下一个命令后显示后台进程标准输出[重复]
【发布时间】:2019-01-24 04:54:59
【问题描述】:

我正在一个子 shell 中运行一个进程,该进程可能会或可能不会挂起,然后如果该进程在 10 秒后仍在运行,则终止该进程。

这样做时,我将stdoutstderr> /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 的帮助将不胜感激。

【问题讨论】:

  • 我没有看到来自kill 的任何输出。你指的是什么?
  • 您的重定向仅适用于它们所针对的单个命令。如果你想抑制来自Command_That_May_Hang 的输出,那么你需要运行Command_That_May_Hang >/dev/null 2>&1。抑制来自kill 的输出不会影响作为该kill目标 的单独程序是否写入输出。
  • nit:“我管道标准输出和标准错误”不正确。您正在将 stdout 和 stderr 重定向到 /dev/null。不涉及管道。

标签: bash


【解决方案1】:

消息由 bash 本身打印,而不是由 kill 命令打印。所以你不能通过重定向脚本中的任何输出来抑制它。

你可以通过执行来禁用作业控制的监控模式

set +m

引自 bash 手册页:

-m 监控模式。作业控制已启用。此选项默认开启 支持它的系统上的交互式外壳(参见上面的作业控制)。全部 进程在单独的进程组中运行。当后台作业 完成后,shell 打印一行包含其退出状态。

+m 禁用监控模式。

【讨论】:

    【解决方案2】:

    谈到实际子进程输出,而不是shell诊断状态

    据我了解,您只想在程序接收到终止信号后才抑制程序的输出。

    您不能通过重定向来自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"
    

    说 shell 诊断状态

    参见the answer by Ralf:这是由shell 编写的输出,不是kill 命令,也不是被杀死的命令。 (它也仅在命令运行在默认情况下仅对交互式 shell 而不是脚本启用的配置中运行时编写)。

    【讨论】:

    • 我很确定“kill 命令”字面意思是kill,而不是“被杀死的命令”。
    • @melpomene,他们正在重定向来自kill 本身的输出,这就是为什么我认为与它交谈是合适的。
    猜你喜欢
    • 2016-09-19
    • 2011-05-16
    • 2014-11-23
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    相关资源
    最近更新 更多