我正在尝试编写一个.sh文件,同时运行许多程序
我试过了
prog1
prog2
但是它会运行prog1,然后等待prog1结束,然后启动prog2……
那么如何并行运行呢?
我正在尝试编写一个.sh文件,同时运行许多程序
我试过了
prog1
prog2
但是它会运行prog1,然后等待prog1结束,然后启动prog2……
那么如何并行运行呢?
当前回答
这里有很多有趣的答案,但我从这个答案中获得了灵感,并将一个简单的脚本组合在一起,并行运行多个进程,并在完成后处理结果。你可以在以下要点中找到它:
#!/usr/bin/env bash
# inspired by https://stackoverflow.com/a/29535256/2860309
pids=""
failures=0
function my_process() {
seconds_to_sleep=$1
exit_code=$2
sleep "$seconds_to_sleep"
return "$exit_code"
}
(my_process 1 0) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 1 second to success"
(my_process 1 1) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 1 second to failure"
(my_process 2 0) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 2 seconds to success"
(my_process 2 1) &
pid=$!
pids+=" ${pid}"
echo "${pid}: 2 seconds to failure"
echo "..."
for pid in $pids; do
if wait "$pid"; then
echo "Process $pid succeeded"
else
echo "Process $pid failed"
failures=$((failures+1))
fi
done
echo
echo "${failures} failures detected"
结果是:
86400: 1 second to success
86401: 1 second to failure
86402: 2 seconds to success
86404: 2 seconds to failure
...
Process 86400 succeeded
Process 86401 failed
Process 86402 succeeded
Process 86404 failed
2 failures detected
其他回答
并行运行多个程序:
prog1 &
prog2 &
如果你需要脚本等待程序完成,你可以添加:
wait
在您希望脚本等待它们的地方。
#!/bin/bash
prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log
将错误重定向到单独的日志。
使用GNU Parallel http://www.gnu.org/software/parallel/,它就像:
(echo prog1; echo prog2) | parallel
或者如果你喜欢:
parallel ::: prog1 prog2
了解更多:
观看介绍视频快速介绍: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1 浏览教程(man parallel_tutorial)。您的命令行 会因此爱你的。 阅读:Ole Tange, GNU Parallel 2018 (Ole Tange, 2018)。
由于某些原因,我不能使用等待,我想出了这个解决方案:
# create a hashmap of the tasks name -> its command
declare -A tasks=(
["Sleep 3 seconds"]="sleep 3"
["Check network"]="ping imdb.com"
["List dir"]="ls -la"
)
# execute each task in the background, redirecting their output to a custom file descriptor
fd=10
for task in "${!tasks[@]}"; do
script="${tasks[${task}]}"
eval "exec $fd< <(${script} 2>&1 || (echo $task failed with exit code \${?}! && touch tasks_failed))"
((fd+=1))
done
# print the outputs of the tasks and wait for them to finish
fd=10
for task in "${!tasks[@]}"; do
cat <&$fd
((fd+=1))
done
# determine the exit status
# by checking whether the file "tasks_failed" has been created
if [ -e tasks_failed ]; then
echo "Task(s) failed!"
exit 1
else
echo "All tasks finished without an error!"
exit 0
fi
如果您有一个GUI终端,您可以为希望并行运行的每个进程生成一个新的选项卡终端实例。
这样做的好处是,每个程序都在自己的选项卡中运行,它可以独立于其他运行的程序进行交互和管理。
例如,在Ubuntu 20.04上:
gnome-terminal --tab -- bash -c 'prog1'
gnome-terminal --tab -- bash -c 'prog2'
要按顺序运行某些程序或其他命令,可以添加;
gnome-terminal --tab -- bash -c 'prog1_1; prog1_2'
gnome-terminal --tab -- bash -c 'prog2'
我发现对于某些程序,终端在启动之前就关闭了。对于这些程序,我将终端命令与;等待或;睡眠1
gnome-terminal --tab -- bash -c 'prog1; wait'
对于Mac OS,你必须为你正在使用的终端找到一个等效的命令——我没有在Mac OS上测试,因为我没有Mac。