Вопрос или проблема
Относительно команды cmd1.sh | grep "message"
, в которой cmd1.sh выглядит следующим образом:
#!/bin/bash
echo "message from foreground father process"
setsid sleep 100 &
echo "foreground father process quits"
- cmd1.sh выводит сообщение
- запускает фоновый подпроцесс
- затем снова заканчивается сообщением
- завершается, оставляя фоновый подпроцесс
sleep 100
активным
Вы обнаружите, что cmd1.sh
работает хорошо, но cmd1.sh | grep "message"
зависает, и я понимаю, что это происходит потому, что подпроцесс подключается к каналу.
Так что может ли кто-нибудь из экспертов предложить решение, чтобы выйти из cmd1.sh | grep "message"
, не изменяя cmd1.sh?
(На самом деле моя конкретная проблема связана с pg_ctl restart | grep "blabla"
, где pg_ctl — это бинарный файл, запускающий postgres)
Ответ или решение
Чтобы решить проблему, связанную с командой cmd1.sh | grep "message"
, и избежать блокировки выполнения, представляю вам подробное описание процесса и решение. Ваша цель — выполнить пайплайн, при этом оставив фоновый процесс, запущенный командой cmd1.sh
, работающим.
Исходная проблема
Скрипт cmd1.sh
выполняет следующие действия:
- Выводит сообщение в консоль.
- Запускает фоновый процесс
sleep 100
черезsetsid
, что изолирует его в отдельной сессии. - Завершает выполнение с выводом финального сообщения.
При запуске cmd1.sh
напрямую, всё работает корректно, и фоновый процесс остается активным. Однако выполнение через пайплайн cmd1.sh | grep "message"
вызывает зависание, поскольку поток вывода пайплайна взаимодействует с дочерними процессами.
Корень проблемы
Проблема заключается в унаследованной связи стандартных потоков между командой grep
и фоновым процессом, который создается скриптом cmd1.sh
. Пайплайн создает блокировку, поскольку grep
продолжает ожидать ввода данных до завершения всех задействованных процессов.
Решение задачи
Для решения данной проблемы, не изменяя содержимое cmd1.sh
, можно воспользоваться следующим подходом:
-
Изолировать процесс
cmd1.sh
от пайплайна: Используйте командуstdbuf
или подобные методы для управления буферизацией ввода-вывода. Это позволит избежать блокировки. -
Использовать конструкцию
nohup
, для того чтобы фоновый процесс продолжал свою работу после завершения всех стандартных потоков.
Пример решения выглядит следующим образом:
( cmd1.sh & echo "Process launched" ) | stdbuf -o0 grep "message"
Детали решения
-
Подчеркивание независимости: Оболочка запускает
cmd1.sh
в фоновом режиме, аecho "Process launched"
позволяет ‘освободить’ пайплайн, завершая передачу данных в стандартный вывод и предоставляяgrep
конкретный набор данных для обработки. -
Использование
stdbuf
: Укомплектовывает буферизацию, предотвращая лишнее накапливание данных в стеке.
Эта довольно простая инженерная комбинация позволяет обойти проблему блокировки, давая возможность успешно интерпретировать команды в пайплайне, и при этом фоновый процесс, запущенный cmd1.sh
, продолжает функционировать без влияния на общий поток выполнения.
Поэтому, вредные навязчивые состояния процесса и блокировки будут эффективно устранены данным подходом.