stderr로 출력하는 에코


1115

에코처럼 작동하지만 stdout이 아닌 stderr로 출력되는 표준 Bash 도구가 있습니까?

나는 할 수 있다는 것을 알고 echo foo 1>&2있지만 그것은 추악하고 오류가 발생하기 쉽다고 생각합니다 (예 : 상황이 바뀌면 잘못 편집 될 가능성이 높습니다).


답변:


1452

이렇게하면 읽을 수 있습니다.

>&2 echo "error"

>&2파일 디스크립터 # 2를 파일 디스크립터 # 1에 복사합니다. 따라서이 경로 재 지정이 수행 된 후 두 파일 디스크립터는 동일한 파일을 참조합니다. 하나의 파일 디스크립터 # 2는 원래 참조했습니다. 자세한 내용은 Bash Hackers Illustrated Redirection Tutorial을 참조하십시오 .


2
나는이 트릭을 꽤 오래 전에 배웠다. 이 페이지에는 좋은 정보가 있습니다. tldp.org/LDP/abs/html/io-redirection.html
Marco Aurelio

46
@BCS 나는 alias쉘 스크립트를 사용하는 것에 대해 몰랐다 . 아마 사용하는 것이 더 안전 할 것errcho(){ >&2 echo $@; }
브레이든 최저

3
> & 2는 일반적으로 끝에 있습니다. 이것은 작동하지만 덜 자주 사용됩니다
Iskren Ivov Chernev

159
거의 40 년 동안 유닉스 계열 시스템을 사용해 왔지만 결국 어디에서나 리디렉션을 할 수있는 일은 결코 없었습니다. 이렇게 앞쪽에 놓으면 훨씬 더 분명해집니다 (@MarcoAurelio가 말한 것처럼 "읽기 용이"). 새로운 것을 가르쳐 주신 +1
Hephaestus

참고 사항 : 단순히 문자열을 에코하는 것 외에도 형식을 지정하거나 다른 작업을 수행하려면 리디렉션을 끝으로 다시 이동해야합니다. 예를 들어 errcho(){ >&2 echo $@|pr -To5;}작동하지 않습니다. 이와 같은 작업을 수행하려면 마지막 파이프 다음에 어딘가에 리디렉션을 배치해야합니다.errcho(){ echo $@|>&2 pr -To5;}
Jon Red

423

함수를 정의 할 수 있습니다 :

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

이것은 스크립트보다 빠르며 종속성이 없습니다.

Camilo Martin의 bash 특정 제안은 "here string"을 사용하며 echo가 정상적으로 삼키는 인수 (-n)를 포함하여 전달하는 모든 것을 인쇄합니다.

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

Glenn Jackman의 솔루션은 또한 논쟁 삼키는 문제를 피합니다.

echoerr() { printf "%s\n" "$*" >&2; }

7
에코는 다소 신뢰할 수 없다고 말해야합니다. echoerr -ne xt"-ne xt"를 인쇄하지 않습니다. 더 잘 사용하십시오 printf.
Camilo Martin

10
오, 당신은 실제로 고양이도 사용할 수 있습니다 :echoerr() { cat <<< "$@" 1>&2; }
Camilo Martin

2
나는 그것을 몰랐다. 추가되었습니다.
James Roth

4
또는printf "%s\n" "$*" >&2
glenn jackman 16:13에

4
@GKFX 물론 인용 할 때만 제대로 작동합니다. 사람들이 자신의 줄을 인용하지 않는 이유는 저 너머입니다. (당신이 인용하지 않을 때, 모든 것이 하나로 구분 이상 $IFS의 경우 별도의 인수로 전송됩니다 공백 echo으로 그들을을 연결 수단 0x20의 만 입력이 개 적은 문자까지 outweight 편의를 인용하지의 위험) .
Camilo Martin

252

1표준 출력 이므로 출력 리디렉션 앞에 명시 적으로 이름을 지정할 필요는 >없지만 대신 다음 과 같이 입력 할 수 있습니다.

