эхо, которое выводит на stderr

666

Есть ли стандартный инструмент Bash, который действует как эхо, но выводит на stderr, а не на stdout?

Я знаю, что могу сделать echo foo 1>&2, но это довольно уродливо и, я подозреваю, склонность к ошибкам (например, с большей вероятностью будет отредактировано неправильно, когда ситуация изменится).

  • 0
    Похожие страницы : stackoverflow.com/a/12704488/194894
  • 3
    почему нет, echo "foo" > /dev/stderr ? Или echo "foo" >&2 ? То же самое, я думаю.
Показать ещё 1 комментарий
Теги:

13 ответов

791
Лучший ответ

Этот вопрос старый, но вы можете сделать это, что облегчает чтение:

>&2 echo "error"

Оператор >&2 буквально означает перенаправление адреса дескриптора файла 1 (stdout) на адрес файлового дескриптора 2 (stderr) для этой команды 1. В зависимости от того, насколько глубоко вы хотите это понять, прочтите следующее: http://wiki.bash-hackers.org/howto/redirection_tutorial

Чтобы избежать взаимодействия с другими перенаправлениями, используйте subshell

(>&2 echo "error")

1>&2 копирует дескриптор файла №2 в дескриптор файла # 1. Поэтому после выполнения этого перенаправления оба файловых дескриптора будут ссылаться на один и тот же файл: дескриптор 1 одного файла был изначально, ссылаясь на.

  • 171
    alias errcho='>&2 echo'
  • 0
    Я изучил этот трюк довольно давно. Эта страница содержит полезную информацию. tldp.org/LDP/abs/html/io-redirection.html
Показать ещё 16 комментариев
345

Вы можете определить функцию:

echoerr() { echo "$@" 1>&2; }
echoerr hello world

Это будет быстрее, чем script и не имеет зависимостей.

Камило Мартин bash конкретное предложение использует "здесь строку" и будет печатать все, что вы передаете ему, включая аргументы (-n), которые эхо обычно проглатывало:

echoerr() { cat <<< "$@" 1>&2; }

Решение Гленна Джекмана также позволяет избежать проблемы с глотанием аргумента:

echoerr() { printf "%s\n" "$*" >&2; }
  • 6
    Я должен сказать, что эхо вроде ненадежно. echoerr -ne xt не собирается печатать "-ne xt". Лучше использовать printf для этого.
  • 9
    О, вы тоже можете использовать cat: echoerr() { cat <<< "$@" 1>&2; }
Показать ещё 10 комментариев
195

Так как 1 - стандартный вывод, вам не нужно явно указывать его перед перенаправлением вывода, например >, но вместо этого можно просто ввести:

echo This message goes to stderr >&2

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

  • 1
    Я больше думал о том, чтобы потерять или отделиться от суффикса все вместе в некоторой неудачной копировальной вставке.
  • 0
    Будет ли лучше использовать форму echo >&2 some message или echo >&2 "some message" ?
Показать ещё 2 комментария
30

Другой вариант

echo foo >>/dev/stderr
  • 2
    Эта опция переносная? Кто-нибудь знает, если это не работает для какого-то вкуса Unix?
  • 5
    Это не работает в определенных chroot, которые не могут получить доступ к / dev / stderr.
Показать ещё 4 комментария
28

Нет, это стандартный способ сделать это. Это не должно вызывать ошибок.

  • 7
    Это не должно вызывать ошибок, но я мог бы с большей вероятностью. ОТО, это не так уж важно.
  • 1
    Единственный способ завершиться неудачей - это если идентификатор файла для stdout не равен 1 или идентификатор файла для stderr не равен 2. Так как эти константы определены в POSIX.1, что, я считаю, является необходимым условием для построения bash, это будет работать на обозримое будущее. Таким образом, мне любопытно, что вы подразумеваете под «вероятностью неправильного редактирования, когда что-то изменится». У вас есть похожая проблема с людьми, меняющими слово «эхо» на что-то другое?
Показать ещё 4 комментария
12

Это простая функция STDERR, которая перенаправляет входной канал в STDERR.

#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {

cat - 1>&2

}

# remove the directory /bubu
if rm /bubu 2>/dev/null; then
    echo "Bubu is gone."
else
    echo "Has anyone seen Bubu?" | STDERR
fi


# run the bubu.sh and redirect you output
tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err
  • 1
    Я думаю, что вы можете сделать то же самое с псевдонимом и быть гораздо более компактным
9

Не используйте cat, поскольку некоторые из них упоминаются здесь. cat - это программа а echo и printf - это встроенные функции bash (shell). Запуск программы или другого script (также упоминалось выше) означает создание нового процесса со всеми его затратами. Использование встроенных функций записи довольно дешево, потому что нет необходимости создавать (выполнять) процесс (-environment).

Опнер спрашивает: "Есть ли какой-либо стандартный инструмент для вывода (pipe) в stderr", ответ schort: NO... почему?... rediredcting pipes - это концептуальная концепция в таких системах, как unix (Linux...) и bash (sh), которая основывается на этих концепциях.

Я согласен с разработчиком в том, что перенаправление с такими обозначениями: &2>1 для современных программистов не очень приятен, но это bash. bash не предназначался для создания огромных и надежных программ, он призван помочь администраторам работать с меньшими нажатиями клавиш; -)

