Почему вывод некоторых программ Linux не идет ни в STDOUT, ни в STDERR?
На самом деле, я хочу знать, как надежно фиксировать весь вывод программы, независимо от того, какой «поток» он использует. У меня проблема в том, что некоторые программы, кажется, не позволяют захватывать их вывод.
Примером является команда time:
time sleep 1 2>&1 > /dev/null
real 0m1.003s
user 0m0.000s
sys 0m0.000s
или же
time sleep 1 &> /dev/null
real 0m1.003s
user 0m0.000s
sys 0m0.000s
Почему я вижу результат оба раза? Я ожидал, что все это будет передано в / DEV / нуль ,
Какой выходной поток использует время, и как я могу передать его в файл?
Один из способов обойти проблему - создать удар сценарий, например, combine.sh
содержащий эту команду:
$@ 2>&1
Тогда вывод «времени» может быть записан правильным образом:
combine.sh time sleep 1 &> /dev/null
(ничего не видно - правильно)
Есть ли способ достичь того, чего я хочу, без использования отдельного сценария объединения?
2>&1 > /dev/null
означает «2 теперь идет туда, куда идет 1 (т. е. к терминалу по умолчанию), а затем 1 теперь переходит в / dev / null (но 2 по-прежнему идет к терминалу!). use>/dev/null 2>&1
сказать "1 теперь идет в / dev / null, затем 2 идет туда, где 1 идет (то есть также в / dev / null). Это все равно не сработает, поскольку встроенное время не будет перенаправлено, но в целом правильно (например, это будет работать, если вы используете / usr / bin / time). Думайте о "2 & gt; & amp; 1" как о копировании "направления" 1 в 2, а не как 2, переходящее к 1Ответы:
Этот вопрос рассматривается в BashFAQ / 032 , В вашем примере вы бы:
Причина по которой
не ведет себя так, как вы ожидаете, потому что с этим синтаксисом вы захотите
time
командаsleep 1 2>/dev/null
(да, командаsleep 1
с STDERR перенаправлен на/dev/null
). Встроенныйtime
работает таким образом, чтобы сделать это на самом деле возможно.bash
встроенная на самом деле может сделать это, потому что ... ну, это встроенный. Такое поведение было бы невозможно с внешней командойtime
обычно находится в/usr/bin
, В самом деле:Теперь ответ на ваш вопрос
есть: вывод идет на стандартный вывод или же STDERR ,
Надеюсь это поможет!
источник
exec 3>/some/file ; ls >&3 ;
)coproc
встроенный. Но это не так дляtime
встроенный.Ваш конкретный вопрос о
time
Встроенный ответили, но есть являются некоторые команды, которые не пишут ниstdout
илиstderr
, Классическим примером является команда Unixcrypt
,crypt
без аргументов шифрует стандартный вводstdin
и пишет это в стандартный выводstdout
, Он запрашивает у пользователя пароль, используяgetpass()
который по умолчанию выводит подсказку/dev/tty
,/dev/tty
текущее оконечное устройство. Запись в/dev/tty
имеет эффект записи в текущий терминал (если есть, см.isatty()
).Причина
crypt
не могу написатьstdout
потому что он пишет зашифрованный выводstdout
, Также лучше подсказать/dev/tty
вместо того, чтобы писатьstderr
так что если пользователь перенаправляетstdout
а такжеstderr
, подсказка все еще видна. (По той же причине,crypt
не могу прочитать пароль отstdin
, поскольку он используется для чтения данных для шифрования.)источник
time sleep 1 > /dev/null 2>&1
# перенаправляет вывод "sleep" на null. Затем «время» записывает свой собственный вывод без перенаправления. Это как "time (sleep 1 > /dev/null 2>&1)
».(time sleep 1) > /dev/null 2>&1
# запускает "time sleep 1", затем перенаправляет свой вывод на ноль.[] S
источник
Проблема в вашем случае заключается в том, что перенаправление работает по-другому. Вы написали
Это перенаправляет стандартный вывод на
/dev/null
а затем перенаправляет стандартную ошибку на стандартный вывод.Чтобы перенаправить весь вывод, вы должны написать
Тогда стандартная ошибка будет перенаправлена на стандартный выход, и после этого все стандартные выходные (содержащие стандартную ошибку) будут перенаправлены на
/dev/null
,источник
time
, Смотрите мой ответ для некоторых объяснений.