echo이 메시지는 stderr> & 2로 이동합니다

1>&2신뢰할 수있는 타이핑이 어려워 질 까봐 걱정되는 것처럼 보이므로 중복을 제거 1하는 것은 약간의 격려가 될 수 있습니다!


59

다른 옵션

echo foo >>/dev/stderr

4
이 옵션은 휴대용입니까? 이것이 유닉스 맛에 효과가 없는지 누군가 알고 있습니까?
Dacav

7
/ dev / stderr에 액세스 할 수없는 특정 chroot에서는 작동하지 않습니다.
Zachary Vance

12
이 줄을 실행하는 스크립트가 호출 되면 foo-자체 stderr가 리디렉션 된 경우-예를 들어 foo >foo.log 2>&1-그 echo foo >/dev/stderr전에 모든 출력을 클로버합니다. >>대신 사용해야합니다.echo foo >>/dev/stderr
doshea

마찬가지로 /dev/fd/2.
jbruni

@Dacav 이것은 확실히 휴대용입니다 : /proc/self/fd/2. 아래 내 대답을 참조하십시오 :)
Sebastian

31

아니요, 표준 방법입니다. 오류가 발생하지 않아야합니다.


9
그것은 오류가 발생하지 않아야하지만 가능성을 수 있습니다. OTOH 그렇게 큰 문제는 아닙니다.
BCS

6
@ Mike DeSimone : 다른 사람이 코드를 엉망으로 만들고 출력을 뒤섞으며 실제로 bash를 알지 못하면 쉽게을 떨어 뜨릴 수 있습니다 1>&2. 우리는 이것이 일어나지 않기를 희망하지만, 우리 모두가 그 장소에 있었을 것이라고 확신합니다.
Cascabel

2
( echo something 1>&2 ; something else ) > log-> (echo something; cp some junk 1>&2 ; something else) > log죄송합니다.
BCS

29
IMHO, 누군가가 코드를 엉망으로 만들고 bash를 모른다면 이것이 가장 작은 문제 일 수 있습니다.
Mike DeSimone 2016 년

7
그것이 문제가 될 가능성이 있다고 생각되면 다른 언어를 사용해야합니다.
직관

17

메시지를 syslog에도 기록하지 않아도되는 경우 not_so_ugly 방법은 다음과 같습니다.

logger -s $msg

-s 옵션은 "메시지를 표준 오류 및 시스템 로그에 출력합니다"를 의미합니다.


1
대단해! 얼마나 휴대 할 수 있습니까?
code_monk

@code_monk : 로거 명령은 IEEE 표준은 로거 명령 ( "POSIX.2") 호환 폴더의 유틸리티 - 리눅스 패키지의 일부이며 리눅스 커널 아카이브 ⟨에서 사용할 1003.2 것으로 예상된다 kernel.org/pub/linux/utils / util- linux⟩.
miku

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

2
나는 당신이 별칭으로 같은 일을 할 수 있고 훨씬 더 컴팩트해질 수 있다고 생각합니다
BCS

또는 장치 파일로 직접 파이프 할 수 있습니다 echo what | /dev/stderr.
ardnew

11

참고 : 나는 오해의 소지가 있거나 모호한 "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의 우려를 처리하는 이유 :

  • 가장 좋은 구문 가능 (못생긴 기호 대신 의미있는 단어)
  • 오류를 만들기가 더 어렵습니다 (특히 스크립트를 재사용하는 경우)
  • 표준 Bash 도구는 아니지만 사용자 또는 회사 / 조직의 표준 셸 라이브러리 일 수 있습니다.

