Оболочка execBuilt-In (первый нюанс)

Оболочка execBuilt-In (первый нюанс)

Я пытаюсь перенаправить весь вывод программы (Steam) в /dev/null, чтобы он не отображался в терминале.

Вот что я пробовал: steam & > /dev/null 2>/dev/nullиsteam & > /dev/null 2>&1

Ни один из них не подавляет сообщения вообще (насколько я могу судить).

Насколько я понимаю, & отсоединяет процесс от терминала, а > перенаправляет ввод/вывод, причем по умолчанию/пустой > является stdout, а 2> — stderr. Есть ли еще выходы, кроме этих двух? Почему я все еще вижу вывод, если перенаправляю его весь?

решение1

Пытаться:

steam 2>&1 > /dev/null &

2>&1перенаправляет stderr в stdout и > /dev/nullперенаправляет stdout в /dev/null.

to &background процесс был неправильно размещен. Он должен быть в конце строки. Если поместить после , steamно до >, ничего из не steamбудет перенаправлено, хотя процесс будет правильно переведен в фоновый режим.

решение2

Эта конкретная проблема с steamслучается как особый случай, который иногда может потребовать особого понимания и обработки. steamСреда выполнения — это скрипт-обертка, содержащий следующее:

#!/bin/bash
# default to minimize on close, so we never have a running steam process
# in the background because of a broken Tray Icon on some desktops/WMs
#export STEAM_FRAME_FORCE_CLOSE=${STEAM_FRAME_FORCE_CLOSE:-0}
exec /usr/lib/steam/steam "$@"

Обратите внимание, что он использует execвстроенную оболочку, а также передает все аргументы с помощью $@.

Итак, хотя обычное решение для перенаправления вывода оболочки будет похоже на@Adobe и ответ @Gary, этот конкретный тип случая часто может потребовать немного более тонкого подхода и понимания того, что происходит за кулисами. Есть некоторая тонкость относительно того, почему все возможные методы перенаправления вывода и порядок операций steamиногда не могут работать так, как ожидалось.

Оболочка execBuilt-In (первый нюанс)

Стандарт POSIX определяет поведение длякомандаexec. Bash обеспечивает это черезexecВстроенная оболочка. Что может повлиять на стандартное перенаправление ввода-вывода и дерево подпроцессов, в зависимости от того, как оно вызывается. Примечание:Хотя технически это не применялось в конкретном варианте использования OP и перечисленных командах, я включаю это сюда, потому что это распространенная ошибка и предостережение, о котором следует знать.

Из стандарта IEEE 1003.1, издание 2004 г.:

Утилита exec должна открывать, закрывать и/или копировать дескрипторы файлов, как указано в любых перенаправлениях как части команды.

Если exec указан без команды или аргументов, и любые файловые дескрипторы с номерами больше 2 открываются с соответствующими операторами перенаправления, не указано, остаются ли эти файловые дескрипторы открытыми, когда оболочка вызывает другую утилиту. Скрипты, обеспокоенные тем, что дочерние оболочки могут неправильно использовать открытые файловые дескрипторы, всегда могут закрыть их явно, как показано в одном из следующих примеров.

Если exec указан с командой, он заменит оболочку командой без создания нового процесса. Если указаны аргументы, они будут аргументами команды. Перенаправление влияет на текущую среду выполнения оболочки.

