В соответствии с этим , размещение списка команд между фигурными скобками приводит к тому, что список выполняется в текущем контексте оболочки. Никакая подоболочка не создана .
Используя, 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
в третьем случае, когда в документации говорится, что команды между фигурными скобками выполняются в текущем контексте оболочки?
{ sleep 2 | command ps -H; }
Ответы:
В конвейере все команды выполняются одновременно (со своим stdout / stdin, соединенным каналами), поэтому в разных процессах.
В
Все три команды выполняются в разных процессах, поэтому как минимум две из них должны выполняться в дочернем процессе. Некоторые оболочки запускают один из них в текущем процессе оболочки (если он встроен как,
read
или если конвейер является последней командой скрипта), ноbash
запускает их все в своем отдельном процессе (кроме как сlastpipe
опцией в последнихbash
версиях и при некоторых конкретных условиях). ).{...}
групповые команды. Если эта группа является частью конвейера, она должна выполняться в отдельном процессе, как простая команда.В:
Нам нужна оболочка, чтобы оценить, что
a; b "$?"
это отдельный процесс, поэтому нам нужна подоболочка. Оболочка может оптимизироваться, не разветвляясь,b
поскольку это последняя команда, которая будет запущена в этой группе. Некоторые оболочки делают это, но, видимо, нетbash
.источник
bash -c "sleep 112345 | cat | cat "
я вижу только один созданный bash и затем 3 дочерних для него без каких-либо других чередующихся подбаш.a; b "$?"
? Действительно ли существует фундаментальная потребность в subheel, или, может быть, это проектное решение / реализация на bash?eval
), но оценка (выполнить первую команду, дождаться ее, запустить вторую) сделано в ребенке, тот, который имеет стандартный вывод, подключенный к трубе.{ sleep 2 | ps -H; }
родительском bash видит,sleep 2
что требуется форк / exec. Но в{ { sleep 2; } | ps -H; }
родительском bash,{ sleep 2; }
другими словами, есть некоторый код bash. Похоже, что родитель может обрабатывать fork / exec,sleep 2
но рекурсивно порождает новый bash для обработки обнаруженного кода bash. Это мое понимание, имеет ли смысл?Вложенные фигурные скобки, кажется, означают, что вы создаете дополнительный уровень области видимости, который требует вызова новой суб-оболочки. Вы можете увидеть этот эффект со 2-й копией Bash в вашем
ps -H
выводе.Только процессы, предусмотренные на первом уровне фигурных скобок, выполняются в рамках оригинальной оболочки Bash. Любые вложенные фигурные скобки будут работать в своей собственной оболочке Bash.
пример
Извлекая
| ps -H
микс только для того, чтобы мы могли видеть вложенные фигурные скобки, мы можем запуститьps auxf | less
в другой оболочке.Но подождите, это еще не все!
Если вы удалите каналы и воспользуетесь этой формой команды, мы увидим, чего вы на самом деле ожидаете:
Теперь в появившемся окне наблюдения каждые две секунды мы получаем обновление того, что происходит:
Вот первый
sleep 10
:Вот второй
sleep 10
:Вот третий
sleep 10
:Обратите внимание, что все три сна, хотя и вызванные на разных уровнях вложенности фигурных скобок, действительно влияют на PID 5676 Bash. Поэтому я считаю, что ваша проблема связана с использованием
| ps -H
.Выводы
Использование
| ps -H
(то есть конвейер) вызывает дополнительную вложенную оболочку, поэтому не используйте этот метод при попытке опроса того, что происходит.источник
Я опубликую результаты моих тестов, которые приведут меня к выводу, что bash создает под-оболочку для групповой команды тогда и только тогда, когда она является частью конвейера, это похоже на то, как если бы вы вызывали какую-то функцию, которая также была бы вызвана в под-оболочке.
источник