Создание подошвы Bash с фигурными фигурными скобками

В соответствии с этим , размещение списка команд между фигурными скобками приводит к тому, что список будет выполнен в текущем контексте оболочки. Ни одна подседка не создана .

Используя ps, чтобы увидеть это в действии

Это иерархия процессов для конвейера процесса, выполняемого непосредственно в командной строке. 4398 - это идентификатор PID для оболочки входа:

sleep 2 | ps -H;
  PID TTY          TIME CMD
   4398 pts/23   00:00:00 bash
   29696 pts/23   00:00:00   sleep
   29697 pts/23   00:00:00   ps

Теперь следует иерархия процессов для конвейера процесса между фигурными скобками, выполняемыми непосредственно в командной строке. 4398 - это идентификатор PID для оболочки входа. Он похож на приведенную выше иерархию, доказывая, что все выполняется в текущем контексте оболочки :

{ sleep 2 | ps -H; }
   PID TTY          TIME CMD
    4398 pts/23   00:00:00 bash
    29588 pts/23   00:00:00   sleep
    29589 pts/23   00:00:00   ps

Теперь, это иерархия процессов, когда sleep в самом себе помещается внутри фигурных скобок (так что два уровня фигурных скобок в все)

{ { sleep 2; } | ps -H; }
  PID TTY          TIME CMD
   4398 pts/23   00:00:00 bash
   29869 pts/23   00:00:00   bash
   29871 pts/23   00:00:00     sleep
   29870 pts/23   00:00:00   ps

Почему bash необходимо создать подседель для запуска sleep в третьем случае, когда в документации указано, что команды между фигурными фигурными скобками выполняются в текущем контексте оболочки?

28 голосов | спросил iruvar 30 PMpWed, 30 Apr 2014 22:13:15 +040013Wednesday 2014, 22:13:15

3 ответа


25

В конвейере все команды запускаются одновременно (со своим stdout /stdin, подключенным по каналам), поэтому в разных процессах.

В

cmd1 | cmd2 | cmd3

Все три команды запускаются в разных процессах, поэтому по крайней мере два из них должны выполняться в дочернем процессе. Некоторые оболочки запускают один из них в текущем процессе оболочки (если он встроен как read или если конвейер является последней командой скрипта) но bash запускает их все в своем отдельном процессе (кроме lastpipe в последних версиях bash и при определенных условиях).

{...} группировать команды. Если эта группа является частью конвейера, она должна выполняться в отдельном процессе, как простая команда.

В:

{ a; b "$?"; } | c

Нам нужна оболочка для оценки того, что a; b "$?" - это отдельный процесс, поэтому нам нужна подоболочка. Оболочка могла бы оптимизировать, не открывая для b, так как это последняя команда, которая будет запущена в этой группе. Некоторые оболочки делают это, но, по-видимому, не bash.

ответил Stéphane Chazelas 1 Mayam14 2014, 01:18:25
18

Вложение фигурных скобок, по-видимому, означает, что вы создаете дополнительный уровень охвата, который требует вызова новой суб-оболочки. Вы можете увидеть этот эффект со второй копией Bash в вашем выводе ps -H.

В рамках исходной оболочки Bash выполняются только процессы, указанные на первом уровне фигурных скобок. Любые вложенные фигурные фигурные скобки будут выполняться в своей собственной оболочке Bash.

Пример

$ { { { sleep 20; } | sleep 20; } | ps -H; }
  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5012 pts/1    00:00:00   bash
 5014 pts/1    00:00:00     bash
 5016 pts/1    00:00:00       sleep
 5015 pts/1    00:00:00     sleep
 5013 pts/1    00:00:00   ps

Извлекая | ps -H, чтобы мы могли видеть вложенные фигурные скобки, мы можем запустить ps auxf | less в другой оболочке.

saml     29190  0.0  0.0 117056  3004 pts/1    Ss   13:39   0:00  \_ bash
saml      5191  0.0  0.0 117056  2336 pts/1    S+   14:42   0:00  |   \_ bash
saml      5193  0.0  0.0 107892   512 pts/1    S+   14:42   0:00  |   |   \_ sleep 20
saml      5192  0.0  0.0 107892   508 pts/1    S+   14:42   0:00  |   \_ sleep 20
saml      5068  0.2  0.0 116824  3416 pts/6    Ss   14:42   0:00  \_ bash
saml      5195  0.0  0.0 115020  1272 pts/6    R+   14:42   0:00      \_ ps auxf
saml      5196  0.0  0.0 110244   880 pts/6    S+   14:42   0:00      \_ less

Но подождите больше!

Если вы вынимаете трубы и используете эту форму команды, мы видим, что вы действительно ожидаете:

$ { { { sleep 10; } ; { sleep 10; } ; sleep 10; } } | watch "ps -H"

Теперь в появившемся окне часов мы получаем обновление каждые 2 секунды:

Вот первый sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5678 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5681 pts/1    00:00:00     watch
 5682 pts/1    00:00:00       ps

Вот второй sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5691 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5694 pts/1    00:00:00     watch
 5695 pts/1    00:00:00       ps

Вот третий sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5704 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5710 pts/1    00:00:00     watch
 5711 pts/1    00:00:00       ps

Обратите внимание, что все три спящего режима, но вызываемые на разных уровнях вложения фигурных скобок, занимают постоянное пребывание в PID 5676 Bash. Поэтому я считаю, что ваша проблема сама по себе связана с использованием | ps -H.

Выводы

Использование | ps -H (т. е. канал) вызывает дополнительную под-оболочку, поэтому не используйте этот метод при попытке чтобы допросить, что происходит.

ответил slm 30 PMpWed, 30 Apr 2014 22:40:27 +040040Wednesday 2014, 22:40:27
7

Я опубликую результаты моих тестов, что приведет меня к выводу, что bash делает под-оболочку для групповой команды if и only , если она является частью конвейера, что похоже на можно было бы вызвать некоторую функцию, которая также будет вызываться в под-оболочке.

$ { A=1; { A=2; sleep 2; } ; echo $A; }
2

$ { A=1; { A=2; sleep 2; } | sleep 1; echo $A; }
1
ответил Miroslav Koškár 30 PMpWed, 30 Apr 2014 22:56:51 +040056Wednesday 2014, 22:56:51

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132