Bash: как продолжить цикл, если условие X выполнено

Я пытаюсь запустить процесс на нескольких виртуальных машинах, используя действия 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. Это просто существующая программа, которую мне нужно запустить, а не то, что я могу изменить самостоятельно.

Ваш пример тайм-аута такой же, как и предыдущий пример.

Robin Hellmers 08.07.2024 11:29

хороший момент, я это исправил

Tijmen 08.07.2024 11:30

Я бы обработал команду ssh в фоновом режиме, а затем запустил цикл for, который проверяет журналы. Но тогда у вас будут постоянно работать все процессы ssh, но, насколько я понимаю, это то, что вам нужно, даже если «часть настройки» завершена.

Robin Hellmers 08.07.2024 11:34

Если я правильно вас понял, проблема в том, что моя программа работает вечно, а вы хотите прервать ее, как только будет выполнено определенное условие. Конечно, было бы лучше изменить мою программу так, чтобы она завершалась сама по себе в случае возникновения условия, но если вы не можете этого сделать, я предлагаю вам написать программу-обертку вокруг моей программы, которая отслеживает мою программу и убивает ее после выполнения условия. имеет место. Тогда вам просто нужно запустить вашу обертку вместо моей программы.

user1934428 08.07.2024 13:03

@user1934428 user1934428 Я не пытаюсь завершить сам процесс myprogram, а оставляю его работающим и заставляю цикл for, вызвавший его, продолжить работу до следующей виртуальной машины. Ответ Робина ниже — элегантный способ сделать это, но, тем не менее, спасибо за ваш вклад.

Tijmen 08.07.2024 13:14

В этом случае ваша программа-оболочка должна запустить мою программу в фоновом режиме (и использовать nohup, чтобы она не была уничтожена). Если оболочка завершает работу (после того, как она обнаружила условие), ваш ssh завершится, и цикл продолжится.

user1934428 08.07.2024 13:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Другие вопросы по теме