Вопрос или проблема
У меня есть программа, работающая под управлением сервиса systemd, и я хотел бы передать ей текст/команды, поэтому я попробовал сделать это с помощью FIFO файла:
файл .service
[Unit]
Description=Служба сервера Minecraft!
[Service]
EnvironmentFile=/etc/systemd/system/minecraft.env
WorkingDirectory=/srv/http/mc/mcserver/
ExecStart=/srv/http/mc/mcserver/start < /srv/http/mc/mcserver/minecraft_input
StandardOutput=append:/srv/http/mc/mcserver/mcserver.log
[Install]
WantedBy=multi-user.target
файл .socket
[Socket]
ListenFIFO=/srv/http/mc/mcserver/minecraft_input
Service=minecraft.service
[Install]
WantedBy=sockets.target
Но когда я пытаюсь записать в файл (либо с помощью echo 'stop (или что-то другое)' > minecraft_input
, либо echo 'stop (или что-то другое)' | tee minecraft_input
), он просто зависает без вывода, и ничего не передается. (FIFO файл создан с использованием mkfifo и имеет права 664)
Есть несколько возможных проблем. Во-первых, давайте исключим systemd
как фактор. Что происходит, если вы просто запустите свою службу вручную?
В одной командной строке/окне выполните
/srv/http/mc/mcserver/start < /srv/http/mc/mcserver/minecraft_input
Затем в другом окне выполните ваши команды echo
. Работает ли это, как ожидалось? Мой предположение — нет.
Существует как минимум две другие потенциальные проблемы. Во-первых, когда команда echo stop > minecraft_input
завершает работу, это вызовет отправку EOF через FIFO в команду start
. Это приведет к закрытию стандартного ввода команды start
, что мешает ей получать больше команд. Стандартный ввод нельзя повторно открыть, пока вся служба не завершит работу и не будет перезапущена systemd
.
Вы можете обойти это, используя tail -F
для чтения из FIFO, повторно открывая его всякий раз, когда он закрывается, вот так:
tail -F /srv/http/mc/mcserver/minecraft_input | \
/srv/http/mc/mcserver/start
Другая проблема может быть в том, что команды, которые вы отправляете, слишком короткие и задерживаются в буфере. Вы можете отключить буферизацию, дополнительно изменив вашу командную строку сервера на такую:
stdbuf -o 0 tail -f /srv/http/mc/mcserver/minecraft_input | \
/srv/http/mc/mcserver/start
Это изменяет стандартный вывод из tail
в режим без буферизации. С этим изменением вы должны иметь возможность успешно передавать короткие команды в ваш процесс start
через FIFO.
stdbuf
не является утилитой POSIX стандартов, и, возможно, по умолчанию ее нет в вашей системе. Вы обычно можете найти ее в пакете с названием что-то вроде GNU Tools.
Ответ или решение
Проблема: зависание терминала при записи в FIFO файл
Обзор проблемы
Вы столкнулись с проблемой, когда ваш сервис Minecraft, запущенный через systemd, зависает при попытке передачи команд через FIFO файл. Эта проблема может быть связана с особенностями работы FIFO, а также с тем, как ваша служебная программа обрабатывает стандартный ввод. Давайте подробнее рассмотрим возможные причины и решения.
Сначала проведем диагностику
Для начала, рекомендуется исключить ошибки, связанные с systemd. Попробуйте запустить вашу программу вручную, чтобы проверить, как она реагирует на команды.
/srv/http/mc/mcserver/start < /srv/http/mc/mcserver/minecraft_input
В другом терминале выполните команду:
echo 'stop' > /srv/http/mc/mcserver/minecraft_input
Если при этом ничего не происходит, продолжим исследовать причины.
Возможные причины зависания
-
Закрытие стандартного ввода
При выполнении командыecho
в FIFO, после завершения этой команды будет отправлен сигнал EOF (конец файла) в стандартный ввод вашей программы. Это приведет к закрытию стандартного ввода, и вы не сможете отправлять другие команды, пока сервис не будет перезапущен.Решение: Вместо прямого чтения из FIFO, вы можете использовать
tail -F
, который будет отслеживать FIFO и восстанавливать соединение в случае его закрытия:tail -F /srv/http/mc/mcserver/minecraft_input | /srv/http/mc/mcserver/start
-
Буферизация данных
Командаecho
или другие короткие команды могут задерживаться в буфере перед отправкой. Это связано с тем, что стандартный ввод может быть буферизован.Решение: Используйте утилиту
stdbuf
, чтобы отключить буферизацию:stdbuf -o 0 tail -f /srv/http/mc/mcserver/minecraft_input | /srv/http/mc/mcserver/start
Это позволит обеспечить немедленную передачу команд, и ваша программа сможет обрабатывать их сразу же.
Установка stdug – buf
Стоит упомянуть, что stdbuf
не является стандартной утилитой POSIX и может отсутствовать на вашей системе. Обычно она доступна в пакетах GNU. Проверьте наличие и установите её, если это необходимо.
Заключение
Работа с FIFO файлами требует внимательного подхода к обработке ввода и вывода. Использование tail -F
в сочетании с stdbuf
может значительно повысить стабильность и эффективность вашего сервиса Minecraft, устраняя зависания терминала. Если у вас есть дополнительные вопросы или требуется помощь в настройке, не стесняйтесь обращаться за поддержкой.