我正在 shell 中编写一个脚本,其中一个命令正在运行并且需要 2 分钟。每次。此外,我们对此无能为力。但是如果我想在脚本中运行这个命令 100 次,那么总时间将是 200 分钟。这将产生一个大问题。没有人愿意等待 200 分钟。我想要的是并行运行所有 100 个命令,以便输出将在 2 分钟内出现,或者可能需要更多时间,但不需要 200 分钟。
如果有任何机构可以以任何方式帮助我,我们将不胜感激。
GNU Parallel就是你想要的,除非你想重新发明轮子。这里有一些更详细的例子,但很短:
ls | parallel gzip # gzip all files in a directory
...并行运行所有 100 个命令,以便输出将在 2 分钟内出现
这只有在您的系统上有 200 个处理器时才有可能。
shell 脚本中没有这样的实用程序/命令来并行运行命令。你可以做的是在后台运行你的命令:
for ((i=0;i<200;i++))
do
MyCommand &
done
使用&
(背景),每次执行都会尽快安排。但这并不能保证您的代码将在 200 分钟内执行完毕。这取决于您的系统上有多少个处理器。
如果您只有一个处理器,并且每次执行命令(需要 2 分钟)都在 2 分钟内进行一些计算,那么处理器正在做一些工作,这意味着没有浪费任何周期。在这种情况下,并行运行命令并没有帮助,因为只有一个处理器也不是空闲的。因此,这些进程将只是等待轮到它们执行。
如果您有多个处理器,那么上述方法(for 循环)可能有助于减少总执行时间。
As @KingsIndian said, you can background tasks, which sort of lets them run in parallel. Beyond this, you can also keep track of them by process ID:
#!/bin/bash
# Function to be backgrounded
track() {
sleep $1
printf "\nFinished: %d\n" "$1"
}
start=$(date '+%s')
rand3="$(jot -s\ -r 3 5 10)"
# If you don't have `jot` (*BSD/OSX), substitute your own numbers here.
#rand3="5 8 10"
echo "Random numbers: $rand3"
# Make an associative array in which you'll record pids.
declare -A pids
# Background an instance of the track() function for each number, record the pid.
for n in $rand3; do
track $n &
pid=$!
echo "Backgrounded: $n (pid=$pid)"
pids[$pid]=$n
done
# Watch your stable of backgrounded processes.
# If a pid goes away, remove it from the array.
while [ -n "${pids[*]}" ]; do
sleep 1
for pid in "${!pids[@]}"; do
if ! ps "$pid" >/dev/null; then
unset pids[$pid]
echo "unset: $pid"
fi
done
if [ -z "${!pids[*]}" ]; then
break
fi
printf "\rStill waiting for: %s ... " "${pids[*]}"
done
printf "\r%-25s \n" "Done."
printf "Total runtime: %d seconds\n" "$((`date '+%s'` - $start))"
You should also take a look at the Bash documentation on coprocesses.