Bash-скрипт, выполнять команду while, пока она не выводит значение.

Вопрос или проблема

Я пытаюсь написать bash-скрипт (совсем новичок в этом, кстати) на системе Linux, и я в основном хочу, чтобы он выполнял команду каждые 5 секунд, пока другая команда не выводит значение.

Итак, на данный момент у меня есть

xev | grep -A2 —line-buffered -E ‘ButtonRelease’ | grep -o ‘button 1’

что по сути выводит “button 1”, когда я кликаю по окну xev. Я хочу запускать отдельную команду каждые 5 секунд до тех пор, пока я не нажму на окно xev, после чего скрипт остановится.

Если ваша команда возвращается немедленно, тогда просто возьмите вашу команду и запишите вывод в переменную.

output=$(xev | grep -A2 —line-buffered -E ‘ButtonRelease’ | grep -o ‘button 1’)

Затем проверьте, пуста ли переменная, с помощью

[ -z «$output» ]

Вы можете вставить это в цикл while:

output=»»while [ -z «$output» ] ; do sleep 5 output=$(xev | grep -A2 -E ‘ButtonRelease’ | grep —line-buffered -o ‘button 1’)done


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

# Создайте временный файлoutput=$(mktemp)# Выполните свою команду# > «$output» отправит вывод этой команды в файл.# Символ & в конце — это «fork». Это означает, что мы продолжим выполнение скрипта # пока эта команда работает. Вам также нужна опция —line-buffered

# для всех вызовов

grepxev | grep -A2 —line-buffered -E ‘ButtonRelease’ | grep —line-buffered -o ‘button 1’ > «$output» &

# Сохраните идентификатор процесса разветвленного процесса

pid=$?

# Запустите цикл, пока файл/вывод не существует или его размер равен нулю,

# оставайтесь в цикле

while [ ! -s «$output» ] ; do echo «отдельная команда» sleep 5doneecho »

Мы что-то получили

«cat «$output»

# Если вам нужно завершить исходный процесс, сейчас подходящее время

kill $pid

# Не забудьте удалить файл

# ‘trap’ хорошо подходит для этогоrm «$output»

Ответ или решение

Для решения задачи по написанию Bash скрипта, который будет выполнять команду каждые 5 секунд, пока другая команда не выдаст значение, необходимо понять две ключевые идеи. Во-первых, это взаимодействие с командами, которые могут блокировать выполнение, и во-вторых, правильное управление выходными данными команды для определения, следует ли продолжать цикл или завершить его.

Теория

Основная идея — это создание цикла while, который будет проверять наличие выходных данных от команды. В примере рассматривается команда xev, которая взаимодействует с системой событий X Window в Linux. Поскольку ваша задача заключается в периодическом выполнении другой команды, пока клик по окну xev не произойдёт, необходимо корректно обрабатывать стандартный вывод этой команды.

Блокировка и линии буферизации: Основной вызов заключается в работе с командами, которые могут блокировать терминал или буферизовать выходные данные, что затрудняет точное определение момента, когда событие произошло. С использованием опции —line-buffered мы заставляем grep немедленно обрабатывать каждую линию данных.

Пример

Рассмотрим решения в двух подходах:

  1. Простейший случай (команда выполняется быстро):

    output=»»while [ -z «$output» ] ; do sleep 5 output=$(xev | grep -A2 —line-buffered -E ‘ButtonRelease’ | grep -o ‘button 1’)done

    Здесь скрипт будет каждые 5 секунд проверять, выдаёт ли команда xev какие-либо данные. Цикл завершится, как только найдётся фраза button 1.

  2. Когда процесс блокирует выполнение и требует родительского контроля:

    Для более сложного управления выполнением команд, когда xev может блокировать, используется временный файл для хранения выхода:

    # Создаём временный файлoutput=$(mktemp)# Запускаем команду в фоне и перенаправляем вывод в файлxev | grep -A2 —line-buffered -E ‘ButtonRelease’ | grep —line-buffered -o ‘button 1’ > «$output» &# Сохраняем PID запущенного процессаpid=$!# Запускаем цикл, пока файл пустwhile [ ! -s «$output» ] ; do echo «Выполнение команды вызывает выполнится каждые 5 секунд» sleep 5doneecho «Событие произошло.»cat «$output»# Завершаем процесс xevkill $pid# Удаляем временный файлrm «$output»

    В этом методе используется временный файл для промежуточного хранения результата команды. Это позволяет продолжать выполнение других частей сценария. PID процесса xev сохраняется для возможности его остановки, когда выполнение задачи завершено. Это особенно важно для освобождения системных ресурсов.

Применение

Эти методики применимы для автоматизации множества задач, которые требуют реакции на системные события или изменения в логах. Например, вы можете использовать подобный скрипт для мониторинга активности операционной системы или обработки событий в реальном времени. Расширение этих идей возможно для работы с многопоточными системами или для обработки более сложных условных проверок выходных данных.

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

Друзья помогите этому контенту стать доступнее в социальных сетях.

Не проходи мимо жмакни по кнопке возможно кому то еще он будет полезен!