unix 有没有办法让bash job control安静下来?

6kkfgxo0  于 2023-06-22  发布在  Unix
关注(0)|答案(6)|浏览(180)

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

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

由于我试图并行运行作业并使用输出,所以我想找到一种方法来使bash静音。有没有办法消除这种多余的输出?

ni65a41a

ni65a41a1#

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

(sleep 10 & )
edqdpe6u

edqdpe6u2#

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

    • 静默Bash的作业控制消息2种基本场景**:

Launch-and-Forget:

CodeGnome's helpful answer answer建议将后台命令封装在一个简单的子shell中-例如(sleep 10 &)--这可以有效地抑制作业控制消息--无论是作业 * 创建 * 还是作业 * 终止 *。
这有一个重要的副作用:

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

对于launch-and-forget场景,这 * 不是 * 问题

  • 你只要做好后台工作,
  • 你让它自己完成(你相信它运行正确)。

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

Launch-and-control-later:

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

  • 如果需要的话,杀了它。
    *同步等待(在稍后的某个时间点)完成,

需要采取不同的办法:

  • 静默 * 创建 * 作业控制消息的处理如下,但要静默 * 终止 * 作业控制消息 * 绝对*,必须关闭作业控制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 +m),则使 * 终止 * 作业控制消息静音的唯一方法是kill作业或wait作业:

警告:有 * 两种边缘情况 * 这种技术仍然产生输出:

  • 如果后台命令尝试从stdin * 马上 * 读取。
  • 如果后台命令立即终止。

要安静地启动作业(如上所述,但不使用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的 * 同步 * 输出,然后允许沉默。
但是,如前所述,如果作业自行完成 *,则仍将显示作业控制消息。

50few1ms

50few1ms3#

将其 Package 在一个虚拟脚本中:
quiet.sh:

#!/bin/bash
$@ &

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

./quiet.sh echo toto

你可能需要根据你的输入来玩报价。

llmtgqce

llmtgqce4#

互动,不。它将始终显示作业状态。您可以使用set -b影响状态显示的时间。
没有什么可以阻止您使用命令的输出(通过管道或存储it变量等)。作业状态由shell发送到控制端,不与其他I/O混合。如果你正在做一些复杂的工作,解决方案是编写一个单独的脚本。
只有在bashrc中有一些函数使用了作业控制,并且希望直接访问交互式环境时,作业消息才是真正的问题。不幸的是你对此无能为力。

ie3xauqp

ie3xauqp5#

imho,最简单的方法来实现这一点,我在很多场合使用如下:

exec {oldfd2}<&2 # copy/dup stderr
exec 2<&- # tell stderr to zip it
sleep 3 &
sleep3bgpid=$!
someotherbgcmd 2>&$oldfd2 & 
#route stderr of this job to orig stderr
otherbgcmdpid=$!
# restore things as they were...
exec 2<&$oldfd2 # restore stderr
exec {oldfd2}>&- # close dup'ed fd
unset oldfd2 # keep env clean
...
unset sleep3bgpid othercmdbgpid

使用set +/-m时要小心,我在会话中运行了许多没有tty的任务,请参阅echo $-,其中假设存在作业控制是不正确的。在正常的交互式会话中,这些标志是:然而,在远程无tty会话中,它们是hiBH……干杯在这里输入代码

ajsxfq5m

ajsxfq5m6#

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

echo 'hello world' > /dev/null &

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

相关问题