И, по крайней мере, вы можете поместить перенаправление в любом месте строки:

$ echo This message >&2 goes to stderr 
This message goes to stderr
  • 0
    Указывать разработчикам не использовать программы только по причине производительности - преждевременная оптимизация. Элегантные, простые в использовании подходы должны быть предпочтительнее трудного для понимания кода, который работает лучше (порядка миллисекунд).
  • 0
    @GuyPaddock извините, вы не прочитали это должным образом. Елки; Речь идет о перенаправлении труб, которые хорошо обрабатываются Bash. Если кому-то не нравится (уродливый) синтаксис перенаправления bash, ему следует прекратить реализацию сценариев bash или изучить способ bash. Во-вторых, Вы должны знать, как дорого запускать новый процесс по сравнению с вызовом встроенной функции bash.
Показать ещё 2 комментария
8

Если вы не имеете права записывать сообщение также в syslog, путь not_so_ugly следующий:

logger -s $msg

Опция -s означает: "Вывести сообщение на стандартную ошибку, а также на системный журнал".

  • 0
    это замечательно! насколько это портативно?
6

Примечание. Я отвечаю на пост-не вводящее в заблуждение/неопределенное "эхо, которое выводит на stderr" (уже ответил OP).

Используйте функцию, чтобы показать намерение и укажите нужную реализацию. Например.

#!/bin/bash

[ -x error_handling ] && . error_handling

filename="foobar.txt"
config_error $filename "invalid value!"

output_xml_error "No such account"

debug_output "Skipping cache"

log_error "Timeout downloading archive"

notify_admin "Out of disk space!"

fatal "failed to open logger!"

И error_handling:

ADMIN_EMAIL=root@localhost

config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }

output_xml_error() { echo "<error>$*</error>" 2>&1; }

debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }

log_error() { logger -s "$*"; }

fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }

notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }

Причины, которые обрабатывают проблемы в OP:

  • Самый красивый синтаксис (значимые слова вместо уродливых символов)
  • сложнее сделать ошибку (особенно если вы повторно используете script)
  • это не стандартный инструмент Bash, но он может быть стандартной библиотекой оболочки для вас или вашей компании/организации.

Другие причины:

  • Ясность - показывает намерение другим сопровождающим
  • скорость - функции быстрее, чем shell-скрипты
  • reusability - функция может вызывать другую функцию
  • Конфигурируемость - нет необходимости редактировать оригинал script
  • отладка - проще найти строку, ответственную за ошибку (особенно, если вы пытаетесь выполнить тонну перенаправления/фильтрации)
  • надежность - если функция отсутствует, и вы не можете отредактировать script, вы можете вернуться к использованию внешнего инструмента с тем же именем (например, log_error может быть псевдонимом для регистрации в Linux)
  • переключения - вы можете переключиться на внешние инструменты, удалив атрибут "x" библиотеки
  • output agnostic - вам больше не нужно заботиться, попадает ли он в STDERR или где-либо еще.
  • персонализация - вы можете настроить поведение с переменными среды
3

read - это встроенная команда оболочки, которая печатает на stderr и может использоваться как эхо без выполнения трюков перенаправления:

read -t 0.1 -p "This will be sent to stderr"

-t 0.1 - это таймаут, который отключает чтение основных функций, сохраняя одну строку stdin в переменной.

  • 3
    Bash на OS X не позволяет "0.1"
3

Сделайте script

#!/bin/sh
echo $* 1>&2

который будет вашим инструментом.

Или создайте функцию, если вы не хотите иметь script в отдельном файле.

  • 5
    Лучше, чтобы это была функция (как ответ Джеймса Рота), и лучше передавать все аргументы, а не только первые.
  • 2
    Почему функция будет лучше? (Или, альтернативно: «Лучше объяснить, почему так будет лучше ...»)
Показать ещё 1 комментарий
1

Об этом уже ответили и много голосов. Только для записи:

echo "my errz" > /proc/self/fd/2

будет эффективно выводиться на stderr. Объяснение: /proc/self - это ссылка на текущий процесс, а /proc/self/fd содержит дескрипторы открытых файлов процесса. Затем 0, 1 и 2 означают stdin, stdout и stderr соответственно.

Я нашел его более читаемым. Также это может работать в большинстве дистрибутивов Linux:

echo "my errz" > /dev/stderr

Сделать его более читаемым.

  • 1
    Ссылка /proc/self не работает на MacOS, поэтому я остановлюсь на более прямолинейном методе /dev/stderr . Также, как отмечено в других ответах / комментариях, вероятно, лучше использовать >> для добавления.
  • 3
    /proc/self/fd/* доступен в Termux для Android, но не /dev/stderr .
-5

Mac OS X: Я попробовал принятый ответ и пару других ответов, и все они привели к написанию STDOUT, а не STDERR на моем Mac.

Вот переносимый способ записи стандартной ошибки с использованием Perl:

echo WARNING! | perl -ne 'print STDERR'
  • 0
    LOL Downvote все, что вы хотите, но это решение, которое я на самом деле использую в своем коде!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню