有没有办法让 bash 作业控制安静?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11097761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:31:54  来源:igfitidea点击:

Is there a way to make bash job control quiet?

bashshellunixparallel-processing

提问by static_rtti

Bash is quite verbose when running jobs in the background:

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

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

Since I'm trying to run jobs in parallel and use the output, I'd like to find a way to silence bash. Is there a way to remove this superfluous output?

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

回答by Todd A. Jacobs

You can use parentheses to run a background command in a subshell, and that will silence the job control messages. For example:

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

(sleep 10 & )

回答by mklement0

Note: The following applies to interactiveBash sessions. In scripts, job-control messages are neverprinted.

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

There are 2 basic scenariosfor silencing Bash's job-control messages:

2 种基本场景可以使 Bash 的作业控制消息静音



Launch-and-forget:

一劳永逸:

CodeGnome's helpful answer answersuggests enclosing the background command in a simple subshell- e.g, (sleep 10 &)- which effectively silences job-control messages - both on job creationand on job termination.

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

This has an important side effect:

这有一个重要的副作用

  • By using control operator &insidethe subshell, you lose control of the background job- jobswon't list it, and neither %%(the spec. (ID) of the most recently launched job) nor $!(the PID of the (last) process launched (as part of) the most recent job) will reflect it.[1]
  • 通过使用控制运营商&内部子shell,你失去了后台作业的控制-jobs就不一一列举了,既不%%(规范(ID)最近推出的职业。)也不是$!(启动了(最后一个)进程的PID(作为)最近工作的一部分)将反映它。[1]

For launch-and-forget scenarios, this is nota problem:

对于一劳永逸的场景,这不是问题

  • You just fire off the background job,
  • and you let it finish on its own (and you trust that it runs correctly).
  • 你只需解雇后台工作,
  • 然后让它自行完成(并且您相信它可以正确运行)。

[1] Conceivably, you could go looking for the process yourself, by searching running processes for ones matching its command line, but that is cumbersome and not easy to make robust.

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



Launch-and-control-later:

稍后启动和控制:

If you want to remain in control of the job, so that you can later:

如果您想保持对工作的控制,以便以后可以:

  • kill it, if need be.
  • synchronously wait(at some later point) for its completion,
  • 杀死它,如果需要的话。
  • 同步等待(稍后)完成,

a different approach is needed:

需要一种不同的方法:

  • Silencing the creationjob-control messages is handled below, but in order to silence the terminationjob-control messages categorically, you must turn the job-control shell option OFF:

    • set +m(set -mturns it back on)
    • Caveat: This is a global settingthat has a number of important side effects, notably:
      • Stdin for background commands is then /dev/nullrather than the current shell's.
      • The keyboard shortcuts for suspending (Ctrl-Z) and delay-suspending (Ctrl-Y) a foreground command are disabled.
      • For the full story, see man bashand (case-insensitively) search for occurrences of "job control".
  • To silence the creationjob-control messages, enclose the background command in a group commandand redirect the latter's stderr output to /dev/null

    { sleep 5 & } 2>/dev/null
    
  • 沉默创造就业,控制消息是以下处理,但为了 沉默终止作业控制消息明确,必须打开作业控制shell选项OFF

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

    { sleep 5 & } 2>/dev/null
    

The following example shows how to quietly launch a background job while retaining control of the job in principle.

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

$ 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 

If you do notwant to turn off the job-control option (set +m), the only way to silence the terminationjob-control message is to either killthe job or waitfor it:

如果你希望关闭作业控制选项(set +m),只有这样,才能沉默终止作业控制消息是要么kill工作或wait为它:

Caveat: There are two edge caseswhere this technique still produces output:

警告:在两种边缘情况下,此技术仍会产生输出:

  • If the background command tries to read from stdin right away.
  • If the background command terminates right away.
  • 如果背景命令试图从标准输入读取的时候了
  • 如果背景命令终止的时候了

To launch the job quietly (as above, but without set +m):

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

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

To waitfor it quietly:

wait为它悄然:

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

To killit quietly:

kill悄悄给它:

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

The additional waitis necessary to make the termination job-control message that is normally displayed asynchronouslyby Bash (at the time of actual process termination, shortly after the kill) a synchronousoutput from wait, which then allows silencing.

wait为了使Bash通常异步显示的终止作业控制消息(在实际进程终止时,在终止后不久)成为来自的同步输出wait,然后允许静默,附加是必要的。

But, as stated, if the job completes by itself, a job-control message will still be displayed.

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

回答by jedwards

Wrap it in a dummy script:

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

quiet.sh:

安静.sh:

#!/bin/bash
$@ &

then call it, passing your command to it as an argument:

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

./quiet.sh echo toto

You may need to play with quotes depending on your input.

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

回答by ormaaj

Interactively, no. It will always display job status. You can influence when the status is shown using set -b.

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

There's nothing preventing you from using the output of your commands (via pipes, or storing it variables, etc). The job status is sent to the controlling terminal by the shell and doesn't mix with other I/O. If you're doing something complex with jobs, the solution is to write a separate script.

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

The job messages are only really a problem if you have, say, functions in your bashrc which make use of job control which you want to have direct access to your interactive environment. Unfortunately there's nothing you can do about it.

如果您的 bashrc 中有一些函数,这些函数利用了您希望直接访问交互式环境的作业控制,那么作业消息才是真正的问题。不幸的是,您对此无能为力。

回答by ACE

One solution (in bash anyway) is to route all the output to /dev/null

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

    echo 'hello world' > /dev/null &

The above will not give you any output other than the id for the bg process.

除了 bg 进程的 id 之外,上面不会给你任何输出。