Разница важна, когда вы запускаете дочерние процессы.
Назначение:
$stdout = File.open("/dev/null", "w")
system "ls"
warn $stdout.fileno # file descriptor number
Вывод - обратите внимание, как вывод system
по-прежнему отображался:
1.txt 2.txt
7
Переоформление:
$stdout.reopen("/dev/null")
system "ls"
warn $stdout.fileno
Вывод - вывод system
был отправлен на /dev/null
:
1
Резюме:
Переназначение $stdout
, $stdin
или $stderr
влияет только на текущий процесс ruby. Дочерний процесс записывает свой собственный стандартный вывод в файловый дескриптор (FD) 1, считывает стандартный ввод из FD 0 и записывает диагностический вывод в FD 2.
Если вы хотите, чтобы потомок унаследовал изменение, вам нужно снова открыть поток, потому что он повторно использует дескриптор файла. Обратите внимание, что на ребенка влияет только, если вы reopen
до запуска ребенка.
Один вариант использования: вы пишете скрипт-демон (или другой скрипт, который должен продолжать работать после выхода из системы). Рекомендуется снова открыть все 3 стандартных потока до /dev/null
, в противном случае вы можете получить прерванный канал, если сценарий или дочерний процесс попытается использовать потоки.