【问题标题】:Running bash commands in the background without printing job and process ids在后台运行 bash 命令而不打印作业和进程 ID
【发布时间】:2011-12-02 23:20:52
【问题描述】:

在 bash 中在后台运行一个进程相当容易。

$ echo "Hello I'm a background task" &
[1] 2076
Hello I'm a background task
[1]+  Done                    echo "Hello I'm a background task"

但是输出很冗长。第一行打印后台任务的作业 ID 和进程 ID,然后是命令的输出,最后是作业 ID、状态和触发作业的命令。

有没有办法抑制运行后台任务的输出,以使输出看起来与末尾没有 & 符号时完全一样?即:

$ echo "Hello I'm a background task" &
Hello I'm a background task

我问的原因是我想将后台进程作为选项卡完成命令的一部分运行,因此该命令的输出必须不间断才能有意义。

【问题讨论】:

标签: bash bash-completion


【解决方案1】:

与完成无关,但您可以通过将调用放在子外壳中来抑制该输出:

(echo "Hello I'm a background task" &)

【讨论】:

  • 谢谢,这绝对有效。不幸的是,当从 bash 完成函数运行这样的脚本时,bash 似乎会等到子进程完成后再给出完成结果。这很不幸,因为这意味着似乎不可能让后台工作人员被 bash-completion 触发。
  • 如果您想wait 完成后台作业,则不能使用此功能。
【解决方案2】:

根据@shellter 的回答,这对我有用:

tyler@Tyler-Linux:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1;
Hello I'm a background task
tyler@Tyler-Linux:~$

我不知道这背后的原因,但我记得有一篇旧帖子不承认会阻止 bash 输出进程 ID。

【讨论】:

  • @Tyzoid 。我在 bash shell (v 4.2.37) 中尝试了您的解决方案,并得到了有趣的结果。 1. 我得到了相同的结果,只是在最后添加了;。 (不睡觉)。 2. 但是注意到当我在“下”行添加echo STDERR 2>&1 时,出现了[1]+ Done ... 的东西! . 3. 我的解决方案(正如我现在所指出的)适用于kshecho STDERR 2>&1 仅产生输出STDERR。好吧,为我们俩生活和学习。祝大家好运。
【解决方案3】:

在一些较新版本的 bash 和 ksh93 中,您可以用子 shell 或进程组(即{ ... })将其包围。

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $

【讨论】:

  • 当我使用花括号时,最后一行输出仍然显示(我不确定你为什么看不到它)。
  • 我完全复制了这个,但它对我不起作用,它仍然显示输出,正如@AlexSpurling 所说。也许我做错了什么,因为其他人赞成它,但恐怕我必须给它-1。
  • @Mark :我刚刚对此做了一些快速测试,我发现问题是我继续使用ksh93+ 作为我的主要外壳。此代码按 ksh 中的承诺工作。但由于 OP 标有bash,我了解您的 dv。在@Tyzoid 的回答中查看 bash 测试的结果。祝大家好运!
  • 既然你已经明确表示这在 bash 中不起作用,我将删除 -1。
  • 对我来说,这在 Bash 函数中效果很好,也可以使用 wait $! 等待该过程,这似乎不是接受答案的情况。
【解决方案4】:

基于this answer,我想出了更简洁正确的:

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date

【讨论】:

  • 完美!并可重复用于其他东西
  • 这一点都不完美,因为后台作业的错误输出会被抑制!
【解决方案5】:

在上述答案的基础上,如果您需要允许 stderr 从命令中通过:

f() { echo "Hello I'm a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null

【讨论】:

【解决方案6】:

试试:

user@host:~$ read < <( echo "Hello I'm a background task" & echo $! )
user@host:~$ echo $REPLY
28677

您已经隐藏了 输出PID。请注意,您仍然可以从 $REPLY

中检索 PID

【讨论】:

  • 这太完美了!谢谢
【解决方案7】:

很抱歉对旧帖子的回复,但我认为这对其他人有用,这是 Google 上的第一个回复。

我在使用这种方法(子shell)和使用“等待”时遇到问题。但是,当我在函数中运行它时,我能够做到这一点:

function a {
    echo "I'm background task $1"
    sleep 5
}

function b {
    for i in {1..10}; do
        a $i &
    done
    wait
} 2>/dev/null

当我运行它时:

$ b
I'm background task 1
I'm background task 3
I'm background task 2
I'm background task 4
I'm background task 6
I'm background task 7
I'm background task 5
I'm background task 9
I'm background task 8
I'm background task 10

在我收到提示之前有 5 秒的延迟。

【讨论】:

    【解决方案8】:

    子外壳解决方案有效,但我也希望能够等待后台作业(并且最后没有“完成”消息)。来自子 shell 的 $! 在当前交互式 shell 中不是“可等待的”。唯一对我有用的解决方案是使用我自己的等待功能,这非常简单:

    myWait() {
      while true; do
        sleep 1; STOP=1
        for p in $*; do
          ps -p $p >/dev/null && STOP=0 && break
        done
        ((STOP==1)) && return 0
      done
    }
    
    i=0
    ((i++)); p[$i]=$(do_whatever1 & echo $!)
    ((i++)); p[$i]=$(do_whatever2 & echo $!)
    ..
    myWait ${p[*]}
    

    很简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      • 2015-07-26
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      相关资源
      最近更新 更多