Как bash относится к «>> ()»

9

Экспериментируя с перенаправлением вывода и подстановкой процесса, я наткнулся на следующую команду и ее вывод:

    me @ elem: ~ $ echo foo>> (кошка); эхо-бар
    бар
    me @ elem: ~ $ foo

(Да, этот пустой символ новой строки в конце является преднамеренным.)

Итак, bash echo's bar, печатает мою обычную подсказку, echo foo, echo - новую строку и оставляет мой курсор там. Если я нажму клавишу ввода еще раз, он выведет мою подсказку в новой строке и оставит после нее курсор (как и ожидалось, когда кто-нибудь нажмет клавишу ввода в пустой командной строке).

Я ожидал, что он напишет foo в файловый дескриптор, cat прочитает его и echo's foo, панель второго echo echo, а затем вернется в командную строку. Но это явно не тот случай.

Может кто-нибудь объяснить, пожалуйста, что происходит?

Стэнли Ю.
источник
Я хотел бы предложить посмотреть ответы на этот вопрос: unix.stackexchange.com/questions/182800/… Это объясняет двойное перенаправление и объяснит, почему вы заканчиваете с разными результатами. И Муру, и Майкл Хормерс.
Нет времени
Для вопроса, явно касающегося того, почему вывод подстановки процесса появляется после подсказки (а в некоторых случаях вообще не появляется) в некоторых версиях оболочки Bourne Again, см. Unix.stackexchange.com/questions/471987 .
JdeBP

Ответы:

9

Может fooотображаться до bar, после barили даже после запроса, в зависимости от времени. Добавьте небольшую задержку, чтобы получить согласованное время:

$ echo foo > >(sleep 1; cat); echo bar; sleep 2 
bar
foo
$

barпоявляется сразу же, затем fooчерез одну секунду, затем следующая подсказка через следующую секунду.

Происходит то, что bash выполняет подстановки процессов в фоновом режиме.

  1. Основной процесс bash запускает выполнение подоболочки sleep 1; catи устанавливает для нее канал.
  2. Основной процесс bash выполняется echo foo. Так как это не заполняет буфер канала, echoкоманда завершается без блокировки.
  3. Основной процесс bash выполняется echo bar.
  4. Основной процесс bash запускает команду sleep 2.
  5. Тем временем подоболочка запускает команду sleep 1.
  6. Примерно через 1 секунду sleep 1возвращается в подпроцесс. Подпроцесс продолжает выполняться cat.
  7. cat копирует свой ввод в свой вывод (который отображается на экране) и возвращает.
  8. Подоболочка закончила свою работу, она выходит.
  9. Еще через секунду sleep 2возвращается. Основной процесс оболочки завершает выполнение, и вы видите следующее приглашение.
Жиль "ТАК - прекрати быть злым"
источник
3

Вам не нужна замена процесса, чтобы получить этот эффект. Попробуй это:

( echo foo | cat & )

Вы получите почти такой же результат (без bar; я оставлю это как упражнение) и по той же причине. В обоих случаях catзапускается как фоновая задача. В моей строке это явно. В случае замены процесса это также явно - это отдельный процесс, связанный с дескриптором файла имени, - но, возможно, это не так очевидно.

Дочерний процесс не обязательно завершается, прежде чем bashпечатать следующее приглашение. И так как его вывод буферизован, он ничего не выводит, пока не завершится. В этот момент bash только что напечатал $на stderr, и теперь фоновый процесс завершается после печати fooи новой строки.

RICi
источник