在Linux上,如果你想要多条命令一起运行,有几种方式可以实现,但具体使用哪种方式取决于你希望这两条命令如何并行或顺序执行。
1、顺序执行:如果你希望第一条命令执行完毕后,再执行第二条命令,你可以简单地将它们写在同一行,用分号(;)分隔。例如:
command1;command2这样,无论command1执行成功还是失败,command2都会执行。
2、并行执行:如果你希望多条命令同时执行,互不干扰,可以使用&符号将第一条命令放在后台执行,然后立即执行第二条命令。但请注意,这实际上并不是将多个命令“拼接”在一起执行,而是让第一个命令在后台运行,同时立即开始执行第二个命令。例如:
command1&command2但请注意,由于&只是将command1放入后台,如果command1的输出很重要,你可能需要重定向其输出到文件或使用其他方式捕获。
3、使用&&和||进行条件执行
&&:仅当第一个命令成功执行(即退出状态为0)时,才执行第二个命令。
||:仅当第一个命令执行失败(即退出状态非0)时,才执行第二个命令。
例如:
command1&&command2# 如果command1成功,则执行command2command1||command2# 如果command1失败,则执行command24、如果你在脚本里启动了后台程序,可以使用wait等待后台进程
#!/bin/bash# 启动一个后台进程(比如sleep 5)sleep5&# 获取最后一个后台进程的PIDlast_pid=$!# 输出这个PIDecho"最后一个后台进程的PID是:$last_pid"# 等待这个特定的后台进程完成wait$last_pid# 输出完成信息echo"后台进程已完成"5、管道,上面的执行方法中,不难发现少一个|,单独写在这里,是因为在linux中|是管道的意思,也就是说严格规范的使用含义是把上一个命令的输出作为下一个命令的输入,但是如果使用场景允许,确实可以作为顺序执行的方法
6、如果你要执行的命令完全一致,从而批量执行命令,可以使用 xargs 命令完成,比如对所有机器发送一条命令
#!/bin/bashLOCAL_FILE="/path/to/local/file"REMOTE_DIR="/path/to/remote/dir"USER="your_username"# servers.txt 每行一个机器域名# 使用xargs并行执行scp命令,-P 10指定并行度为10, -I {} 这是个固定写法用来代指拿到的数据,后面的命令可以用 {} 占位符catservers.txt|xargs-P10-I{}scp-r"${LOCAL_FILE}""${USER}@{}:${REMOTE_DIR}"如果你要做的事情,比较复杂,需要一个代码块,你可以导出一个方法
get_presto_task(){localquery_id=$1locallast_part="${query_id##*_}"localdata_position=$((last_part%JOBS))curl-s"$SERVER/v1/query/$query_id">>"${OUTPUT_FILE}.${data_position}"}export-fget_presto_task# xargs 命令是 sh 解析器,所以要通过 bash -c 的方式显示切回 bash,"$@" 这是个固定写法,用来代指对后面的参数拆包 , _ {} 这部分就是脚本参数列表 _ 是缺省写法你也可以给本次bash进程写个具体名字,{} 是管道拿到的内容做第一个参数的意思cat"$TMP_QUERYIDS"|xargs-I{}-P"$JOBS"bash-c'get_presto_task "$@" '_{}多个命令同时执行时,往往会另行指定 bash 对错误的处理方式,也就是把下面的命令放在脚本的最上方
# 定义脚本对执行中出现错误的处理方式# -e 任意命令返回非零状态时立即终止脚本# -u 引用未定义变量时直接报错退出,防止空值注入# -o pipefail 管道中任一命令失败,整个管道返回失败状态(默认只检测最后一个命令)set-euopipefail此时,$?会失效,因为遇到错误脚本就退出了,需要使用||逻辑
# 方法1:|| 短路逻辑(set -e 不会终止)curl-s"$SERVER/v1/query/$query_id">>"${OUTPUT_FILE}.${data_position}"||{echo"请求失败:$query_id"# 可以记录日志、跳过、重试等}或者临时告诉脚本这个命令可以失败
curl-s"$SERVER/v1/query/$query_id">>"${OUTPUT_FILE}.${data_position}"||true还有一种写法是,将命令放在 if 中
# 用 if 包裹(if 条件中的命令失败不会触发 set -e)if!curl-s"$SERVER/v1/query/$query_id">>"${OUTPUT_FILE}.${data_position}";thenecho"请求失败:$query_id"fi# 简写[[!curl-s"$SERVER/v1/query/$query_id">>"${OUTPUT_FILE}.${data_position}]] && echo "请求失败:$query_id"