我想在 bash 腳本的 while 回圈中啟動一系列后臺作業:
END=10
i=0;
while [ $i -lt $END ]
do
(SOME COMMAND;\
sleep 3;
SOME COMMAND 1;\
SOME COMMAND 2;\
SOME COMMAND 3;) &
i=`expr $i 1`
done
在這個while回圈之外,我想等到所有這10個后臺作業都完成SOME COMMAND 1然后繼續,所以psudo代碼是這樣的:
until [the number of process that finished SOME COMMAND 1 is greater or equal to $END];
do
sleep 0.5
done
我試圖做的是添加另一個這樣的計數器:
true_started_cnt=0
END=10
i=0;
while [ $i -lt $END ]
do
(SOME COMMAND;\
sleep 3;
SOME COMMAND 1;\
true_started_cnt=`expr $true_started_cnt 1`;\
SOME COMMAND 2;\
SOME COMMAND 3;) &
i=`expr $i 1`
done
until [ $true_started_cnt -ge $END ]
do
echo "Waiting for initial period for all streams to finish"
sleep 0.5
done
但這似乎不起作用,可能是因為多個 bg 作業同時寫入同一個全域變數。我想知道如何在這段代碼中實作我的意圖。
參考這篇文章,我也在嘗試:
echo 1 >/dev/shm/foo
END=10
i=0;
while [ $i -lt $END ]
do
(SOME COMMAND;\
sleep 3;
SOME COMMAND 1;\
echo $(($(</dev/shm/foo) 1)) >/dev/shm/foo;\
SOME COMMAND 2;\
SOME COMMAND 3;) &
i=`expr $i 1`
done
until [ $(echo $(</dev/shm/foo)) -ge $END ]
do
echo "Waiting, true_started_cnt=$(echo $(</dev/shm/foo))"
sleep 1
done
但仍然無法正常作業。
uj5u.com熱心網友回復:
您的上一個腳本中也可能存在競爭條件,請嘗試以下操作:
cp /dev/null /dev/shm/foo
END=10
for ((i=0; i<$END; i )); do
(
echo SOME COMMAND;\
sleep $((i 1));\
echo $i SOME COMMAND 1;\
echo $i >>/dev/shm/foo;\
echo $i SOME COMMAND 2;\
sleep $((i 1));\
echo $i SOME COMMAND 3
) &
done
until [ $(wc -l /dev/shm/foo | awk '{print $1}') -ge $END ]
do
echo "Waiting, /dev/shm/foo contains $(echo $(</dev/shm/foo))"
sleep 1
done
echo "*********** All SOME COMMAND 1 finished"
wait
echo "Script finished"
uj5u.com熱心網友回復:
如果您只想確保所有行程都退出,則不需要記錄進度。
#!/bin/bash
END=10
pids=()
for (( i = 0; i < END; i )); do
( sleep "$(( RANDOM % 10 1 ))" ) &
pids[$!]=$!
done
while [[ ${#pids[@]} -gt 0 ]]; do
for pid in "${pids[@]}"; do
echo "Waiting for $pid to exit."
wait "$pid"
kill -s 0 "$pid" >/dev/null || unset 'pids[pid]'
done
sleep 1
done
uj5u.com熱心網友回復:
您可以使用 FIFO 佇列來表示某個階段的作業完成:
集合點.sh
#!/usr/bin/env bash
shopt -so errexit
shopt -so nounset
declare -ri job_count=5
# A FIFO queue where jobs will signal their completion.
mkfifo rendezvous
# Clean up FIFO queue on script exit.
trap EXIT EXIT; EXIT() {
rm -f rendezvous
trap - EXIT # Restore default interrupt handler.
kill -s EXIT "$$" # Propagate interrupt.
}
# Wait until the known number of jobs have signaled their completion to the
# FIFO queue.
wait_rendezvous() {
(
local -i counter=0
while read -r; do
(( counter ))
if (( counter == job_count )); then
break
fi
done
) < rendezvous
}
# Signal completion to the FIFO queue.
show_at_rendezvous() {
# For some reason, without the trailing ampersand some A jobs end up
# dangling.
echo "done" > rendezvous &
}
#
# Actual script logic starts below.
#
command_a() {
local -i job_id=$1
echo "Command A[$job_id]: start"
sleep 5
show_at_rendezvous
echo "Command A[$job_id]: done"
}
command_b() {
local -i job_id=$1
echo "Command B[$job_id]: start"
sleep 10
echo "Command B[$job_id]: done"
}
# Launch jobs.
for i in $(seq 1 "$job_count"); do
command_a "$i" &
command_b "$i" &
done
# Wait for all A jobs to signal their completion.
wait_rendezvous
echo "All A commands done; now awaiting for B commands..."
# Wait for all remaining jobs to finish.
wait
echo "All B commands done."
輸出
$ ./rendezvous.sh
Command A[1]: start
Command B[1]: start
Command A[2]: start
Command B[2]: start
Command A[3]: start
Command B[3]: start
Command A[4]: start
Command B[4]: start
Command A[5]: start
Command B[5]: start
Command A[2]: done
Command A[1]: done
All A commands done; now awaiting for B commands...
Command A[5]: done
Command A[3]: done
Command A[4]: done
Command B[1]: done
Command B[2]: done
Command B[3]: done
Command B[4]: done
Command B[5]: done
All B commands done.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/407342.html
標籤:
