Потоки против прерываний

Каждый процесс в системах Linux по умолчанию имеет один вход (stdin) и два выхода (stdout, stderr). Терминалы принимают ввод с клавиатуры и отправляют его на stdin оболочки, которую они запускают, а также принимают stdout и stderr от процесса и печатают их на экран.

Когда вы запускаете команду в оболочке (в терминале), она связывает свой собственный stdin с stdin процесса, поэтому все набранные вами клавиши передаются команде. Он также связывает их stdout и stderr со своими собственными (которые терминал затем печатает на экран). То же самое происходит, когда вы выполняете команду внутри сценария, stdin, stdout и stderr связаны с родительским процессом, и в конечном итоге они распространяются на терминал.

Кроме того, команды в сценариях по умолчанию блокируются. Они будут выполнять следующую команду только после завершения выполнения той, которую они выполняют.

Учитывая это, давайте рассмотрим ваш скрипт (упрощая до двух интересующих нас строк):

sh script2.sh
echo ".open Simulation\n"

Что это делает, так это запускает sh (который запускает script2.sh), присоединяет свой stdin к stdin скрипта и блокирует, ожидая его завершения. Вторая строка не будет выполняться, пока не завершится первый процесс.

Теперь, все, что вы набираете в оболочке, например .open Simulation\n, будет отправлено в sh, который отправит это в ваш script2.sh. Как только (если вообще) ваш script2.sh завершит работу, он выйдет, а ваш основной скрипт передаст .open Simulation\n в shell и выйдет.

Теперь мы знаем, что происходит. Как мы можем это исправить? Вы можете отменить стандартное прикрепление stdin, stdout и stderr куда угодно, включая файлы или другие процессы. Для этого в оболочке есть мощные утилиты, перенаправление ввода/вывода и командные каналы.

Перенаправления ввода/вывода позволяют вам перенаправить ввод/вывод в любой файл, например:

echo "contents of a file" > somefile.txt

Это запишет содержимое файла в somefile.txt, перенаправив stdout команды echo в somefile.txt. Перенаправление ввода работает аналогично:

cat < somefile.txt

Выведет содержимое файла на экран, перенаправив cats stdin на чтение из somefile.txt (обратите внимание, что это надуманный пример, большинство людей просто cat somefile. txt, что заставляет cat читать somefile.txt самостоятельно, а не заставлять shell делать это.)

Далее идут командные трубы, они позволяют вам соединить stdout одной программы со stdin другой. Это похоже на то, что вы хотите, отправить вывод echo в stdin вашего скрипта:

echo ".open Simulation" | sh script2.sh

Теперь это хорошо работает для простого ввода, но если у вас больше пары строк, есть более простой способ; Heredocs. Например, чтобы передать несколько строк в ваш скрипт, вы можете

sh script2.sh <<EOD
.open Simulation
.do something
.end Simulation
EOD

Что отправит три строки (не включая EOD) в ваш скрипт, готовые для обработки вашим скриптом. Если вам нужно сделать что-то более сложное, вы можете использовать перенаправление подкоманд, что позволит вам перенаправить вывод подпрограммы в вашу программу, здесь с sleep 1 между каждой строкой:

sh script2.sh <(
    echo ".open Simulation"
    sleep 1
    echo ".do something"
    sleep 1
    echo ".end Simulation"
)

В этом примере ваш скрипт сразу увидит .open Simulation, затем через секунду он получит .do something, затем еще через секунду .end Simulation, прежде чем stdin будет закрыт.

1
29.07.2015, 07:17
0 ответов

Теги

Похожие вопросы