Как сделать сценарий оболочки, который отправляет вывод в процесс

11

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

Я хотел бы запустить приложение в качестве демона в фоновом режиме (запустить / остановить его с помощью init).

Я мог tail -fбы записать в журнал, но это не позволит мне отправить входные данные в процесс.

Есть ли способ настроить это так, чтобы я мог как читать, так и отправлять ввод, но он все еще работает в фоновом режиме?

Я также хотел бы иметь возможность отправлять входные данные демону из разных процессов (например, сценарий оболочки, который может отправлять команду «Stop \ n»).

Билл К
источник
Просто комментарий любому, кто придет, чтобы прочитать это - ответ здесь фантастический. Если вы не знаете о именованных каналах, я настоятельно рекомендую вам хотя бы попробовать. Используя это, я мог запускать Minecraft как сервис и взаимодействовать с консолью из других сценариев, записывая в именованный канал - так что стало возможным писать сценарии для остановки сервера, отправлять сообщения пользователям и т. Д., Все еще анализируя выходной журнал искать ключевые строки (например, отправлять сообщения чата на имя пользователя в виде текстов)
Bill K

Ответы:

9

Читай из трубы, пиши в файл

Если вы хотите, чтобы демон считывал ввод, произведенный каким-либо произвольным процессом, вам необходимо подключить этот процесс к каналу. Здесь произвольный процесс заключается в том, что вы повторяете команды, и он будет выполняться в другом контексте. Поэтому создайте именованный канал (часто называемый fifo в контексте unix).

mkfifo /var/run/daemon.fifo
</var/run/daemon.fifo /path/to/daemond --option >daemon.log

И просто напишите команды в канал:

echo 'FORWARD 10' >/var/run/daemon.fifo
echo 'LEFT 72' >/var/run/daemon.fifo

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

</var/run/daemon.fifo tail -c +1 -f | {
  echo $$ >/var/run/daemon.pid
  exec /path/to/daemond --option >daemon.log
}

В некоторых tailреализациях вы можете быть укушены буферизацией: tailпроцесс будет ждать, пока не соберет достаточно байтов для вывода некоторого результата. Я не думаю, что это разрешимо в наборе инструментов POSIX; если это проблема, используйте тривиальную программу на C, Perl или Python. Насколько я могу судить, tailGNU coreutils (как в Linux и других местах) безопасен в этом отношении.

Когда вы остановите демон, echo >/var/run/daemon.fifoубьете tailпроцесс.


Запуск программы внутри экрана

Вместо того, чтобы вызывать демон прямо из вашего менеджера сервисов (вы действительно используете только SysV init или что-то дополнительное, например сценарии-обертки или Upstart?), Вызывайте

screen -c daemon.screenrc -L -d -m -S daemon_name /path/to/daemond --option

Поскольку демон не будет дочерним процессом диспетчера служб, необходимо обязательно отправить сигнал нужному процессу. Как это сделать, зависит от того, как именно запускается демон и чем.

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

-LОпция делает экран записи все , что появляется в окне в файл. Имя файла задается в daemon.screenrcс logfileдирективой.

Жиль "ТАК - прекрати быть злым"
источник
На самом деле, я бы очень хотел иметь возможность отправлять на него стандартные сообщения из скрипта - возможно, это вопрос, который я должен был задать. В настоящее время я просто запускаю сервер из сценария и могу набирать его в терминале, но кажется, что он должен работать как служба ...
Билл К
@ Билл: Хорошо, я вижу. Тогда первое, что приходит мне в голову, это именованная труба.
Жиль "ТАК - перестань быть злым"
Я думаю, что это именно то, что я хочу, @Gilles! Мне нужно понять это лучше, хотя. Я проведу некоторое время, разбирая справочные страницы, чтобы понять это - я, честно говоря, получаю очень мало от этого (я получаю большую часть того, что вы делаете, и почти ничего от того, как вы это делали - и я думал, что у меня вроде разгадать эту штуку.) Моя теория заключалась не в том, чтобы напрямую подключаться к процессу, а в том, чтобы создать еще один скрипт, который соединял бы его ввод-вывод с демонами-демонами, чтобы казалось, что оригинальная консоль работает, но с возможностью сделать эхо 'FORWARD 10' из другого скрипта в то же время.
Билл К
Я думаю, что я многое понимаю. Если я разобью его, я теперь пойму "труба mkfifo" и "tail -f pipe | command> output", проверил их и они работают. Я думаю, что большинство других ваших вещей были уловки, чтобы заставить его работать на одной строке - я что-то упустил?
Билл К
@Bill: Вы можете написать на терминал внутри экрана снаружи (используя stuffкоманду экрана ). Но вам не нужны служебные данные (обработка, но, что наиболее важно, когнитивное) терминала здесь, канала почти достаточно (этого достаточно с небольшим процессом ретрансляции, игнорирующим конец файла). Возможно, вы захотите немного поэкспериментировать с <fifo catили <fifo tail -f | catв одном терминале и echo >fifo; echo >fifoв другом терминале; Я думаю, у тебя все будет хорошо.
Жиль "ТАК - перестань быть злым"