В
cmd1 | cmd2
cmd1
и cmd2
запускаются параллельно с stdout cmd1
подключенным к записывающему концу канала (или пары сокетов в ksh93 ), а stdin cmd2
подключен к другому концу ту трубу.
В:
cmd < file
cmd
запускается с cmd
stdin, открытым на file
.
Итак, вы видите, что
cmd1 | cmd2 < file
конфликты; вам нужно выбрать, является ли stdin cmd2
каналом из cmd1
или file
.
В приведенном выше примере в большинстве оболочек <file
имеет приоритет, так как перенаправление выполняется после(оболочка запускает 2 процесса с каналом в -между ними, и , затем интерпретирует каждую из команд, включая перенаправления внутри каждой независимо)
Это означает, что стандартный ввод cmd2
будет file
, а канал echo
, в который выполняется запись, не будет иметь читателя (сломанного канала ). Таким образом, в вашем случае bar
никогда не доберется до nc
, а процесс, выполняющий echo bar
, может даже быть убит, если он напишет bar
после того, как другой процесс открыл файл.
Однако в zsh
с опцией multios
в (и включенной по умолчанию )zsh
обнаруживает, что вы пытаетесь перенаправить тот же файловый дескриптор (сюда 0, stdin )дважды и принимает то, что вы имели в виду, чтобы данные из обоих этих источников были отправлены в cmd2
, поэтому вместо того, чтобы делать cmd2
stdin каналом из cmd1
или file
, он фактически запустить внутренний фидерный процесс , который считывает данные из обоих источников и отправляет их (один за другим через другой канал )в cmd2
.
cmd1 < <(cmd2)
— это просто случай cmd1 < file
, где file
— это именованный канал (или что-то, что ведет себя как именованный канал )с записью cmd2
на другом конце, но в остальном не сильно отличается.
Переносимо, если вы хотите отправить вывод двух команд,или отправить вывод команды и содержимое файла какой-либо команде, вы должны использовать:
{
cmd1
cmd2
} | cmd3
Или:
{
cmd1
cat < file
} | cmd2
Так вот:
{
echo bar
echo foo
} | nc localhost 6969
Программы, которые полагаются на ввод, как вы описали, должны запускаться внутри терминального мультиплексора, такого какtmux
(https://en.wikipedia.org/wiki/Tmux)или screen
(https://www.gnu.org/software/screen/). Думайте об этом как о текстовой -версии окна терминала.
Используйте screen my-program
для запуска my-program
. Затем вы можете отсоединить от консоли виртуального экрана, используя комбинацию клавиш -штрихов Ctrl-ACtrl-D , и вы вернетесь к оболочки, с которой вы начали, но ваша программа продолжает работать в фоновом режиме. Затем с помощью screen -r
вы можете повторно подключиться к виртуальной консоли.
(, и ваша программа )будет продолжать работать до тех пор, пока вы не завершите работу программы или сервер не будет перезагружен.
tmux
очень похож, но имеет больше параметров и функций и использует другие сочетания клавиш.
Чтобы скрипт продолжал работать в фоновом режиме, используйте nohup:nohup scriptcommand &
. В идеале сценарий должен иметь возможность не запрашивать ввод. Если по какой-то причине это невозможно, можно использовать Expect для ввода 'y'.
Создание службы systemd для скрипта позволит запускать скрипт при перезагрузке системы. Вы также можете использовать Restart=always
в вашем файле systemd для перезапуска службы, если служба была закрыта или убита, документация systemd содержит дополнительную информацию .