Каждый процесс в системах 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 будет закрыт.