В (по крайней мере )системах на базе Linux -FIFO или Named Pipe являются однонаправленными. В вашей ситуации вы хотите, чтобы программа читала и писала в один и тот же FIFO. Это становится еще более сложным, потому что вы можете столкнуться с взаимоблокировкой, если превысите внутренний буфер канала.
Два общих момента.
Вы не можете с пользой иметь двух читателей; если вы это сделаете, вы обнаружите, что ваши чтения будут чередоваться недетерминировано, и ваши данные будут разделены между двумя читателями. Вы не получите дубликаты одних и тех же данных для обоих считывателей.
У вас может быть два (или более )модуля записи, но выходные данные снова будут чередоваться в том порядке, в котором они получены конвейером. Если ваши модули записи не будут тщательно синхронизированы, такие данные, как First writer
и Second writer
, могут быть получены как искаженные FirSecond wrstwrititerer
.
Используя программу в нижней части этого ответа, рассмотрите возможность запуска следующих двух сценариев из разных сеансов терминала. Тогда попробуйте свои варианты.
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh read ./fifo.sh read ./fifo.sh write /etc/hosts
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh write /etc/passwd ps -ef |./fifo.sh write ./fifo.sh read
First terminal Second terminal Third terminal
-------------------- -------------------- --------------------
./fifo.sh both /etc/passwd
Скрипт для fifo.sh
выглядит следующим образом
#!/bin/bash
#
pipe=/tmp/mypipe
########################################################################
# Reader
#
doRead()
{
echo "Reading from pipe $pipe" >&2
nl <"$pipe"
}
########################################################################
# Writer. We pause after every line (for effect)
#
doWrite()
{
[[ $# -eq 0 ]] && set -- -
echo "Writing to pipe $pipe" >&2
cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >>"$pipe"
}
########################################################################
# Reader-Writer. We pause after every line (for effect)
#
doBoth()
{
[[ $# -eq 0 ]] && set -- -
echo "Reading and writing to pipe $pipe" >&2
exec 3<>"$pipe"
nl <&3 & readPID=$!
cat "$@" | while IFS= read -r line; do printf "%s\n" "$line"; sleep 1; done >&3
kill $readPID 2>/dev/null
}
########################################################################
#
action="$1"
shift
if [[ ! -p "$pipe" ]]
then
echo "Creating pipe $pipe" >&2
mkfifo "$pipe"
fi
case "$action" in
read*) doRead "$@" ;;
write*) doWrite "$@" ;;
both) doBoth "$@" ;;
esac
Создание образа Docker и его запуск — это один из вариантов, как вы упомянули.
Однако более простым подходом к *nix-системам может быть использование супервизора для запуска службы. Не только python
, я запускал всевозможные скрипты perl
, shell
и ruby
под supervisord
. Я даже запускал приложения Flask под supervisord
без необходимости докеризации этих простых веб-сервисов.
На самом деле, в нескольких случаях, когда мне приходилось запускать несколько служб в док-контейнере для переноса устаревших приложений, я использовал супервизор в ENTRYPOINT, хотя это не рекомендуется и противоречит всей философии контейнеризации и облачных технологий, но мы должны делайте эти вещи иногда.
В Ubuntu вы можете установить supervisord
как
$ sudo apt install supervisor
, а затем включите службу супервизора как-
$ sudo systemctl enable supervisor
$ sudo systemctl start supervisor
Пример файла конфигурации может быть следующим:-
$ sudo vi /etc/supervisor/conf.d/service_name.conf
[program:service_name]
command=/usr/local/bin/python_script.py
directory=/home/app
user=app
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stdout_logfile = /var/log/supervisor/service_name.log
redirect_stderr = true
Автоматический перезапуск в конфигурации обеспечит перезапуск службы, если она по какой-либо причине завершится. Автозапуск гарантирует, что если вы перезагрузите систему, эта служба запустится, если у вас включен супервизор для запуска при загрузке системы.
Создав службу,вы можете запустить его как-
$ sudo supervisorctl start service_name
и вы можете проверить статус, когда захотите, как-
$ sudo supervisorctl stop service_name
Чтобы остановить службу, которую вы используете-
$ sudo supervisorctl stop service_name
Подробнее об этом можно прочитать здесь-http://supervisord.org/