Существует ли стандарт, как команды, которые запускают другие команды, лечат конструкции оболочки, такие как перенаправления?

Просто запустите:

$ shopt extglob

Он вернет текущий статус:

$ shopt extglob 
extglob         on
$ shopt -u extglob 
$ shopt extglob 
extglob         off

Чтобы показать все параметры, просто запустите:

$ shopt
1
15.08.2018, 23:20
2 ответа

TL;DR:

Is there a common expectation how something_else should behave?

Да, как обычная команда. Оболочка не понимает command1 command2как две команды, это одна команда и один аргумент (, даже если это может быть имя действительного двоичного файла, найденного в /bin, например ). Это command1, который позже запускает command2через системный вызов exec(), а не через оболочку.

Are there shell constructs that can disambiguate these commands (like which program's output is redirected)

Нет, someting_elseне будет рассматриваться как-то особенно. Как сказано выше, нет другой конструкции, кроме одной команды и одного аргумента. Также кажется, что путаница в этом вопросе заключается в том, что и strace, и fooпредполагаются запущенными оболочкой, но на самом деле это цепочка родительских -дочерних процессов.

Как оболочка обрабатывает команды и перенаправления

Bourne -как и оболочки (это bash, dash,ksh)все следуют правилам POSIX в отношении того, как интерпретируются команды. POSIX определяет:«Простая команда» — это последовательность необязательных присвоений переменных и перенаправлений в любой последовательности, за которыми могут следовать слова и перенаправления, завершающиеся управляющим оператором». Это можно представить в виде:

[VAR=foo BAR=baz] command1 [arg1, arg2...] [ n>m ]

Общее правило заключается в том, что перенаправление применяется к команде, которая будет оставлена ​​большинством не -слова назначения. В вашем примере strace— это команда, а foo— аргумент для strace. Перенаправления применяются только к команде, а не к аргументам, то есть к strace. fooзапускается не оболочкой, а strace, и в этом случае fooстановится дочерним процессом strace. Точно так же somethingelseбудет рассматриваться как команда с fooв качестве аргумента.

Дескрипторы файлов

Что касается не встроенных -команд, они являются дочерними процессами оболочки, а дочерние процессы наследуют файловые дескрипторы оболочки, поэтому они обычно не управляют перенаправлениями -, они получают «предварительно упакованные» места назначения., так что, что касается straceи 2>/dev/null,ему, вероятно, все равно, какой на самом деле файловый дескриптор 2 (, если он не активно проверяет уровень исходного кода ). straceпо-прежнему будет записывать вывод в файловый дескриптор 2, но оболочка уже подключила -этот файловый дескриптор, чтобы он указывал на /dev/null.

Поскольку файловые дескрипторы наследуются, это также объясняет, почему, если вы делаете что-то вроде strace stat noexist 2>stracelog.txt, оба потока ошибок из straceи statпопадают в один и тот же файл. Напротив, некоторые команды позволяют явно указать пункт назначения в качестве одной из своих опций. Таким образом, с strace -o tracelog.txt stat noexist 2>stracelog.txtу вас есть вывод только из statв файл stracelog.txt-, хотя дескриптор файла унаследован, теперь флаг -oявляется свойством strace, а вывод управляется командой даже если дескриптор файла унаследован.

Это также дает нам небольшой намек :на то, что теоретически команды могут «перенаправлять» в смысле дублирования файловых дескрипторов на существующие с помощью dup2()системного вызова, который является точно таким же механизмом, который использовали бы оболочки, но насколько >тип символов перенаправления -, который все еще находится под контролем оболочки и, следовательно, интерпретируется только родительской оболочкой.

Почему 2>/dev/null ?

Общепринято, что диагностический вывод направляется на stderr. На самом деле у нас уже есть два отличных поста на эту тему:

watchи straceв ваших примерах следуют соглашению, вот и все. Нет необходимости указывать 2>/dev/nullдля скрытия вывода таких команд как такового.

Если вы хотите указать перенаправления для команды, которую вы передаете в качестве аргумента, например, на strace, вам понадобится оболочка вокруг нее. Например,

strace -f bash -c 'stat /etc/passwd nonexisting 2>/dev/null'

Обратите внимание на использование флага -f, так как если вы сосредоточены на отслеживании системных вызовов применительно к команде stat,вы можете не увидеть их без флага -f.

1
27.01.2020, 23:23

Сами команды не обрабатывают перенаправления. Когда оболочка создает новый процесс для запуска команды, она настроит ввод-вывод в соответствии с указаниями. Сама команда просто запускается, не заботясь об этом.

Ваша команда something_elseпросто выводит вывод на стандартный вывод и стандартный вывод, как обычно.

2
27.01.2020, 23:23

Теги

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