2015-06-04 3 views
0

ребенка Если я бегу Баш скрипт так:стандартный вывод и стандартный поток ошибок Перенаправление в процессе

./script.sh 2>&1 

stderr будет перенаправлен на stdout.

Если сценарий вызывает некоторый инструмент внутри (например, ls) или порождает новый процесс, будут ли эти дочерние процессы имеют свои stderr также перенаправлены на stdout?

+2

Да, это так. – anubhava

ответ

10

Создание дочернего процесса в UNIX/Linux использует процедуру, обычно известную как fork. Это делается для копирования почти всего адресного пространства процесса текущего процесса (код программы, данные, почти все) на ребенка. Идентификатор процесса (PID) отличается у ребенка, но почти все остальное одно и то же.

Один из элементов в процессе, который скопирован, представляет собой таблицу дескриптора файла . Это похоже на массив. Существует запись для каждого открытого файла, и по соглашению первые три, 0, 1, 2 представляют собой стандартные потоки , stdin, stdout, stderr. Этим объясняются номера, используемые в 2>&1. Когда мы перенаправляем, это три записи, которые были изменены у ребенка. Это делается оболочкой, так как на этом этапе наш дочерний процесс является другим процессом оболочки.

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

Итак, если таблица дескриптора файла была изменена ранее, новая программа наследует этих изменений. Нет ничего, чтобы остановить программу от переопределения этих настроек и использования разных файлов, но это редко делается.

Все это по умолчанию. Программы могут изменять, какие файловые дескрипторы и другие элементы сохраняются на границе fork/exec, но обычно этого не делают.

+0

благодарит за подробное объяснение – Tomek

1

Да, это короткий ответ. Вы можете попробовать это сами:

$ (>&1 echo "STDOUT is gone"; >&2 echo "I'm still here") > /dev/null 
I'm still here 

STDOUT родительского процесса [Я начинаю новую оболочку с фигурными скобками: ()] будет отправлено /dev/null, и так будет все детские STDOUT.

Смежные вопросы