다른 이유들:

  • 명확성-다른 관리자에게 의도를 보여줍니다
  • 속도-함수는 쉘 스크립트보다 빠릅니다
  • 재사용 성-함수가 다른 함수를 호출 할 수 있음
  • 구성 성-원본 스크립트를 편집 할 필요가 없습니다
  • 디버깅-오류를 일으키는 라인을 쉽게 찾을 수 있습니다 (특히 리디렉션 / 필터링 톤이 많은 데드 링을하는 경우)
  • 견고성-함수가 누락되어 스크립트를 편집 할 수없는 경우 동일한 이름의 외부 도구를 사용하는 것으로 대체 할 수 있습니다 (예 : Linux에서 log_error는 로거에 별명을 지정할 수 있음)
  • 스위칭 구현-라이브러리의 "x"속성을 제거하여 외부 도구로 전환 할 수 있습니다
  • 출력에 구애받지 않음-STDERR 또는 다른 곳으로가더라도 더 이상 신경 쓸 필요가 없습니다.
  • 개인화-환경 변수로 동작을 구성 할 수 있습니다

10

나의 제안:

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

또는

echo "my errz" >> /dev/stderr

echo "my errz" > /proc/self/fd/2것이다 효율적으로 출력 stderr하기 때문에 /proc/self현재 프로세스에 대한 링크이며, /proc/self/fd공정 열린 파일 기술자를 보유하고, 0, 1,와 2약자 stdin, stdout그리고 stderr각각.

