Tro*_*fin 5 linux shell scripting
我有 2 个包含 ffmpeg 命令的 shell 脚本(command1.sh 和 command2.sh)。command2.sh 有大约 500 个 ffmpeg 命令,这些命令通过“;”依次触发,而 command1.sh 处理音频 ffmpeg 命令。
主要问题:杀死整个脚本需要太多时间,并且它会占用我执行另一个脚本所需的 1-2 分钟的 CPU 功率,所以我白白失去了 CPU 功率,因为我无法立即杀死它。
代码: 我有init.sh其中包含:
trap 'print TERM received;exit' 15
chmod +x command1.sh;
chmod +x command2.sh;
./command1.sh & ./command2.sh
Run Code Online (Sandbox Code Playgroud)
所以它会在后台触发。
然后我执行pkill init.sh并捕获 shell陷阱并退出shell 脚本,但我得到 exitCode: 1, failed: true ,并且后台的命令仍执行 1 分钟,直到它们被另一个kill ${pid 杀死我在 pkill 之后执行。
chmod +x在这里是没用的。你完全可以跑步sh command1.sh &。就像是:
#!/bin/sh
for cmd in ./command1.sh ./command2.sh;do
exec $cmd &
PIDS="$PIDS $!"
done
trap "kill $PIDS;exit" 15
wait
Run Code Online (Sandbox Code Playgroud)
当然,在for cmd in和 之间;do,您可以输入任意数量commandXX.sh(只要您将行长度保持在所安装操作系统支持的最大长度内)
这是一个快速的bash测试脚本,它在 2.0 到 12.99 秒之间随机休眠,然后done.在退出前打印:
#!/bin/bash
declare -i toSleep
case $1 in '' | *[!0-9]* ) toSleep='RANDOM%10+2' ;; * ) toSleep=$1 ;; esac
exec {dummy}<> <(:)
read -t $toSleep.$RANDOM -u $dummy _
echo done.
Run Code Online (Sandbox Code Playgroud)
我已将其保存到command1.sh并chmod +x ..链接到command2.sh...
#!/bin/sh
for cmd in "$@";do
exec $cmd &
PIDS="$PIDS $!"
done
printf "You have to: kill -TERM %d\nto end %d tasks: %s\n" \
$$ $(echo $PIDS|wc -w) "$PIDS"
trap "kill $PIDS;echo 'Process $$ killed.';exit" 15
wait
echo "Process $$ running $@ ended normally"
Run Code Online (Sandbox Code Playgroud)
您可以将此shell脚本保存到名为 的文件中simpleParallel.sh(例如),然后:
chmod +x simpleParallel.sh
./simpleParallel.sh ./command1.sh ./command2.sh
You have to: kill -TERM 741297
to end 2 tasks: 741298 741299
Run Code Online (Sandbox Code Playgroud)
那么如果你kill -TERM 741297来自其他地方,
Process 741297 killed.
Run Code Online (Sandbox Code Playgroud)
但如果你不这样做,你可能会读到类似的内容:
./simpleParallel.sh ./command1.sh ./command2.sh
You have to: kill -TERM 741968
to end 2 tasks: 741969 741970
done.
done.
Process 741968 running ./command1.sh ./command2.sh ended normally
Run Code Online (Sandbox Code Playgroud)
注意:如果您在一个进程已完成时发送终止命令,您可能会看到如下错误消息:
./simpleParallel.sh: 1: kill: No such process
Run Code Online (Sandbox Code Playgroud)
查看bash版本可以避免这个错误。
在运行之前./simpleParallel.sh,您可以tty不带参数地运行:
tty
/dev/pts/2
Run Code Online (Sandbox Code Playgroud)
然后在一个新的免费窗口中,您可以运行:
watch ps --tty pts/2
Run Code Online (Sandbox Code Playgroud)
同时再次使用另一个窗口运行kill命令。
最近的bash下,有很多特色。
$EPOCHREALTIME变量,它以微秒粒度扩展为自Unix纪元以来的以秒为单位的时间。wait有一个新[-p VARNAME]选项,它存储PID带参数wait -n或wait不带参数返回的结果。我的脚本可能会变成:
#!/bin/bash
declare -A PIDS ENDED
started=$EPOCHREALTIME
for cmd; do
exec "$cmd" &
PIDS["$cmd"]=$!
CMDS[$!]="$cmd"
done
printf "You have to: kill -TERM %d\nto end %d tasks: %s\n" \
$$ ${#PIDS[@]} "${PIDS[*]}"
trapExit(){
kill "${PIDS[@]}"
printf 'Process %s + %d task killed: %s\n' $$ ${#PIDS[@]} "${!PIDS[*]}"
showDone
exit 1
}
trap trapExit 15
showDone() {
for cmd in "${!ENDED[@]}";do
read -r elap < <(bc -l <<<"${ENDED["$cmd"]}-$started")
printf "Elapsed: %.4f sec for %s\n" "$elap" "$cmd"
done
}
while ((${#PIDS[@]}));do if wait -n -p pid ;then
printf "Process %d done (%s).\n" "$pid" "${CMDS[pid]}"
ENDED["${CMDS[pid]}"]=$EPOCHREALTIME
unset PIDS["${CMDS[pid]}"] CMDS[pid]
fi; done
echo "Process $$ running $* ended normally"
showDone
Run Code Online (Sandbox Code Playgroud)
输出可能如下所示:
./simpleParallel.bash ./command{1,2}.sh
You have to: kill -TERM 1309816
to end 2 tasks: 1309817 1309818
done.
Process 1309817 done (./command1.sh).
done.
Process 1309818 done (./command2.sh).
Process 1309816 running ./command1.sh ./command2.sh ended normally
Elapsed: 3.1644 sec for ./command1.sh
Elapsed: 4.2488 sec for ./command2.sh
Run Code Online (Sandbox Code Playgroud)
或者
./simpleParallel.bash ./command{1,2}.sh
You have to: kill -TERM 1310031
to end 2 tasks: 1310032 1310033
done.
Process 1310033 done (./command2.sh).
done.
Process 1310032 done (./command1.sh).
Process 1310031 running ./command1.sh ./command2.sh ended normally
Elapsed: 9.1868 sec for ./command1.sh
Elapsed: 3.2310 sec for ./command2.sh
Run Code Online (Sandbox Code Playgroud)
如果你kill提早:
./simpleParallel.bash ./command{1,2}.sh
You have to: kill -TERM 1294577
to end 2 tasks: 1294578 1294579
Process 1294577 + 2 task killed: ./command1.sh ./command2.sh
Run Code Online (Sandbox Code Playgroud)
如果你kill稍后:
./simpleParallel.bash ./command{1,2}.sh
You have to: kill -TERM 1294958
to end 2 tasks: 1294959 1294960
done.
Process 1294959 done (./command1.sh).
Process 1294958 + 1 task killed: ./command2.sh
Elapsed: 3.1779 sec for ./command1.sh
Run Code Online (Sandbox Code Playgroud)
或者
./simpleParallel.bash ./command{1,2}.sh
You have to: kill -TERM 1294971
to end 2 tasks: 1294972 1294973
done.
Process 1294973 done (./command2.sh).
Process 1294971 + 1 task killed: ./command1.sh
Elapsed: 6.9344 sec for ./command2.sh
Run Code Online (Sandbox Code Playgroud)
并且没有关于尝试杀死不存在的 pid 的错误消息。
| 归档时间: |
|
| 查看次数: |
1243 次 |
| 最近记录: |