Строка exec /usr/lib/steam/steam "$@"в /usr/bin/steamскрипте-оболочке заменит исполняемую /bin/bashоболочку (согласно строке "shebang"), не создавая нового подпроцесса. $@Спецификатор аргумента передается в двойных кавычках, что в большинстве случаев должно избежать любых побочных эффектов с операторами перенаправления ввода-вывода. Однако полезно знать, что передача некоторых операторов перенаправления вывода в качестве аргументов (например, через ошибочные кавычки "или 'или через evalescape-символ \) может предоставить возможность внедрить операторы перенаправления оболочки в скрипт таким образом, что вызов execможет повлиять на стандартные дескрипторы ввода-вывода и файлов команды. Таким образом, в зависимости от того, как вы передаете 2>&1или >somefileдругие операторы перенаправления в скрипт-оболочку, они будут оцениваться в контексте: "$@". К счастью, двойные кавычки в этом случае устранят большинство побочных эффектов, но важно быть осторожным, какой процесс bash или подоболочка оценивает эти аргументы.

Перенаправление вывода Unix: stdin, stdout, &stderr

Большинство UnixРЕПЛоболочки имеют аналогичный метод перенаправлениястандартные потоки ввода-вывода, stdin, stdout, и stderr. Сюда входят, но не ограничиваются: POSIX sh, Bash, Z Shell zsh, Korn Shell ksh, C Shell csh, Dash dashи другие.

Для ответа на вопрос автора мы сосредоточимся только на Bash, поскольку /usr/bin/steamскрипт-обертка начинается с Bash "притон" линия: #!/bin/bash.

В Bash первые 3 файловых дескриптора ( fd's) всегда определяются следующим образом, индексируясь с нуля 0:

  • stdin"="fd 0
  • stdout"="fd 1
  • stderr"="fd 2

Вывод любой команды можно перенаправить с помощьюОператоры перенаправления вывода в Bash (Справочное руководство Bash: § 3.6 Перенаправления). Базовое введение в это можно найти в этой статье:Забавное перенаправление Bash с помощью дескрипторов. Для более наглядного объяснения с наглядными пособиями,см. эту прекрасную статью (Настоятельно рекомендуется!).

Порядок действий (второй нюанс):

Существует тонкий порядок операций между:

... и:

ИзСправочное руководство Bash § 3.6 Перенаправления:

Перенаправления обрабатываются в порядке их появления, слева направо.

[...СНИП...]

Обратите внимание, что порядок перенаправлений имеет значение. Например, команда

ls > dirlist 2>&1

направляет как стандартный вывод (файловый дескриптор 1), так и стандартную ошибку (файловый дескриптор 2) в файл dirlist, тогда как команда

ls 2>&1 > dirlist

направляет только стандартный вывод в файл dirlist, поскольку стандартная ошибка была сделана копией стандартного вывода до того, как стандартный вывод был перенаправлен в dirlist.

Аналогично существует порядок операций для &и других операторов управления.

ИзСправочное руководство Bash: 2.4 Списки команд:

Список представляет собой последовательность из одного или нескольких конвейеров, разделенных одним из операторов ' ;', ' &', ' &&' или ' ||', и необязательно завершающихся одним из операторов ' ;', ' &' или newline.

Из этих операторов списка ' &&' и ' ||' имеют равный приоритет, за ними следуют ' ;' и ' &', которые имеют равный приоритет.

В качестве разделителя команд может использоваться последовательность из одного или нескольких символов новой строки list, эквивалентная точке с запятой.

Наконец, конкретно раздел о &:

Если команда завершается оператором управления ' &', оболочка выполняет команду асинхронно в подоболочке. Это известно как выполнение команды вфон, и они называютсяасинхронныйКоманды. Оболочка не ждет завершения команды, а возвращается статус 0( true). Когда управление заданиями неактивно (см.Контроль работы), стандартный ввод для асинхронных команд, при отсутствии явных перенаправлений, перенаправляется из /dev/null.

Почему команды ОП не дали ожидаемого результата

Первые две опробованные команды были:

  • steam & > /dev/null 2>/dev/null
  • steam & > /dev/null 2>&1

Причина, по которой они не выполнили предполагаемое перенаправление обоих stdoutи, stderrкак ожидалось, заключается в вышеупомянутомпорядок операций/приоритет операторовправила, перечисленные выше. В частности, &оператор отображается первым в порядке слева направо. Он применяется к первому слову, команде steamи отправляет ее в фоновый режим, работающий какасинхронная команда. stdinподключен к /dev/null, в то время как stdout, и stderrостаются подключенными к управляющемуПсевдотерминал /pty. Это более подробно объяснено ниже.

Но сначала...

Еще больше execпутаницы в цепях!

Связанный контент