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


40

я знаю что

  program > /dev/null 2>&1 

делает. Он перенаправляет вывод в /dev/nullи 2>&1означает перенаправить вывод ошибки в том же месте, куда отправляется вывод.

Моя проблема в том, что мне всегда приходится гуглить, потому что я никогда этого не помню.

Итак, я стараюсь &2>1, 1>2&, 1>&2... Я стараюсь каждую комбинацию , пока я не Google это ...

Какой трюк, чтобы запомнить это легко?


У меня та же проблема, поэтому я делаю это "длинным" способом - перенаправить оба program 1> /dev/null 2>/dev/null. Хотя иногда вам нужно смешивать stdoutи stderrвместе, чтобы увидеть, что на самом деле происходит - например, результат сложного процесса компиляции, перенаправляемый в файл. В этом случае я в конечном итоге
погуглить

Ответы:


20

Вывод лучше, чем ошибка, поэтому он идет первым (1 против 2).

>это сокращение от «идет к». Слева - то, что я хочу отправить, а справа - то, куда я хочу это отправить. Поскольку «где» - это (почти) всегда файл, что-то вроде

program > /dev/null 2>1

будет перенаправлять в файл с именем 1. Таким образом, амперсанд (&)изменяет файл в дескриптор файла.

К сожалению, я не сталкивался и не разработал свою собственную мнемонику, но когда я впервые изучил * nix, я нашел этот логичный способ хорошо работать. После нескольких прогонов он становится второй натурой.


Ваше первое предложение не имеет смысла для меня. stdoutэто файловый дескриптор 1, stderrравен 2. Итак, «ошибка» предшествует «выводу».
Уоррен Янг

Это предложение является мнемоникой для запоминания дескриптора файла stdoutи stderrссылки.
gvkv

Хорошо, но это по-прежнему сбивает с толку, поскольку первоначальный вопрос касается попытки запомнить порядок символов в заклинании "2> & 1".
Уоррен Янг

9

Один трюк состоит в том, чтобы просто помнить, что 1 = стандартный вывод, 2 = стандартная ошибка. Так:

2>&1= стандартный поток ошибок входит в стандартный поток вывода.
1>&2= наоборот

Если вы когда-либо программировали на C-подобном языке, легко запомнить амперсанд ( &). Я предпочитаю думать об этом как об «адресе» существующего дескриптора файла, чтобы вы не меняли сам файл или не создавали новый.


7

Видя , &как узел может помочь: думать о том, что вы хотите сделать , как принимать выход 2, так 2>и связывая его с 1, так2>&1


2
Я просто запомнил фразу "два и один". Независимо от того, является ли ваше мнемоническое выражение фразой или узлом, наличие такого действительно поможет.
Тим Кеннеди

5

На самом деле, это зависит от того, какую оболочку вы используете. Баш обычно очень простителен, и вы можете просто сделать:

program &> file

5

Давайте рассмотрим эти три варианта:

program  2>1
program  2>1& 
program  2>&1

Первый отправляет stderr в файл с именами «1»: в конце концов, bash ожидает перенаправления в файл.

Второй также перенаправляет в тот же файл, но работает programв фоновом режиме: это то, что &должен означать трейлинг .

Это оставляет третью возможность как единственную, которая имеет смысл во вселенной bash для перенаправления на дескриптор файла.

Как запомнить какой есть какой из 0, 1, 2? Подумайте о запуске компьютера из консоли. Во-первых, вы должны набрать что-то (0 = стандартный ввод). Затем вы видите вывод (1 = стандартный вывод). Наконец, и только если что-то пойдет не так, вы увидите stderr (2).


1

Нарисуй это в своих обоях.

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


1

Что касается оболочки bash, я считаю, что лучший способ запомнить это - понять, что происходит.
Если все, что вы хотите сделать, это помнить, как правильно ввести команду, вы можете попробовать

program > /results 2> /results

Это хорошо и понятно, что происходит и легко запомнить. т.е.

  • 1 STDOUT собирается /results
  • 2STDERR также собирается непосредственно в/results

проблема в том, что это не работает так, как вы ожидаете. учитывать следующее:

файл: /tmp/poem.txt

the quick brown fox jumped over the lazy dog

и запустить команду

grep "brown" /tmp/poem.txt NOT_A_FILE > /tmp/results 2> /tmp/results

тогда

$ cat /tmp/results
grep: NOT_A_FILE: No such file or directory
 lazy dog

что здесь случилось?
Насколько я понимаю, bash настраивает перенаправление, указывающее STDERR непосредственно на файл, /tmp/resultsи из-за характера, >который делает 2 вещи

  1. обычно создайте новый файл - в этом случае возможность прошла, поскольку bash прошел эту процедуру во время генерации вывода.
  2. вставьте прямо в начало файла. и не дописывать, как >>делает.

Таким образом, в этом случае STDERR вставляет непосредственно в начало /tmp/resultsпереопределения вывода STDOUT.
Примечание: если вы использовали >>для добавления, вы, вероятно, могли бы сойти с этого синтаксиса.
Однако, чтобы решить проблему, вам нужно - не перенаправлять STDERR - непосредственно в файл, а объединить вывод STDERR в поток STDOUT, чтобы избежать коллизии.
Использование оператора 2>&1оператор достигает этого

grep "brown" poem.txt NOT_A_FILE > /tmp/results 2>&1

&Позволяет Баш отличить от файла с именем 1и 1дескриптор файла.
Для меня само утверждение 2>&1точно объясняет, что происходит - STDERR перенаправляется на сам STDOUT - и заканчивается только /tmp/resultsпотому, что именно на него указывает STDOUT (почти как побочный эффект).
В отличие от того, что утверждают многие из руководств, то есть 2>&1отправляет STDERR туда, куда направлен STDOUT. Если бы это было правдой - у вас все равно была бы проблема с перезаписью.

Для получения дополнительной информации см. Http://mywiki.wooledge.org/BashGuide/InputAndOutput#File_Redirection.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.