我正在尝试使用 GitHub Actions 在多个虚拟机上启动一个进程。但是,该命令未完成(因为它需要继续运行),因此我的 for 循环有点挂起。
我需要的是一种检查命令的日志输出(位于已知文件中)的方法,然后每当日志文件中出现特定句子时继续循环。
这是我目前拥有的一个最小示例:
#! /bin/bash
VMS=("10.10.789.001" "10.10.789.002" "10.10.789.003")
for VM in "${!VMS[@]}"; do
command.sh "$VM"
done
命令.sh:
#! /bin/bash
vmip=$1
ssh user@"$vmip" -T "myprogram -flag &> output.log"
这在某种意义上是有效的,即建立连接,启动
myprogram
并将其输出重定向到output.log
。但是,由于 myprogram
继续运行(按预期),因此 for
循环永远不会到达 done
。
我尝试过像这样设置
timeout
:
#! /bin/bash
VMS=("10.10.789.001" "10.10.789.002" "10.10.789.003")
for VM in "${!VMS[@]}"; do
timeout 5m command.sh "$VM"
done
然而,这结束了整个脚本,因为它在达到超时后有效地抛出了
exit
,并且仍然不会继续 for
循环。
我知道
myprogram
会将 setup complete
写入 output.log
文件,因此我可以通过执行以下操作来检查:
#! /bin/bash
cat vault.log | grep "setup complete"
if [ $? = 0 ]; then
<do something>
fi
如果满足上述条件,则程序已完成设置,现在正在运行,这就是我想要的。但是,我不知道
<do something>
部分需要做什么,以确保原始 for
循环能够继续。
注意我无权访问
myprogram
程序的内容。这只是我需要运行的现有程序,而不是我自己可以改变的东西。
后台处理启动
ssh
的每个 myprogram
命令。然后执行某种循环来检查日志。
命令.sh:
#! /bin/bash
main()
{
local ip="$1"
# Run the program in the background and redirect output to the log file
ssh user@"$ip" -T "myprogram -flag &> output.log" &
local ssh_pid=$!
local max_iterations=100
local iter_sleep_seconds=2
# Wait until the setup complete message appears in the log file
for ((i=1; i<=max_iterations; i++))
do
if ssh user@"$ip" -T "grep 'setup complete' output.log"
then
echo "Setup complete on $ip."
break
else
echo "Waiting for setup to complete on $ip..."
sleep $iter_sleep_seconds
fi
done
if (( i > max_iterations ))
then
echo "Maximum number of iterations reached for $ip. Killing the instance."
kill $ssh_pid
return 1
fi
return 0
}
main "$@"
后台处理
command.sh
的每次调用
main.sh:
VMS=("10.10.789.001" "10.10.789.002" "10.10.789.003")
for VM in "${VMS[@]}"
do
./command.sh "$VM" &
done
wait
echo "All VM processes are done. Check log above if successful."