Когда вы перенаправляете список команд, который содержит перенаправление exec, exec> / dev / null, похоже, по-прежнему не применяется впоследствии, например, с помощью:
{ exec >/dev/null; } >/dev/null; echo "Hi"
«Привет» печатается.
У меня сложилось впечатление, что {}
список команд не считается подоболочкой, если только он не является частью конвейера, поэтому, на exec >/dev/null
мой взгляд, его все равно следует применять в текущей среде оболочки.
Теперь, если вы измените его на:
{ exec >/dev/null; } 2>/dev/null; echo "Hi"
нет ожидаемого выхода; дескриптор файла 1 остается указанным на / dev / null и для будущих команд. Это показано повторным запуском:
{ exec >/dev/null; } >/dev/null; echo "Hi"
который не даст никакого выхода.
Я пытался сделать сценарий и определить его, но я все еще не уверен, что именно здесь происходит.
Что происходит в каждом сценарии с дескриптором файла STDOUT?
РЕДАКТИРОВАТЬ: добавив мой вывод strace:
read(255, "#!/usr/bin/env bash\n{ exec 1>/de"..., 65) = 65
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fcntl(1, F_GETFD) = 0
fcntl(1, F_DUPFD, 10) = 10
fcntl(1, F_GETFD) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
close(10) = 0
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fcntl(1, F_GETFD) = 0
fcntl(1, F_DUPFD, 10) = 10
fcntl(1, F_GETFD) = 0
fcntl(10, F_SETFD, FD_CLOEXEC) = 0
dup2(3, 1) = 1
close(3) = 0
dup2(10, 1) = 1
fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(10) = 0
fstat(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
ioctl(1, TCGETS, 0x7ffee027ef90) = -1 ENOTTY (Inappropriate ioctl for device)
write(1, "hi\n", 3) = 3
источник
close(10)
. Можете ли вы также опубликовать все содержимое скрипта, на котором вы работали?;
после}
, который меняет значение,> /dev/null
чтобы не применять к составному списку в{}
конце концов.Ответы:
Давайте следовать
шаг за шагом.
Есть две команды:
а.
{ exec >/dev/null; } >/dev/null
, с последующимб.
echo "Hi"
Оболочка выполняет сначала команду (а), а затем команду (б).
Исполнение
{ exec >/dev/null; } >/dev/null
выручки происходит следующим образом:а. Во-первых, оболочка выполняет перенаправление
>/dev/null
и запоминает отмену, когда команда заканчивается .б. Затем оболочка выполняется
{ exec >/dev/null; }
.с. Наконец, оболочка переключает стандартный вывод обратно туда, где был. (Это тот же механизм, что и в
ls -lR /usr/share/fonts >~/FontList.txt
перенаправлениях, выполняются только на время выполнения команды, к которой они принадлежат.)Как только первая команда выполнена, оболочка выполняется
echo "Hi"
. Стандартный вывод там, где он был до первой команды.источник
Чтобы не использовать вложенную оболочку или подпроцесс, когда вывод составного списка
{}
передается по конвейеру>
, оболочка сохраняет дескриптор STDOUT перед запуском составного списка и восстанавливает его после. Таким образом,exec >
в составном списке не действует после точки, где старый дескриптор восстанавливается как STDOUT.Давайте посмотрим на соответствующую часть
strace bash -c '{ exec >/dev/null; } >/dev/null; echo hi' 2>&1 | cat -n
:Вы можете видеть, как в строке 134 дескриптор
1
(STDOUT
) копируется в другой дескриптор с индексом, по крайней мере10
(это то, чтоF_DUPFD
делает; он возвращает наименьший доступный дескриптор, начинающийся с заданного числа после дублирования на этот дескриптор). Также посмотрите, как в строке 137 результатopen("/dev/null")
(дескриптор3
) копируется в дескриптор1
(STDOUT
). Наконец, в сети147
староеSTDOUT
сохраненное в дескрипторе10
копируется обратно в дескриптор1
(STDOUT
). Чистый эффект состоит в том, чтобы изолировать изменениеSTDOUT
на онлайн144
(что соответствует внутреннемуexec >/dev/null
).источник
exec
.Разница между
{ exec >/dev/null; } >/dev/null; echo "Hi"
и{ exec >/dev/null; }; echo "Hi"
заключается в том, что двойное перенаправление выполняетсяdup2(10, 1);
перед закрытием fd 10, который является копией оригиналаstdout
, перед выполнением следующей команды (echo
).Это происходит так, потому что внешний редирект фактически перекрывает внутренний. Вот почему он копирует обратно оригинальный
stdout
fd после завершения.источник