问题
我需要执行多个任务(task1、task2),要求:
- 串行执行,task1执行成功后执行task2
- 后台执行,整个执行过程不能因session中断而停止
- 每个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) 作为默认输出,或者 标准输入(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
- &
它们之间都没有任何搭配关系,而仅仅是组合起来各自发挥各自的功效而已