命令链:内联或正在运行的进程
概述
有时您可能希望在Linux中顺序运行多个命令。为此,您可以使用命令链。例如,如果您想下载一个压缩存档,解压缩它,然后从磁盘中删除生成的存档,您可以将这三个命令一起输入。
在这里,我们将了解一些使用Linux中的Bash序列化命令的方法。即使它们已经在运行。
内联命令链
Bash为最终用户提供了极大的灵活性和强大的功能。我们可以创建长指令序列来执行任意数量的任务。
<command1> <arguments1> <链接运算符> <command2> <arguments2> ...
链式操作包括几种常见的操作,因此我们将在这里介绍它们。
; (分号) − 右侧的命令总是在左侧命令之后运行,即使左侧命令失败也是如此。
& (与号) − 左侧是“后台运行”选项;右侧是“立即启动”选项。
| (管道) − 左侧命令的标准输出连接到右侧命令的标准输入。
&& (AND) − 如果左侧命令成功,则执行右侧命令。否则,不执行右侧命令。
|| (OR) − 如果左侧命令执行成功(返回零),则执行右侧命令。
您还可以将语句括在括号中以在子shell中执行它们。
( <command1> && <command2> ) & ( <command3> && <command4> ) &
这两个命令将一个接一个地执行。在每个命令中,第二个结果决定最后一个结果。
使用已运行进程的命令链
我们将研究如何使用Wait()函数在已经启动一个shell脚本后执行第二个shell脚本。这是对称为Wait()的系统调用的包装器。
在不带任何参数运行时,它等待当前shell的所有后台进程。如果没有给出参数,它将挂起shell,直到所有进程完成。
您可以使用pidsof命令获取所有具有相似名称的正在运行进程的进程ID (PID)。假设我们要运行三个后台10秒sleep命令,然后检查哪些命令成功了。我们可以输入:
$ sleep 10 & [1] 26176 $ sleep 10 & [2] 26178 $ sleep 10 & [3] 26179 $ wait $(pidof sleep) && echo Waited for 3 10-second sleeps [1] Done sleep 10 [2]- Done sleep 10 [3]+ Done sleep 10 Waited for 3 10-second sleeps
您可以通过将多个命令组合成一个命令来获得相同的结果。例如,您可以使用以下命令序列:ps -ef | grep -v 'string'。
$ wait $(ps -ef | grep <process name> | tr -s ' ' | cut -f 2 -d ' ' ) && echo Waited for 3 10-second sleeps
命令链显示了将多个操作链接在一起的另一种方法。$()函数告诉我们括号内代码的输出将用作wait函数的参数。在我们的例子中:
ps −ef − 收集所有包含详细信息的进程
grep <进程名称> − 从ps −ef输出中选择包含<进程名称>的行
tr −s ‘ ‘ − 从grep的输出中删除任何重复出现的' '(空格)
cut −d ‘ ‘ −f 2 − 通过指定空格字符作为分隔符,从tr输出中选择第二列。例如,如果我们使用ps −ef | grep java列出系统上所有正在运行的进程,然后仅过滤出其父PID与上一步中PID匹配的进程。
wait命令的限制
对于WAITTEST_TIMEOUT变量,WAITTIME返回程序开始等待指定命令的时间。但是,如果我们依赖于已完成命令的PID,则它不可靠,例如,它无法返回其实际结果。如果应用程序返回的错误代码大于128,则无法判断应用程序是由于信号终止还是自行终止。
最后,`sleep`的一个限制是它只能休眠在同一shell上启动的进程。如果我们需要运行其他用户的进程或在其他shell中打开,则必须使用其他不太直接的方法,例如pidof循环。
while ( pidof -q <command_to_wait> ); do sleep 1; done && <command_to_execute_after>
Wait是sleep的更通用但功能较弱的替代方案。它依赖于特定的休眠周期,并且无法评估目标操作的结果。在shell脚本中迭代之间使用sleep很重要,因为它会将CPU时间返还给系统。特别是如果脚本结束得太快。
结论
我们已经看到了一些在shell脚本中使用命令链的常见方法——既包括内联,也包括等待另一个脚本完成后再继续。还有更多选项和更大的灵活性可用。您可以使用这些技术来创建脚本、函数、条件或循环。