命令末尾的 & 是什么意思?

vic*_*ico 15 bash scripts job-control stdout

我有一个启动脚本行:

pyprogramm >> /dev/null  2>&1 &
Run Code Online (Sandbox Code Playgroud)

含义:

>> /dev/null - redirect stdout to null device
2>&1 - redirect stderr to stdout (that is redirected to null device)
Run Code Online (Sandbox Code Playgroud)

但最后一个&是什么意思?

Ser*_*nyy 18

& 终止符是什么?

&命令末尾的尾随运算符用于将命令置于后台。这实际上是POSIX 标准指定的标准语法:

异步列表

如果命令由控制操作符 ('&') 终止,shell 应在子 shell 中异步执行该命令。这意味着 shell 在执行下一个命令之前不应等待命令完成。

在后台运行命令的格式为:

命令 1 & [命令 2 & ... ]

后台命令的目的是在脚本或交互式shell 等待命令的情况下,在没有主shell 的情况下运行命令,这会阻止其他命令的执行,给用户带来等待的不便。这对于启动长时间运行的命令很方便,但您需要在当前 shell 中继续工作。您可以猜到,这起源于没有多选项卡终端模拟器的时代,但终端是连接到计算机本身的实际物理硬件。

从定义中您可以看到,它&也用作命令列表的命令终止符,很像;。在您的特定示例中,pyprogramm >> /dev/null 2>&1 &列表中只有一个命令。

顺序的;列表 vs 异步 & 列表

更普遍,

echo Hello ; echo World ;
Run Code Online (Sandbox Code Playgroud)

echo Hello & echo World &
Run Code Online (Sandbox Code Playgroud)

是由;&运算符终止的列表的两个示例。一个区别是,如果作业控制被禁用,则&终止列表将具有连接到的输入/dev/null

如果作业控制被禁用(参见 set, -m),异步列表的标准输入,在执行任何显式重定向之前,应被视为分配给与 /dev/null 具有相同属性的文件。如果启用了作业控制,则不会发生这种情况。在所有情况下,标准输入的显式重定向应覆盖此活动。

然而,在顺序列表中,stdin如果没有明确的重定向,每个命令仍然连接到终端。

还要注意,根据我们前面提到的定义,&在子shell 中执行命令。相比之下,;终止列表在当前 shell 中执行。退出状态也存在差异。对于&标准说:

异步列表的退出状态应为零。

当您想在后台放置多个命令时,这很重要。当您编写脚本或命令时,您必须选择不关心它们是否失败的命令,或者您必须找到一种方法来处理非零(错误)退出状态。在您的具体示例中,pyprogramm >> /dev/null 2>&1 &在后台运行应该有某种方式来指示它是否失败,但是判断您使用的2>&1是通过重定向隐藏错误输出,并且您可能认为脚本不应该失败。

相比之下,;退出状态定义为:

顺序列表的退出状态应该是列表中最后一个命令的退出状态。

同样,这会影响您如何在命令行中编写命令的顺序列表,以及如果列表中的某些命令失败,您希望如何处理事情。


旁注和补充阅读

  • 事实上,这是POSIX定义是指所有类似Bourne外壳,意义bashdash以及ksh必须支持它。

  • &in 重定向不同于&作为命令终止符。这意味着复制(复制)文件描述符对象。请参阅输出重定向中 & 的确切含义是什么?

  • bash也有|&运营商(注意管与符号之间没有空格)。从bash 手册

    如果使用|&,command 的标准错误,除了它的标准输出,还通过管道连接到command2 的标准输入;它是 2>&1 | 的简写。标准错误到标准输出的这种隐式重定向是在命令指定的任何重定向之后执行的。

  • 您所说的“&”隐藏输出听起来不正确。您引用的标准中的段落谈到*输入*,而不是*输出*。区分启用与否的作业控制的原因是尝试从 tty 读取的后台进程将被挂起。此时,您需要使用作业控制将其置于前台以提供它正在等待的输入。所有这些都无法在没有作业控制的情况下完成,因此如果作业控制被禁用,则需要从 /dev/null 或等效项重定向标准输入。 (2认同)

小智 7

这意味着在后台运行该命令。调用脚本将继续而不是阻塞,直到被调用的命令完成。