我创建了一个bash脚本来连接到多个服务器并执行程序。每个IP的IP和数量应该从如下结构的配置文件中读取:
127.0.0.1 10
127.0.0.1 1
127.0.0.1 3
etc
j=$((0))
while IFS=' ' read -r ip quantity; do
echo "${ip} x ${quantity}";
for (( i = 1; i <= quantity; i++ ))
do
echo "ssh root@${ip} cd test/libhotstuff && ./examples/hotstuff-app --conf ./hotstuff.gen-sec${j}.conf > log${j} 2>&1"
ssh root@"${ip}" "cd test/libhotstuff && ./examples/hotstuff-app --conf ./hotstuff.gen-sec${j}.conf > log${j} 2>&1" &
j=$((j+1))
done
sleep 1
done < ips
我注意到,如果执行时间过长,while循环就会中断。如果我在这里睡眠1秒,它将在第一次执行后停止。如果我删除它,但内部循环花费的时间太长,则不会读取行的子集。
这里有什么问题?
这是一个版本,它启动后台进程时每个进程之间有1秒的延迟,等待6分钟后逐个杀死它们,每个进程之间都有1秒的延时,以使它们的运行时间大致相同。
您还应该为ssh
添加一些选项,以防止它干扰stdin
,并在运行时提前终止循环。
-n
阻止从stdin读取-oBatchMode=yes
密码短语/密码查询将被禁用-oStrictHostKeyChecking=no
即使主机密钥已更改,也要连接到主机
#!/bin/bash
sshopts=(-n -oBatchMode=yes -oStrictHostKeyChecking=no)
j=0
pids=()
while IFS=$' tn' read -r ip quantity; do
echo "${ip} x ${quantity}";
for (( i = 0; i < quantity; ++i ))
do
remotecmd="cd test/libhotstuff && ./examples/hotstuff-app --conf ./hotstuff.gen-sec${j}.conf > log${j} 2>&1"
localcmd=(ssh ${sshopts[@]} root@${ip} "$remotecmd")
echo "${localcmd[@]}"
"${localcmd[@]}" &
# store the background pid
pids+=($!)
(( ++j ))
sleep 1
done
done < ips
seconds=360
echo "running ${pids[@]} in the background $seconds seconds"
sleep $seconds
echo "telling the background processes to terminate"
for pid in ${pids[@]}
do
echo killing $pid
kill $pid
sleep 1
done
echo "waiting for all the background processes to terminate"
wait
echo Done
这是一个将循环和并行进程卸载到远程shell脚本的版本。从具有数量的HereDocument生成远程shell脚本,并等待所有后台进程终止后再退出。
#!/usr/bin/env sh
while IFS=$' tnr' read -r ip quantity || [ -n "$quantity" ]
do
{
# When satisfied by the output:
# Ucomment the line below and delete its following line with the echo and cat
# ssh "root@$ip" <<EOF
echo ssh "root@$ip"; cat <<EOF
if cd test/libhotstuff
then
i=$quantity
until
i=$((i - 1))
[ $i -lt 0 ]
do
./examples/hotstuff-app \
--conf "./hotstuff.gen-sec$i.conf" >"log$i" 2>&1 &
done
wait
fi
EOF
} &
done <ips
# Wait for all child processes to terminate
wait
echo "All child ssh done!"
用带数量参数的内联shell脚本替换动态HereDocument的另一种方法是:
#!/usr/bin/env sh
while IFS=$' tnr' read -r ip quantity || [ -n "$quantity" ]; do
echo ssh "root@$ip" sh -c '
if cd test/libhotstuff
then
i=0
while [ $i -lt "$1" ]; do
./examples/hotstuff-app --conf "./hotstuff.gen-sec$i.conf" >"log$i" 2>&1 &
i=$((i + 1))
done
wait
fi
' _ "$quantity" &
done <ips
# Wait for all child processes to terminate
wait
echo "All child ssh done!"