Возможно, это относится к категории "обходной путь", но мне удалось достичь того, что я думаю, ваша цель - ввести команду ("python dostuff.py "из вашего примера) в сценарий оболочки, затем запустив ... screen -d -m" / path / to / that / script "
Информация о версии:
$ screen -v
Screen version 3.09.10 (FAU) 4-Sep-01
Похоже, у меня довольно старая версия экрана в этой системе! Возможно, поведение экрана изменилось в более поздних версиях для автоматического выхода?
$ screen -ls
No Sockets found in /tmp/uscreens/S-username.
$ screen -dm "ls"
$ screen -ls
There is a screen on:
32112694.ls (Detached)
1 Socket in /tmp/uscreens/S-username.
(screen -r; exit)
$ screen -ls
No Sockets found in /tmp/uscreens/S-username.
$ cat runme
#!/bin/sh
sleep 6
ls > now
$ screen -d -m ./runme
$ ps -ef|grep sleep
username 9633926 9437204 0 14:55:23 pts/1 0:00 grep sleep
username 15532242 10223670 0 14:55:21 pts/6 0:00 sleep 6
(подождите 6 секунд)
$ screen -ls
No Sockets found in /tmp/uscreens/S-username.
$ ls now
now
Одна вещь, которую я понял, проходя через это, заключается в том, что моя версия screen, похоже, ожидала имя сеанса после -dm
; Мне пришлось разделить -d
и -m
, чтобы передать аргумент команды.
Попробуйте использовать:
ssh user@host screen -d -m python dostuff.py
с необязательным -S
, чтобы присвоить сеансу какое-то конкретное имя.
Чтобы cat
не зависал при отсутствии какой-либо записи, (в этом случае зависает именно открытие fifo, а не чтение из него ), можно сделать:
cat 0<> "$my_named_pipe" <"$my_named_pipe"
Первое перенаправление открывается в режиме чтения+записи, который в большинстве систем не блокирует и создает экземпляр канала, даже если ни писатель, ни читатель уже отсутствуют. Затем второе открытое (чтение -только на этот раз )не будет блокироваться, потому что теперь есть по крайней мере один писатель (сам ).
0
требуется только в последних версиях ksh93, где значение fd по умолчанию для <>
изменено с 0 на 1.
Кроме того, в ksh93
это не будет работать, когда cat
является встроенной оболочкой, например, когда ksh93
вызывается, когда /opt/ast/bin
опережает /bin
в $PATH
или после вызова builtin cat
, как и <"$my_named_pipe"
, (, я думаю, )ksh93 сохраняет предыдущую цель стандартного ввода в отдельном дескрипторе файла, который будет держать канал открытым.Вы можете обойти это, написав вместо этого:
cat 3<> "$my_named_pipe" <"$my_named_pipe" 3<&-
(что, как вы могли бы также утверждать, более четко передает намерение)
Обратите внимание, что <>
в канале также разблокирует другие считыватели для доступа к fifo.
Если бы были некоторые писатели, cat
все равно пришлось бы читать весь их вывод и ждать, пока они не закроют свой конец канала. Вы можете открыть канал в неблокирующем режиме -, например, в GNU dd
:
dd bs=64k if="$my_named_pipe" iflag=nonblock status=noxfer
Который будет читать из канала только до тех пор, пока в нем есть какие-то данные, и выходить с
dd: error reading 'fifo': Resource temporarily unavailable
ошибка, когда больше нет, и не разблокировать других читателей, но это означает, что вы можете пропустить вывод некоторых модулей записи, если они медленнее записывают в канал, чем вы(dd
)читаете его.
Другим подходом может быть тайм-аут, когда в течение некоторого времени не было ввода, например, с помощью socat
опции -T
:
socat -u -T1 - - 0<> "$my_named_pipe" <"$my_named_pipe"
Который вышел бы, если бы из трубы ничего не исходило в течение одной секунды.
Что-то довольно простое — завершить cat
сразу после чтения fifo, независимо от того, есть данные или нет. Вы можете сделать это с помощью timeout
следующим образом:
timeout 2 cat my_named_pipe
Выше timeout
ждет две секунды, прежде чем принудительно завершить работу cat. Если при запуске cat
в именованном канале есть что-то буферизованное, оно будет выведено на стандартный вывод.
Возможно, это не самое чистое решение, но оно работает.
Надеюсь, это поможет.