Почему вывод некоторых программ Linux не идет ни в STDOUT, ни в STDERR?

5612
Will Sheppard

Почему вывод некоторых программ 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 / null .

Какой выходной поток использует время, и как я могу передать его в файл?

Один из способов обойти эту проблему - создать скрипт Bash, например, combine.shсодержащий следующую команду:

$@ 2>&1 

Тогда вывод «времени» может быть записан правильным образом:

combine.sh time sleep 1 &> /dev/null 

(ничего не видно - правильно)

Есть ли способ достичь того, что я хочу, без использования отдельного сценария объединения?

20
сначала вы должны изменить порядок: `2> & 1> / dev / null` означает, что« 2 теперь идет туда, куда идет 1 (т. е. терминал, по умолчанию), а затем 1 теперь переходит в / dev / null (но 2 по-прежнему идет к терминалу!). используйте `> / dev / null 2> & 1`, чтобы сказать:« 1 переходит теперь в / dev / null, затем 2 переходит туда, где 1 (то есть также в / dev / null). Это все равно не сработает, так как встроенное «время» не будет перенаправлено, но в более общем смысле правильно (например, оно будет работать, если вы используете / usr / bin / time). Думайте о «2> & 1» как о копировании «направления» 1 в 2, а не как 2, идущее к 1 Olivier Dulac 10 лет назад 3

3 ответа на вопрос

38
gniourf_gniourf

This question is addressed in BashFAQ/032. In your example, you would:

{ time sleep 1; } 2> /dev/null 

The reason why

time sleep 1 2>/dev/null 

doesn't behave how you're expecting is because with that syntax, you'll want to time the command sleep 1 2>/dev/null (yes, the command sleep 1 with stderr redirected to /dev/null). The builtin time works that way so as to make this actually possible.

The bash builtin can actually do this because... well, it's a builtin. Such a behavior would be impossible with the external command time usually located in /usr/bin. Indeed:

$ /usr/bin/time sleep 1 2>/dev/null $ 

Now, the answer to your question

Why does the output of some linux programs go to neither STDOUT nor STDERR?

is: it does, the output goes to stdout or stderr.

Hope this helps!

Вы можете создать другой fd и сделать так, чтобы команды явно переходили к ним (например, в bash-скрипте: `exec 3> / some / file; ls> & 3;`) Olivier Dulac 10 лет назад 2
@OlivierDulac Конечно, или даже проще с помощью встроенного `coproc`. Но дело не во встроенном времени. gniourf_gniourf 10 лет назад 0
@ gniourf-gniourf: я комментировал из-за твоего предложения "вывод идет в stdout или stderr" ^^ Olivier Dulac 10 лет назад 0
13
Alok

Your particular question about time builtin has been answered, but there are some commands that don't write either to stdout or to stderr. A classic example is the Unix command crypt. crypt with no arguments encrypts standard input stdin and writes it to standard output stdout. It prompts the user for a password using getpass(), which by defaults outputs a prompt to /dev/tty. /dev/tty is the current terminal device. Writing to /dev/tty has the effect of writing to the current terminal (if there is one, see isatty()).

The reason crypt can't write to stdout is because it writes encrypted output to stdout. Also, it's better to prompt to /dev/tty instead of writing to stderr so that if a user redirects stdout and stderr, the prompt is still seen. (For the same reason, crypt can't read the password from stdin, since it's being used to read the data to encrypt.)

+1. Менее актуально для OP, но более актуально для всех, кто сталкивался с вопросом «Почему вывод некоторых программ linux не идет ни в STDOUT, ни в STDERR?» через гугл. :-) ruakh 10 лет назад 1
-1
Uwe Plonus

The problem in your case is that the redirection works in another way. You wrote

time sleep 1 2>&1 > /dev/null 

This redirects the standard output to /dev/null and then redirects the standard error to standard output.

To redirect all output you have to write

time sleep 1 > /dev/null 2>&1 

Then the standard error will be redirected to the standard output and after that all the standard output (containing the standard error) will be redirected to /dev/null.

Это не работает с bash _builtin_ `time`. Смотрите мой ответ для некоторых объяснений. gniourf_gniourf 10 лет назад 0
+1, потому что это полезный ответ на похожий вопрос. Хотя @Olivier объясняет это лучше в комментарии к вопросу выше. Will Sheppard 9 лет назад 0

Похожие вопросы