Фоновые процессы смешивают порядок выполнения сценария оболочки

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

echo one && echo two & echo three && echo four 

дает мне

 [1] 3692 three four one two [1]+ Done echo one && echo two 

По-видимому, все за фоновым процессом выводится первым, а строки кода в хронологическом порядке до того, как фоновый процесс печатается последним. Я наткнулся на это в сценарии, который я пытался написать, и не понимаю, почему он ведет себя так (althogh, я предполагаю, что за этим стоит какая-то изобретательность).

Я уже выяснил, что могу предотвратить это с помощью скобок:

 echo one && (echo two &) echo three && echo four 

дает

 one two three four 

а также

 echo one && (sleep 2 && echo two &) echo three && echo four 

дает

 one three four two 

Потому что вторая строка спит в фоновом режиме и, следовательно, выводит, когда первые строки уже выполнены.

Но почему скобки имеют такой эффект?

Бонусный вопрос: почему скобки предотвращают вывод фонового PID?

2 Solutions collect form web for “Фоновые процессы смешивают порядок выполнения сценария оболочки”

 echo one && echo two & echo three && echo four 

Имейте в виду, что это анализируется как

 echo one && echo two & echo three && echo four 

Я предполагаю, что команды echo успешны (они будут терпеть неудачу только в случаях краев, таких как перенаправление на файл на полный диск). Таким образом, этот фрагмент выполняет две задачи параллельно: один печатает строки one и two , а другой печатает строки three и four . Вмешательство one и two с three и four не гарантируется и может варьироваться от системы к системе, от оболочки до оболочки и от вызова к вызову. Для подобного примера игрушек вы можете наблюдать воспроизводимые результаты в слегка загруженной системе, но это не то, на что вы можете рассчитывать.

 echo one && (echo two &) echo three && echo four 

Вы изменили синтаксический анализ: здесь в фоновом режиме выполняется только команда echo two . Это гарантирует, что one будет выводиться первым, и, как и до three , всегда будет до four , но размещение two может быть где угодно после one .

Оболочка только печатает сообщение о фоновых процессах, если они запускаются из основного процесса оболочки, а не когда они запускаются в подоболочке. Скобки создают подоболочку, поэтому (echo two &) не вызывает оболочку для печати любого сообщения. Это создает фоновый процесс, но не фоновая работа .

 echo one && (sleep 2 && echo two &) echo three && echo four 

В этом фрагменте фоновое задание засыпает в течение 2 секунд перед выдачей two . Это очень вероятно (но фактически не гарантировано), что two будут выдаваться после three и four .

Часть 1

 echo one && echo two & echo three && echo four 

Это можно переписать как

 echo one && echo two & echo three && echo four 

Причина, по которой вы получаете three и four первых, – это просто то, что для того, чтобы обработать one и two операции и работать дольше, чем для печати three и four требуется больше времени.

Вы можете видеть это немного более ясно, как это

 echo one && echo two & sleep 1 echo three && echo four 

В этой ситуации вы получаете one и two , а затем через секунду three и four .

Обратите внимание, что в исходном сценарии нет гарантии, что one и two не будут смешиваться с выходом из three и four , по- thonreee , даже с интерполированными словами, такими как thonreee или twfouro .

Часть 2

 echo one && (echo two &) echo three && echo four 

Это можно переписать как

 echo one && (echo two &) echo three && echo four 

Здесь происходит то, что one печатается сразу, а затем two выстреливаются в подоболочку. Затем (последовательно) выполняется следующая строка, в результате получается three и four . В вашей конкретной ситуации подоболочка мала и достаточно быстра, чтобы их можно было напечатать до выхода three . Однако никаких гарантий этого нет.

Часть 3

Групповые утверждения скобок группируются в подоболочку. Амперсанд & применим к заявлению, но в этом случае вы использовали && для связывания двух команд вместе, поэтому их нужно рассматривать как один оператор.

Возможно, вы должны использовать echo one; echo two echo one; echo two а не echo one && echo two ? Они очень разные. Точка с запятой ; разделяет две команды, которые затем запускаются независимо, но последовательно. Двойной амперсанд && соединяет две команды вместе как логические И , так что вторая будет работать только в том случае, если первая завершится успешно. Сравнить false; echo yes false; echo yes , false && echo yes , а true && echo yes . Затем поэкспериментируйте, заменив && ( логическое И ) на || ( логическое ИЛИ ).

бонус

Вы теряете уведомление о контроле работы, потому что у подоболочки нет управления заданиями.

  • Как printf с несколькими аргументами, разделенными пространством
  • Сценарий Bash, использующий чтение, должен прекратить выполнение на Ctrl + D
  • sudo su - anotherusername, не запрашивающий пароль
  • Написание функции bash для автозагрузки скриптов Matlab
  • Нет вывода из inotifywait | AWK
  • Как написать сценарий для подсчета общего количества файлов и каталогов в моем домашнем каталоге, а затем отобразить его?
  • Установите псевдоним на оболочку Bourne
  • как makefile может определить, доступна ли команда на локальном компьютере?
  • Как указать аргументы для возврата всех файлов точек, но не. а также ..?
  • Почему моя команда не работает при сглаживании?
  • Простая функция обертки awk или псевдоним
  • косвенное изменение переменной в POSIX, как сделано в bash?
  • Linux и Unix - лучшая ОС в мире.