52

在后台运行作业时,Bash 非常冗长:

$ echo toto&
toto
[1] 15922
[1]+  Done                    echo toto

由于我正在尝试并行运行作业并使用输出,因此我想找到一种使 bash 静音的方法。有没有办法消除这种多余的输出?

4

5 回答 5

57

您可以使用括号在子外壳中运行后台命令,这将使作业控制消息静音。例如:

(sleep 10 & )
于 2012-06-19T23:45:39.667 回答
50

注意:以下适用于交互式Bash 会话。在scripts中,从不打印作业控制消息。

消除 Bash 的作业控制消息两种基本方案:


启动后忘记:

CodeGnome 的有用答案建议将后台命令包含在一个简单的子外壳中- 例如(sleep 10 &)- 这有效地使作业控制消息静音 - 无论是在作业创建时还是在作业终止时。

这有一个重要的副作用

  • & 通过在子shell中使用控制运算符,您将失去对后台作业的控制-jobs不会列出它,也不会列出%%(最近启动的作业的规范(ID))和$!(启动的(最后)进程的PID(作为)最近工作的一部分)将反映它。[1]

对于启动后忘记的场景,这不是问题

  • 你只需启动后台工作,
  • 然后你让它自己完成(并且你相信它运行正确)。

[1] 可以想象,您可以自己去寻找进程,通过搜索正在运行的进程以找到与其命令行匹配的进程,但这很麻烦并且不容易变得健壮。


稍后启动和控制:

如果您想继续控制工作,以便以后可以:

  • 杀了它,如果需要的话。
  • 同步等待(稍后)完成,

需要一种不同的方法:

  • 静音创建作业控制消息在下面处理,但为了 绝对静音终止作业控制消息,您必须关闭作业控制 shell 选项

    • set +mset -m重新打开)
    • 警告:这是一个具有许多重要副作用的全局设置,特别是:
      • 用于后台命令的标准输入然后/dev/null是当前 shell 的标准输入。
      • Ctrl-Z暂停 ( ) 和延迟暂停 ( Ctrl-Y) 前台命令的键盘快捷键被禁用。
      • 有关完整的故事,请参阅man bash并(不区分大小写)搜索“作业控制”的出现。
  • 要使创建作业控制消息静音,请将后台命令包含在组命令中,并将后者的 stderr 输出重定向到/dev/null

    { sleep 5 & } 2>/dev/null
    

以下示例显示了如何在原则上保留对作业的控制权的同时安静地启动后台作业。

$ set +m; { sleep 5 & } 2>/dev/null # turn job-control option off and launch quietly
$ jobs # shows the job just launched; it will complete quietly due to set +m 

如果您不想关闭作业控制选项set +mkillwait

警告:在两种极端情况下,这种技术仍然会产生输出:

  • 如果后台命令立即尝试从标准输入读取。
  • 如果后台命令立即终止。

安静地启动工作(如上,但没有set +m):

$ { sleep 5 & } 2>/dev/null

wait悄悄地为它:

$ wait %% 2>/dev/null    # use of %% is optional here

kill悄悄地给它:

{ kill %% && wait; } 2>/dev/null

wait为了使通常由 Bash异步显示的终止作业控制消息(在实际进程终止时,杀死后不久)成为来自 的同步输出,则需要额外的内容wait,然后允许静音。

但是,如前所述,如果作业自行完成,仍将显示作业控制消息。

于 2016-07-09T04:21:42.293 回答
1

将其包装在一个虚拟脚本中:

安静的.sh:

#!/bin/bash
$@ &

然后调用它,将您的命令作为参数传递给它:

./quiet.sh echo toto

根据您的输入,您可能需要使用引号。

于 2012-06-19T09:23:36.037 回答
1

交互式,没有。它将始终显示作业状态。您可以使用 影响显示状态的时间set -b

没有什么可以阻止您使用命令的输出(通过管道或存储它的变量等)。作业状态由 shell 发送到控制终端,不与其他 I/O 混合。如果您正在做一些复杂的工作,解决方案是编写一个单独的脚本。

只有当你的 bashrc 中有函数使用你想要直接访问交互环境的作业控制时,作业消息才是真正的问题。不幸的是,您对此无能为力。

于 2012-06-19T10:08:21.677 回答
-1

一种解决方案(无论如何在 bash 中)是将所有输出路由到 /dev/null

    echo 'hello world' > /dev/null &

除了 bg 进程的 id 之外,上述内容不会为您提供任何输出。

于 2012-09-14T19:12:16.357 回答