команда sh: exec 2> & 1 - PullRequest
       19

команда sh: exec 2> & 1

46 голосов
/ 01 августа 2009

Что будет делать эта команда?

exec 2>&1 

Ответы [ 6 ]

36 голосов
/ 01 августа 2009

Технически говоря, он дублирует или копирует stderr на стандартный вывод.

Обычно вам не нужен исполнитель для этого. Более типичное использование exec с файловыми дескрипторами состоит в том, чтобы указать, что вы хотите назначить файл неиспользуемому файловому дескриптору, например

exec 35< my_input

Кстати, не забывайте, что последовательность объявления при передаче в файл важна, поэтому

ls > mydirlist 2>&1

будет работать, потому что он направляет как stdout, так и stderr в файл mydirlist, тогда как команда

ls 2>&1 > mydirlist

направляет только stdout, а не stderr, в файл mydirlist, поскольку stderr был скопирован как stdout до того, как stdout был перенаправлен в mydirlist.

Редактировать: Так работает оболочка, сканируя слева направо. Поэтому прочитайте второй как «скопировать stderr на stdout» перед тем, как сказать «отправить stdout mydirlist». Затем прочитайте первый, который говорит «отправить stdout в файл mydirlist», прежде чем он скажет «дублировать stderr на тот стандартный stdout, который я настроил». Я знаю. Это совершенно не интуитивно понятно!

32 голосов
/ 26 октября 2012

Одна из лучших статей о том, что "2> & 1" я видел, - это Объяснения Bash One-Liners, Часть III: Все о перенаправлениях .

Но что текущие ответы на этот вопрос не дают, так это то, почему вы захотите сделать это после простого «exec». Как объясняется на странице руководства bash для команды exec: «Если команда не указана, любые перенаправления вступают в силу в текущей оболочке».

Я написал простой скрипт с именем out-and-err.py, который записывает строку вывода в stdout, а другую строку в stderr:

#!/usr/bin/python
import sys
sys.stdout.write('this is stdout.\n')
sys.stderr.write('this is stderr.\n')

И затем я обернул это в сценарий оболочки с именем out-and-err.sh как "exec 2> & 1":

#!/bin/bash
exec 2>&1
./out-and-err.py

Если я запускаю только скрипт на python, stdout и stderr разделяются:

$ ./out-and-err.py 1> out 2> err
$ cat out
this is stdout.
$ cat err
the is stderr.

Но если я запускаю сценарий оболочки, вы можете видеть, что exec позаботится о stderr для всего после:

$ ./out-and-err.sh 1> out 2> err
$ cat out
this is stdout.
this is stderr.
$ cat err
$

Если ваш сценарий оболочки-оболочки делает намного больше, чем просто одна команда python, и вам нужно объединить весь вывод в stdout, выполнение "exec 2> & 1" сделает это для вас простым.

13 голосов
/ 01 августа 2009

Связывает стандартную ошибку со стандартным выходом

2 - это стандартный вывод, а 1 - это стандартный вывод. Когда вы запускаете программу, вы получите обычный вывод в stdout, но любые ошибки или предупреждения обычно отправляются в stderr. Если вы хотите, например, направить весь вывод в файл, полезно сначала объединить stderr с stdout с 2>&1.

2 голосов
/ 01 августа 2009

Как сказал @cma, он помещает stderr в стандартный вывод. Причина, по которой вам может потребоваться такое поведение, заключается в использовании grep или любой другой утилиты для захвата выходных данных, которые появляются только в stderr. Или вы можете просто сохранить все выходные данные, включая stderr, в файл для последующей обработки.

0 голосов
/ 27 октября 2018

В эти дни я тоже был поглощен этой проблемой, но теперь я выпрыгиваю из нее. Итак, позвольте мне объяснить, что происходит после ввода exec 1>&2 в CLI.

Я хочу уничтожить проблему по частям, поэтому, если вы знаете, что знания уже прочитаны, просто просмотрите их, чтобы сэкономить время.

  • Что означает exec означает:

exec - это встроенная команда в Linux. В отличие от традиционной команды, которая просто разветвляет процесс под-оболочки, exec может изменить текущий процесс оболочки.

  • Что такое перенаправление ввода / вывода: Перенаправление является функцией в Linux. При этом вы можете изменить стандартные устройства ввода / вывода. В Linux по умолчанию есть три файловых дескриптора. Handle Name Description 0 stdin Standard input 1 stdout Standard output 2 stderr Standard error

  • Позвольте мне увидеть пример:

    1. открыть новый терминал
    2. Получить идентификатор процесса termianl $ pstree -p | grep 'term' | tr -d ' '
    3. Проверьте дескриптор файла процесса. $ sudo ls -l /proc/{pid}/fd bash $ pstree -p | grep -i 'terminal' | tr -d ' ' ||||-gnome-terminal-(6008)-+-bash(7641)-+-grep(8355) $ sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Как видите, в ls указан файл процесса PID (6860). Во-первых, все они называют по номеру (0, 1, 2), во-вторых, все они связывают ссылку на файл с / dev / pts / 3, это означает, что любой стандартный ввод / вывод / ошибка будет отображаться в pts3.
    4. Измените стандартный вывод на / tmp / stdout bash $ ls /tmp/stdout ls: cannot access '/tmp/stdout': No such file or directory $ exec 1>/tmp/stdout $ ls $ pwd $ echo "Are you ok" $ Выходные данные команды исчезли в это время.
    5. Откройте новый терминал, чтобы проверить файл proc bash $ sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /tmp/stdout lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Очевидно, что мы можем заметить, что 1 (дескриптор файла) уже меняет ссылку на / tmp / stdout. Как и у нас, кроме стандартного вывода передачи в / tmp / stdout
    6. Восстановить перенаправление. bash $ exec 1>&2 $ cat /tmp/stdout a.sh /home/alopex Are you ok $ sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Опять же, ссылка 1 (дескриптор файла) на / dev / pts / 3, мы снова можем увидеть вывод.
  • Резюме:

  • exec 1>&2 сделать стандартный вывод ---> стандартная ошибка
0 голосов
/ 27 декабря 2016

Одно довольно полезное приложение exec 2>&1, с которым я столкнулся, это когда вы хотите объединить stderr и stdout для нескольких команд, разделенных точкой с запятой. Мой конкретный пример произошел, когда я отправлял более чем одну команду на popen в PHP, и я хотел видеть чередование ошибок, как если бы вы вводили команды в командной строке:

$ echo hi ; yikes ; echo there
hi
-bash: yikes: command not found
there
$ 

Следующее не объединяет stderr и stdout, за исключением последнего echo (что бессмысленно, поскольку yikes вызывает ошибку):

echo hi ; yikes ; echo there 2>&1

Я могу получить объединенный вывод «трудным путем» следующим образом:

echo hi 2>&1; yikes 2>&1; echo there 2>&1

Это выглядит намного чище и менее подвержено ошибкам, если вы используете exec:

exec 2>&1 ; echo hi; echo yikes; echo there

Выходные данные stdout и stderr точно чередуются точно так же, как если бы вы выполнили три команды, разделенные точкой с запятой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...