![如何编写 bash 脚本,当且仅当前一个命令的处理完成时才触发下一个命令](https://linux22.com/image/154042/%E5%A6%82%E4%BD%95%E7%BC%96%E5%86%99%20bash%20%E8%84%9A%E6%9C%AC%EF%BC%8C%E5%BD%93%E4%B8%94%E4%BB%85%E5%BD%93%E5%89%8D%E4%B8%80%E4%B8%AA%E5%91%BD%E4%BB%A4%E7%9A%84%E5%A4%84%E7%90%86%E5%AE%8C%E6%88%90%E6%97%B6%E6%89%8D%E8%A7%A6%E5%8F%91%E4%B8%8B%E4%B8%80%E4%B8%AA%E5%91%BD%E4%BB%A4.png)
我有这样的命令,它将触发一个进程
./extract.sh 1553212800 1554854400 &
例如,这将给出一个进程 ID1234
我只想在1234
完成后运行下一个命令
./extract.sh 1554854400 1556668800 &
类似这样的命令还有很多
答案1
如果您想等待它完成,似乎没有必要将其放在后台,但是:
./extract.sh 1553212800 1554854400 &
pid=$!
if wait "$pid"; then
./extract.sh 1554854400 1556668800 &
fi
内置程序wait
退出时显示:
返回最后一个ID的状态;如果 ID 无效或给出的选项无效,则失败。
答案2
你可以删除&
每个命令末尾的 ,这样 shell 就会运行这些命令不是作为后台任务,或者,如果您确实需要将它们作为后台任务运行(因为您还并行执行其他操作),则需要将进程的 PID 保存在变量中,然后wait
才能完成:
./extract.sh 1553212800 1554854400 & pid="$!"
# other things
wait "$pid"
./extract.sh 1554854400 1556668800 & & pid="$!"
# other things (again)
wait "$pid"
# etc.
就我个人而言,如果我有一长串此类命令,我会将它们全部放在一个脚本中,例如
#!/bin/sh
./extract.sh 1553212800 1554854400
./extract.sh 1554854400 1556668800
(注意,没有后台作业)
然后我可能会这样开始脚本nohup
:
nohup ./script.sh &
这将允许我注销然后重新登录以查看脚本进程是否仍在运行(通过使用检查ps
)。
或者,我只需启动一个tmux
会话,然后像平常一样启动脚本(否nohup
),然后按Ctrl+Bd与之分离。稍后,我可以使用 . 回到相同的 shell 会话tmux attach
。请参阅tmux
手册。
答案3
虽然这可能无法直接回答所述问题,但我想我会提出这个解决方案,特别是因为 OP 看起来还没有确定管道。
在许多 Posix shell 中,可以通过符号将多个命令链接在一起&&
。基本上,这意味着运行第一个命令,然后在第一个命令运行完成且没有错误后,运行&&
.例如:
./extract.sh 1553212800 1554854400 && ./extract.sh 1554854400 1556668800 &
但是,这会将所有内容作为单个大型后台进程运行。此外,您还面临着永远不会运行引发错误的命令后面的命令的风险。所以在这样的场景中:
./valid_run.sh && ./throws_error.sh && ./second_valid_run.sh
如果valid_run.sh
运行正常,但throws_error.sh
不运行,则second_valid_run.sh
不会运行。
或者,一种更简洁的方法是将所有命令保存在包装器 BASH 脚本中,然后运行该脚本:
包装器.sh:
#!/bin/bash
./extract.sh 1553212800 1554854400
./extract.sh 1554854400 1556668800
命令行:
$ ./wrapper.sh &
我认为这可能是组织命令的最佳方式。