Я пытаюсь запустить процесс на нескольких виртуальных машинах, используя действия GitHub. Однако команда не завершается (поскольку она должна продолжать работу), поэтому мой цикл 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 в фоновом режиме, а затем запустил цикл for, который проверяет журналы. Но тогда у вас будут постоянно работать все процессы ssh, но, насколько я понимаю, это то, что вам нужно, даже если «часть настройки» завершена.
Если я правильно вас понял, проблема в том, что моя программа работает вечно, а вы хотите прервать ее, как только будет выполнено определенное условие. Конечно, было бы лучше изменить мою программу так, чтобы она завершалась сама по себе в случае возникновения условия, но если вы не можете этого сделать, я предлагаю вам написать программу-обертку вокруг моей программы, которая отслеживает мою программу и убивает ее после выполнения условия. имеет место. Тогда вам просто нужно запустить вашу обертку вместо моей программы.
@user1934428 user1934428 Я не пытаюсь завершить сам процесс myprogram, а оставляю его работающим и заставляю цикл for, вызвавший его, продолжить работу до следующей виртуальной машины. Ответ Робина ниже — элегантный способ сделать это, но, тем не менее, спасибо за ваш вклад.
В этом случае ваша программа-оболочка должна запустить мою программу в фоновом режиме (и использовать nohup, чтобы она не была уничтожена). Если оболочка завершает работу (после того, как она обнаружила условие), ваш ssh завершится, и цикл продолжится.





Фоновая обработка каждой запускаемой 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
основной.ш:
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."
Ваш пример тайм-аута такой же, как и предыдущий пример.