我想知道,bash 脚本如何完成需要依次执行的任务。
这里有一个例子,我想在我的 CentOS VPS 上安装以下软件。
$ yum update
$ yum install libvpx-devel
$ sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
$ yum install nginx
$ wget https //dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb - Chrome_stable
$ mkdir foo
$ mv Chrome_stable foo
你明白我的意思,我每周必须执行大量命令。因此,我的问题是,由于某些安装可能会失败,而其他安装则需要等待一个安装完成后才能继续下一个安装。
那么,有没有办法告诉 bash 等到一次安装/下载完成后再执行下一个命令,并且在移动之前检查前一次安装是否成功。
答案1
如果您正在执行的进程在前台运行(上面显示的所有内容都在前台运行),则您不需要告诉 bash 等待 - 它会阻止等待它们退出。
一旦它们退出,bash 就可以检查返回代码并根据该代码做出不同的行为。最后一个子进程的返回代码存储在 $? 变量中:
#!/bin/bash
yum update
if [ $? -ne 0 ]; then
echo "Sorry, yum update had non-zero exit code, why don't we stop here?"
exit 1
fi
yum install libvpx-devel
...
请注意,Unix 惯例是返回代码 0 表示进程成功,返回其他任何代码表示存在问题。问题可能很简单(例如,grep 无法找到您要查找的字符串),也可能更复杂。
另请注意,您可以使用 && 和 || 运算符在一行中利用返回代码:
yum update && echo "yum succeeded"
yum update || echo "yum failed"
回复评论中@Contax 的问题:
“yum update” 和 “$?” 之间的关系是每一个运行的程序有一个返回给操作系统的退出代码。如果程序未指定,它通常默认为 0(成功),但可以在程序中指定(例如,上面脚本中显示的“exit 1”将该脚本的退出代码设置为 1。在 C 中,main() 函数中的“return(-1)”将导致程序的退出代码为 -1。)Bash 会自动读取此退出代码并将其填充到 $? 中供您使用。只需将其视为管道的一部分 - 它位于墙后,它使一切正常运转。
如果您有很多任务要执行,那么这确实会很乏味。这就是为什么 95% 的 shell 脚本不进行任何错误检查,当出现问题时会以惊人的方式崩溃 :) 您必须为if [ $? -ne 0 ]; then
每个任务创建一个子句。如果您真的很有冒险精神,您可以找到一种方法将您的执行包装到循环中并重新使用代码,但这可能得不偿失。
|| 简写对于在代码简单性和错误检查之间进行折衷非常有用。正如您所注意到的,if
为所有内容编写一个子句是一件非常麻烦的事情,但yum update || exit 1
会导致您的脚本在该过程失败时快速而安静地放弃。这比花时间打印出信息并进行清理要不友好,但比继续运行注定会失败的命令要好,因为之前的步骤失败了。