如何在一个命令行中运行多个带有&的命令?


12

我遇到了头痛的问题。

我想在后台执行多个命令,所以我想一开始在bash中启动它们。在后台在linux shell中启动一个命令很容易,就像这样:

myCommand &

启动多个命令也很容易,就像这样:

myCommand1 && myCommand2

要么

myCommand1 ; myCommand2

但是,如果我想在后台运行多个命令,则尝试使用以下命令格式,但失败:

myCommand1 & && myCommand2 &

要么

myCommand1 & ; myCommand2 &

两种格式都失败。如何运行&一个命令行中包含的多个命令?


2
将它们放在脚本中并在后台运行脚本
Panther



豹,似乎使用()比使用脚本更容易解决此问题。让我们首先尝试充分利用shell本身提供的功能,而不是自己编写我们想要的东西。但是,当然,使用脚本也可以解决此问题。不管怎么说,还是要谢谢你。
钟钟

如果我想运行“ tail -F <file1>> <file2>”,然后运行“ jobs -l”,然后再次运行“ disown -h%1”
怎么办

Answers:


24

用 ()。

如果要顺序运行它们:

(myCommand1; myCommand2) &

要么

(myCommand1 &) && (myCommand2 &)

如果希望它们并行运行:

myCommand1 & myCommand2 &

在bash中,您也可以使用以下命令({和;之后的空格是必填项):

{ myCommand1 && myCommand2; } &

3
(myCommand1 &) && (myCommand2 &)myCommand2即使myCommand1失败也会运行。
terdon

()可以帮助bash区分&和&&。因此,当我们想使用&和&&聚集时,只需使用()分隔执行单元。
钟钟

16

我想你想要这个:

myCommand1 & myCommand2 &

这将启动myCommand1,并将其发送到背景,然后再跟“&”号,然后立即启动myCommand2并将其也发送到背景,因此再次释放外壳。

清单

为了更好地理解,您可以在此处通过命令替换管道

列表是由一个运算符分隔的一个或多个流水线的序列; &&|| ,并可选地由以下之一终止 ;

如果命令由控制操作符终止,则外壳程序将在子外壳程序的后台执行该命令。外壳程序不等待命令完成,返回状态为0 按顺序执行;Shell等待每个命令依次终止。返回状态是最后执行的命令的退出状态。

AND和OR列表是由&&||分隔的一个或多个管道的序列。 分别控制操作员。
资源:man bash

让我们将其分解为示例。您可以通过组合命令并将命令与以下命令之一分开来构建列表; & && ||

command1 ; command2  # runs sequentially
command1 && command2 # runs sequentially, runs command2 only if command1 succeeds
command1 || command2 # runs sequentially, runs command2 only if command1 fails
command1 & command2  # runs simultaneously

您可以使用以下其中一项终止列表:; & <newline>
通常,您通过按Enter等于来执行命令或列表<newline>。分号;具有相同的目的,尤其是在脚本中。符号&然而在背景子shell启动该命令(S),立即释放外壳。

您可以使用()圆括号或大括号{}将列表进一步分组,不同之处在于圆括号会生成子外壳,而大括号则不会。弯括号在第一个括号后需要一个空格,在结束括号之前需要一个分号或换行符。例如:

# if c1 succeeds start a shell in the background
# and run c2 and c3 sequentially inside it
c1 && ( c2 ; c3 ) & 
# run c1 and if it succeeds c2 sequentially as a group command
# if c1 or c2 fail run c3 in the background
{ c1 && c2 ;} || c3 &

如果您不确定使用truefalse测试构造是否按预期工作,这可能会变得非常复杂:

$ { true && true ;} || echo 2
$ { true && false ;} || echo 2
2

工作控制

jobs命令显示当前外壳中正在运行或最近已完成的后台作业的列表。有许多键盘快捷键和命令可用于作业控制:

  • Ctrl+ Z键入使当前在前台运行的进程停止的挂起字符,它不会终止,而是保留在jobs列表中
  • Ctrl+ Y键入延迟的挂起字符,当尝试从终端读取输入时,导致当前在前台运行的进程被停止
  • fg= %如有必要,可将某个进程置于前台,您可以按以下方式指定该进程:

     %       # last process in the jobs list
     %1      # 1st process in the jobs list
     %abc    # process beginning with the string “abc”
     %?abc   # process containing the string “abc” anywhere
    
  • bg= %&在必要时将进程引入后台:

     %&      # last process in the jobs list
     %1&     # 1st process in the jobs list
     %abc&   # process beginning with the string “abc”
     %?abc&  # process containing the string “abc” anywhere
    
  • wait 等待后台进程完成并返回其终止状态:

     wait %1 # 1st process in the jobs list

    想象一下,您开始了一个漫长的过程(jobs显示为3),然后意识到您希望计算机在完成时被挂起,echo如果过程没有成功,还会显示一条消息:

     wait %3 || echo failed ; systemctl suspend

但是要特别注意&&,它取决于命令返回的内容,因此我们需要确保无论调用什么实际上都会返回bash认为是真实值的东西。
mathreadler's

@mathreadler除非您谈论的是一些性能不佳的用户脚本,否则退出值定义得很好(请参阅参考资料man bash),并且完全按照预期的用途使用AFAIK –我从没经历过任何奇怪的事情。
甜点,

确切地说,应该注意制作不良的用户脚本。它们确实存在,找到此类错误可能很痛苦。Askubuntu不允许我“ @甜点”您。
mathreadler

好的,既然您提到了,那就有意义了。
mathreadler '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.