Запись в стандартный фоновый процесс
Я на Ubuntu 10.04 box и запустил сервер в фоновом режиме (myserver &) поверх ssh. Он работает нормально, но мне нужен способ получить доступ к стандартному серверу, так как единственный способ управлять сервером - это использовать этот метод.
Есть ли какой-нибудь способ добраться до stdin уже запущенного процесса, чтобы я мог написать ему (и, надеюсь, прочитать его stdout)? Очевидно, что если бы я собирался делать это сейчас, я бы начал с FIFO, перенаправляющего на stdin, но, к сожалению, сейчас уже немного поздно.
Есть идеи?
4 ответа
Вы можете запустить свой сервер с именованным каналом (fifo) в качестве ввода:
mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
cat /tmp/srv-input | myserver &
cat > /tmp/srv-input &
Важно, чтобы ваш сервер не получал EOF. По крайней мере один процесс должен иметь открытую записку fifo, чтобы ваш сервер не получал EOF. PID этой команды сохраняется в /tmp/srv-input-cat-pid
файл для последнего убийства.
В вашем случае, когда вы уже запустили свой сервер, вы должны использовать отладчик, такой как gdb
прикрепить к вашему процессу, чтобы перенаправить его stdin
до пятерки:
gdb -p PID
call close(0)
call open(0, "/tmp/srv-input", 0600)
А затем сделайте что-то вроде ниже, чтобы отправить входные данные на ваш сервер (в другом окне терминала, если необходимо):
echo "command" > /tmp/srv-input
Чтобы отправить EOF на ваш сервер, вам нужно убить cat > /tmp/srv-input
процесс, который PID был сохранен в /tmp/srv-input-cat-pid file
,
В случае GDB просто выйдите из GDB, и EOF будет отправлен.
Вы можете попробовать записать в каталог /proc pid. Скажите, что pid вашего демона 2000, попробуйте написать в /proc/2000/fd/0
То же, что и выше, но "кошка" не работает для меня. Файл получил EOF и закончился после отправки одной команды.
Это сработало для меня:
#!/bin/bash
mkfifo /tmp/srv-input
tail -f /tmp/srv-input | myserver &
Существует более элегантное решение, которое решает проблемы сtail -f
и
Создайте именованный канал для маршрутизации STDIN:
mkfifo /data/in
.Заблокируйте его для записи, чтобы он не закрывался, когда ваш процесс прочитает все текущее содержимое:
sleep infinity > /data/in &
.
Спать вечно лучше, чемtailf -f /dev/null
потому что Tailf использует ресурсы inotify и будет запускаться каждый раз, когда какое-либо приложение отправляет данные в /dev/null. Вы можете увидеть это, запустивstrace
в теме. Это также лучше, чемcat > /dev/null &
потому чтоcat
сам будет отключен от STDIN, который, в свою очередь, закроется.
- Запустите свой процесс в фоновом режиме с помощью
/data/in
предоставление STDIN:application < /data/in &
.
Это работает лучше, чем использование трубопровода из хвоста.tail -f /data/in | application &
потому что канал будет завершен только в том случае, если хвост остановится, но если ваше приложение выйдет из строя, канал продолжит работать.
- Остановите ожидание завершения работы приложения.
wait $(pidof application)
.
При этом не используются ресурсы, и если приложение приводит к сбою вашего сценария послеwait
будет казнен. При желании вы можете добавить вокруг него цикл перезапуска приложения.
- Чтобы завершить работу приложения, корректно перехватывать и передавать ему системные сигналы с помощью
trap 'kill -SIGTERM $(pidof app)' SIGTERM