/proc/self링크가 맥 OS에서 작동하지 않습니다, 그러나, /proc/self/fd/*안드로이드에 Termux 볼 수 있지만 /dev/stderr. Bash 스크립트에서 OS를 감지하는 방법은 무엇입니까? 사용할 변형을 결정하여 스크립트를보다 이식성있게 만들어야하는 경우 도움이 될 수 있습니다.


5
/proc/self링크는 MacOS에서는 작동하지 않으므로 더 간단한 /dev/stderr방법을 사용 하겠습니다 . 또한 다른 답변 / 의견에서 언급했듯이 >>추가하는 데 사용 하는 것이 좋습니다 .
MarkHu

4
/proc/self/fd/*Android의 Termux에서는 사용할 수 있지만에서는 사용할 수 없습니다 /dev/stderr.
go2null

9

cat여기에 언급 된대로 사용하지 마십시오 . catA는 프로그램 상태 echoprintf(쉘) 내장 매크로 배시이다. 프로그램 또는 다른 스크립트 (위에서 언급 한)를 시작하면 모든 비용으로 새로운 프로세스를 생성 할 수 있습니다. 내장 기능을 사용하면 프로세스 (환경)를 생성 (실행) 할 필요가 없으므로 쓰기 기능이 상당히 저렴합니다.

opner는 "표준 파이프 에 stderr 로 출력하는 표준 도구가 있습니까?"라고 묻습니다. ... rediredcting pipe는 유닉스 (Linux ...)와 bash (sh)와 같은 시스템에서 이러한 개념을 기반으로하는 필수 개념입니다.

나는 이와 같은 표기법으로 리디렉션하는 &2>1것이 현대 프로그래머에게는 그리 즐겁지는 않지만 오프닝이라는 것에 동의합니다 . Bash는 거대하고 강력한 프로그램을 작성하기위한 것이 아니며 관리자가 적은 키 누름으로 작업하도록 도와줍니다. ;-)

그리고 최소한 라인의 어느 곳에 나 리디렉션을 배치 할 수 있습니다.

$ echo This message >&2 goes to stderr 
This message goes to stderr

1
성능상의 이유로 프로그램을 사용하지 말라고 개발자에게 알리는 것은 조기 최적화입니다. 이해하기 어려운 코드보다 밀리 초 단위로 더 우수하고 이해하기 쉬운 접근 방식이 선호되어야합니다.
GuyPaddock

@GuyPaddock 죄송합니다.이 글을 제대로 읽지 못했습니다. 전나무; bash가 잘 처리하는 파이프를 리디렉션하는 것에 관한 것입니다. bash가 어떻게 리디렉션되는지 (추악한) 구문이 마음에 들지 않으면 bash 스크립트 구현을 중단하거나 bash 방법을 배워야합니다. 둘째; bash 내장을 호출하는 것과 비교하여 새로운 prozess를 시작하는 것이 얼마나 비쌉니다.
return42

1
누군가에게 Bash 빌트인의 성능 트레이드 오프를 알리는 cat것과 고양이가 느리기 때문에 고양이를 사용하지 않도록 지시 하는 것에는 차이가 있습니다 . cat이 올바른 선택 인 수많은 유스 케이스가 있으므로 이것이 귀하의 답변에 반대하는 이유입니다.
GuyPaddock 2019

@GuyPaddock 오프너가 echo교체를 요청했습니다 . 을 사용하더라도 catbash 리디렉션을 사용해야합니다. 어쨌든. 따라서 cat여기서 사용하는 것은 전혀 의미가 없습니다 . BTW 나는 cat하루에 100 번 사용 하지만 오프너가 요구 한 상황에서는 결코 ... 당신이 그것을 얻었습니까?
return42

8

내가 최근에 우연히 발견 한 다른 옵션은 다음과 같습니다.

    {
        echo "First error line"
        echo "Second error line"
        echo "Third error line"
    } >&2

이것은 &>2모든 라인 에 추가 할 필요가 없기 때문에 다중 라인 오류 출력이 오류 발생을 줄이면서 Bash 내장 기능 만 사용합니다 .


1
믿을 수 없어, bash-redirect를 사용하고 bash-redirect를 사용하는 것이 좋습니다.
return42

1
@ return42 귀하의 답변을 표결했습니다. OP가 시작한 것보다 더 나은 답변이 없다고 OP에게 알리기 때문입니다. 실제로 답변이 아닙니다. 또한 귀하의 답변에 하위 셸 제안이 표시되지 않습니다 ... 귀하의 답변은 OP를 사용하지 말거나 cat다른 유틸리티 를 사용하지 말라고 조언합니다 .
GuyPaddock


6

read stderr에 인쇄하는 쉘 내장 명령이며 리디렉션 트릭을 수행하지 않고 echo처럼 사용할 수 있습니다.

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

-t 0.1비활성화는 표준 입력 변수로 한 줄 저장의 기본 기능을 판독하는 시간 제한이다.


5
OS X의 Bash는 "0.1"을 허용하지 않습니다
James Roth

2

스크립트 만들기

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

그것이 당신의 도구 일 것입니다.

또는 별도의 파일에 스크립트를 원하지 않으면 기능을 수행하십시오.


6
James Roth의 답변과 같은 함수가되는 것이 더 좋으며 첫 번째뿐만 아니라 모든 인수를 전달하는 것이 좋습니다.
Cascabel

2
왜 기능이 더 좋을까요? (또는 대안으로 : "왜 더 나은지 설명하는 것이 더 낫다 ...")
Ogre Psalm33

3
@ OgrePsalm33 함수가 더 좋은 이유 중 하나는 스크립트를 호출 할 때 스크립트를 실행할 환경을 제공하기 위해 일반적으로 새 셸 인스턴스가 만들어지기 때문입니다. 반면에 기능은 현재 실행중인 쉘 환경에 배치됩니다. 이 경우 함수를 호출하는 것이 쉘의 다른 인스턴스 작성을 피할 수 있으므로 훨씬 효율적인 조작입니다.
스텐슨

-10

Mac OS X : 허용되는 답변과 몇 가지 다른 답변을 시도했는데 모두 Mac에서 STDERR이 아닌 STDOUT을 작성했습니다.

Perl을 사용하여 표준 오류에 쓸 수있는 이식 가능한 방법은 다음과 같습니다.

echo WARNING! | perl -ne 'print STDERR'

lol downvote 당신이 원하는 모든 것이지만 이것은 실제로 내 코드에서 사용하는 솔루션입니다!
노아 서스 먼
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.