В чем разница между `>> / dev / stderr` (с пробелом) и`> & 2`?

11

В баш.

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

все мои скрипты используют ">> / dev / stderr"

при bash подскажите, если попробую:
echo test >>/dev/stderrработает
echo test >> /dev/stderrработает
echo test >/dev/stderrработает
echo test > /dev/stderrработает

echo test >>&2FAILS!
echo test >> &2FAILS!
echo test >&2работает
echo test > &2FAILS!

Я готов изменить все свои сценарии на >&2.

Похоже, что он также имеет большое влияние на ssh (после su SomeUser), где >>/dev/stderrне будет работать вообще (разрешение запрещено), только >&2будет работать.

Водолей Сила
источник
можете показать пример ошибки ssh? Я не могу воспроизвести это.
Джефф Шаллер
@JeffSchaller вы правы, это только после suтого, как проблема возникает, обновил вопрос
Водолей Power
@AquariusPower, ... чтобы объяснить это несоответствие, между прочим: при том su -c 'some command', что эта команда выполняется /bin/sh, а не bashтак, поэтому /dev/stderrне гарантируется наличие специфического для bash поведения (такого как моделирование для целей перенаправления, когда оно недоступно).
Чарльз Даффи

Ответы:

22

>& nэто оболочка синтаксис непосредственно дублировать дескриптор файла . Файловый дескриптор 2 является stderr; Вот как это работает. Вы можете дублировать и другие файловые дескрипторы, а не только stderr. Вы не можете использовать режим добавления здесь, потому что дублирование файлового дескриптора никогда не усекается (даже если ваш stderr является файлом) и >&является одним токеном, поэтому вы не можете поместить в него пробел - но >& 2работает.

>> nameдругой допустимый синтаксис, где nameимя файла (и токен >>). В этом случае вы используете имя файла /dev/stderr, которое в зависимости от ОС (в Linux это символическая ссылка /proc/self/fd/2) также означает стандартную ошибку. Режим добавления и усечения завершают работу, когда stderr является терминалом, потому что это не может быть усечено. Если ваша стандартная ошибка - файл, он будет усечен:

anthony@Zia:~$ bash -c 'echo hi >/dev/stderr; echo bye >/dev/stderr' 2>/tmp/foo
anthony@Zia:~$ cat /tmp/foo
bye

Если вы видите ошибку с /dev/stderrover ssh, возможно, администратор сервера применил некоторые меры безопасности, предотвращающие работу этой символической ссылки. (Например, вы не можете получить доступ /procили /dev). Хотя я ожидаю, что любой из них вызовет все виды странных поломок, использование синтаксиса дубликатов файловых дескрипторов является вполне разумным (и, вероятно, немного более эффективным) подходом. Лично я предпочитаю это.

derobert
источник
У меня были большие проблемы при попытке воспроизвести ту проблему усечения, которая у меня была раньше (в противном случае я бы добавил это к вопросу хе-хе), причина, по которой я изменил все, что использовал >>, спасибо за указание на это! Кроме того, я пропустил шаг su SomeUserпосле подключения через SSH.
Водолей Сила
это не bash -c 'echo hi >&2; echo bye >&2' 2>/tmp/foo;cat /tmp/fooусечет! (даже с 2>&1 |tee /tmp/foo), что идеально подходит для регистрации, и будет отлично работать после того, как я все это изменить >&2. Так что я думаю, что только прямое использование файла /dev/stderrпозволяет усекать, а не дублировать дескриптор, круто, спасибо!
Водолей Power
@AquariusPower правильный, дубликат файлового дескриптора никогда не усекается. Это в первом абзаце, может быть, мне нужно как-то выделить это?
Дероберт
не нужен, иногда я медленный, хе-хе
Водолей Сила
3
Этот ответ может быть улучшен. > & - это один знак, а не два, и в этом ложь ОП.
Джошуа
8

Случаи сбоев возникают из-за того, что синтаксис bash для использования &в перенаправлениях определяет один >и требует, чтобы он существовал непосредственно рядом со &знаком:

[П]> & слово

Джефф Шаллер
источник
2

Используйте '>'для перенаправления (усечения, если существует) или '>>'(добавляет, если существует).

Используйте '>&'для дублирования потока, например, если вы хотите, чтобы стандартный вывод И стандартная ошибка в одном и том же файле, вы перенаправляете в файл, '> output.log'а также ошибка с'2>&'

myjob.sh > output.log 2>&
Хосе Мануэль Гомес Альварес
источник