2013-09-12 4 views
1

У меня есть это:Как стандартный вывод и стандартный поток ошибок перенаправляется сюда

$ time 2>&1 sh 2>&1 -c "dd if=/dev/zero of=ddfile bs=512 count=125 && sync" > file 

125 + 0 записей в

125 + 0 записей из

64000 байт (64 Кбайт), скопированные, 0.000617678 с , 104 Мб/с

реальные 0m0.133s

пользователь 0m0.000s

SYS 0m0.020s

$ cat file 

файл пуст.

Вопрос: Я понимаю, что оба dd и time отправляют свои o/p в stderr. Но так как я перенаправил stderr на stdout для time и sh (который является родительским процессом dd), а также отправил stdout для перехода в файл. Я ожидаю, что вещи будут записаны в файл. Почему этого не случилось?

+0

связанные? http://stackoverflow.com/questions/2408981/how-cant-i-redirect-the-output-of-time-command – pje

ответ

3

Во-первых, за некоторыми исключениями перераспределение обычно происходит в том месте, где они написаны. Они удаляются из последовательности команд и аргументов; участвуют только остальные, непереадресованные слова. Таким образом:

3>&1 foo 1>&2 arg1 2>&3 arg2 3>&- arg3 

работает foo arg1 arg2 arg3 с стандартным выводом и стандартным потоком ошибок выгружены, потому что:

  1. 3>&1 делает копию (точнее, dup2) ФД 1 (стандартный вывод) на дескрипторе 3
  2. 1>&2 марки копия fd 2 (stderr) на fd 1 (так что теперь stdout и stderr оба идут туда, куда бы они ни направлялись)
  3. 2>&3 делает копию fd 3 (сохраненный исходный stdout) на fd 2 (stderr)
  4. 3>&- закрывает Fd 3.

(Заметным исключением является то, что конвейерный выход «происходит первый», даже если символ трубы в конце простой командной части.)

Во-вторых, поскольку pje отметил, time - это встроенный баш. time foo запускает команду, затем печатает сводку времени для stderr bash. Ключевое слово time эффективно удаляется первым, затем оставшаяся последовательность команд обрабатывается, как обычно. (Это применимо, даже если команда является конвейером: time раз весь трубопровод.)

В этом случае последовательность команд является одна простой командой, с переадресациями:

2>&1 sh 2>&1 -c ... > file 

Каждого Перенаправление происходит в точке написано, а оставшаяся последовательность:

sh -c ... 

Перенаправлениями являются:

  1. отправьте stderr туда, куда stdout в настоящее время собирается
  2. отправить stderr в stdout, снова (это не имеет никакого эффекта)
  3. отправьте stdout на номер file.

так sh -c запускается с его STDERR будет ваш стандартный вывод, а его стандартный вывод собирается подать file. Как вы заметили, dd выводит свой вывод на stderr, который является stderr sh -c ..., который является вашим стандартом.

При запуске:

time 2>file dd if=/dev/zero of=ddfile bs=512 count=125 

вы получите time 's выход Stderr на вашем STDERR (например, экран), и dd' s STDERR в файле file. (Это происходит независимо от того, насколько правильно вы слайд 2>file части, до тех пор, пока она остается частью простой команды.)

Если попробовать:

2>file time ... 

вы найдете выход time «s перенаправлен , но это полностью побеждает встроенный time, вместо этого работает /usr/bin/time. Чтобы получить встроенный баш-бит, time должен быть впереди. Вы можете сделать подоболочку:

(time ...) 2>file 

или подблок как pje illustrated:

{ time ...; } 2>file 

(синтаксис является неуклюжим с субблоком в виде белого пространства и/или запятой необходимы, но он избегает системного вызова fork).

+0

(Это происходит независимо от того, насколько далеко вы сдвигаете часть файла 2>, если она остается частью простой команды.) Почему так, я не совсем понял это? – abc

+0

@abc: с любым из: 'time 2> file cmd arg' или' time cmd 2> file arg' или 'time cmd arg 2> file',' time' обрабатывается первым, затем 'cmd',' arg' , а файл '2> происходит в любом порядке, настраивая перенаправление' cmd arg', затем запускается 'cmd arg' (с stderr, перенаправленным на время' cmd', но не для '' самого времени'). – torek

4

Если вы хотите перенаправить вывод time и подзаконные команды, вы можете сгруппировать их в качестве блока кода и перенаправить поток ошибок в файл:

$ { time sh -c "dd if=/dev/zero of=ddfile bs=512 count=125 && sync"; } 2> file 

... который производит:

$ cat file 
125+0 records in 
125+0 records out 
64000 bytes (64 kB) copied, 0.000617678 s, 104 MB/s 

real  0m0.133s 
user  0m0.000s 
sys   0m0.020s 
Смежные вопросы

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