nohup 多个命令 &

问题

我需要执行多个任务(task1、task2),要求:

  1. 串行执行,task1执行成功后执行task2
  2. 后台执行,整个执行过程不能因session中断而停止
  3. 每个task的输出到单独的文件中

问:以下方案中,哪些是可行的:

nohup task1 > out1 && task2 > out2 &

nohup task1 > out1 & && nohup task2 > out2 &

nohup task1 > out1 && nohup task2 > out2 &

nohup task1 > out1 & nohup task2 > out2 &

结果

上述命令都无法完成要求

原因

&& 和 &

两者都可以用来分割命令,区别在于 && 只有在前一个命令执行成功(return 0)才会执行下一个命令,而 & 只是将其前面的命令放入后台执行,并立即返回

例如:

command1 && command2 && command3
# 只有 command1 执行成功后才会执行 command2,后面同理

command1 & command2 & command3
# 当程序读到第一个 & 时,会将其之前的命令放到后台执行
# 例如,读到第一个 & 时,将 command1 切割出来并放到后台执行,此时立即返回状态,继续向后读命令,又读到第二个 & 则又将 command2 切割放到后台执行并立即返回,继续往后执行命令,由于 command3 没有 &,故其只会在前台执行

command1 && command2 &
# & 的优先级比 && 高,故该代码会先整体进入后台,然后再通过 && 分割执行

&&、&、;、||

四个都可以用来分割命令,区别在于

  • && 前一个命令执行成功(return 0)才会执行下一个命令,类似 java 中的 &&
  • & 放入后台执行并立即返回,类似 js 中的 promise
  • || 前一个命令执行失败后一个命令才会执行,类似 java 中的 ||
  • ; 前一个命令执行完成,不管成功与否,都会执行下一个命令

nohup 和 &

从功能上看:

& 命令用于将任务放到后台执行,可以使用 jobs 命令查看,也可以使用 fg 命令重新放到前台

nohup 命令屏蔽session的终止信号,即当前session关闭后,命令仍然会执行。但其仍然是属于前台执行的,即当我使用 nohup 执行命令后,其会将标准输出重定向到一个文件,但其本身不会释放前台操作(直到程序执行完毕),此时关闭session后,从其他session中仍然能使用ps命令查看到该命令在继续运行

nohup等待程序执行完成,&则立即返回

从本质上看:

nohup 是 coreutils 软件包中的一个工具软件,而 & 或 && 等都是 bash 下的一种语法。

coreutils 是GNU下的一个软件包,包含linux下的 ls等常用命令。这些命令的实现要依赖于shell程序。

百度百科

& 和 ctrl-z

& 放入后台是继续执行的,c-z 则是暂停的

一段时间后

ctrl-c 和 ctrl-d

c-c 停止当前程序,c-d 停止当前进程

多数情况下,c-d 的作用和键入 exit 的作用相同,例如,在用户登录后的shell按 c-d 则退出当前session(同输入exit),在tmux窗口中按 c-d 则退出当前窗口(同输入exit),在docker -it container sh中按下 c-d 退出container的shell(同exit)

> 和 &> 和 >&

文件描述符:相当于一个文件别名,在bash中,0 表示标准输入,1表示标准输出,2表示标准错误输出

文件名称:某个文件的名称

  1. 文件描述符 > 文件名称
  2. 文件描述符 >& 文件描述符
  3. &> 文件名称

文件描述符若省略不写,则使用 标准输出(1) 作为默认输出,或者 标准输入(0) 作为默认输入

> file_name 等价于 1> file_name,即将标准输出重定向到某个文件

&> file_name 等价于 1>file_name 2>&1,即将标准输出和标准错误输出都重定向到某个文件(注:这种写法只会打开一次文件,若真的手动将其写开,如 1 > f… 2 > f,则会打开两次文件,结果可能不正常)

故,如果你这些写某个命令 git status 2 &> 1,其等价于 git status 2 1>1 2>&1。注意其中的2,第一个2将作为 git status 的参数,第二个2表示标准错误输出,第一个和最后一个1表示表示输出,而第二个1则表示一个文件,这意味着其会将标准输出和错误输出都重定向到一个名称为 1 的文件中。

译自:https://stackoverflow.com/questions/24793069/what-does-do-in-bash

bash 和 shell

shell既指一种计算机语言,也指人机交互接口。

当它作为人机交互接口时,其作用就是接受并解释用户输入的指令(linux命令窗口),bash是shell的一种,另外还有 sh、ash 等。

也就是说 shell 是一系列交互接口的总称,一个苹果(shell)也细分为青苹果(sh)红苹果(ash)等

使用 echo $SHELL 即可查看当前使用的默认shell

正确做法

1. 将所有的命令写入到一个shell脚本中

# task.sh
task1 > out1 && task2 > out2

然后执行该脚本

nohup bash task.sh &

2. 直接使用 bash -c

nohup bash -c "task1 > out1 && task2 > out2" &

再看 nohup command >out 2>&1 &

再回头看这个命令就很清晰明了了,你再不会认为上述各个指令有什么搭配的关系了,它们都是相互独立的,即你去掉任意一个(除command)指令,它都是正确的

  • nohup
  • command
  • >out
  • 2>&1
  • &

它们之间都没有任何搭配关系,而仅仅是组合起来各自发挥各自的功效而已

Leave a Comment