bash : stderr를 붉은 색으로 인쇄


122

bash 디스플레이 stderr 메시지를 붉은 색 으로 만드는 방법이 있습니까?


4
bash는 출력을 채색하지 않을 것이라고 생각합니다. 일부 프로그램은 무언가를 구문 분석하려고 할 수 있으며 채색하면 이스케이프 된 시퀀스로 데이터가 손상됩니다. GUI 응용 프로그램은 색상을 처리해야합니다.
kolypto

Balázs Pozsár와 killdash9 답변을 결합하면 선명하고 function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') } bash와 zsh에 효과적 입니다. 이것을 b / c 평판의 대답으로 추가 할 수 없습니다.
Heinrich Hartmann

1
이 작업을 수행하기 위해 bash를 수정하는 답변을 기다리고 있습니다. 아래의 모든 솔루션은 실제로 stderr을 수정하고 strtout을 재정렬하여 가능하면 stderr의 정확한 바이트 시퀀스를 유지해야 할 때 예를 들어 배관 할 때 문제가 발생합니다.
masterxilo

답변:


98
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)

6
큰! 그러나 나는 그것을 영구적으로 만드는 방법이 있는지 궁금합니다 :)
kolypto

9
좋은 팁! 제안 : >&2직전에 추가하면 ; done)stderr에 대한 출력이 실제로 stderr에 기록됩니다. 프로그램의 일반 출력을 캡처하려는 경우에 유용합니다.
henko

8
다음 tputcommand 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done)
은를 사용

2
각 출력 라인에 대해 2 개의 입력 프로세스를 실행하는 것이 전혀 우아하지 않다고 생각합니다. 아마도 tput 명령의 출력을 변수에 저장하고 각 에코에 사용합니다. 그러나 다시, 가독성은 실제로 더 좋지 않습니다.
Baláss Pozsár

1
이 솔루션은 공백을 보존하지 않지만 간결성을 위해 좋아합니다. IFS= read -r line도움이되지만 그렇지 않습니다. 이유가 확실하지 않습니다.
맥스 머피

89

방법 1 : 프로세스 대체 사용 :

command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)

방법 2 : bash 스크립트에서 함수를 작성하십시오.

color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1

다음과 같이 사용하십시오.

$ color command

두 방법 모두 명령 stderr을 빨간색으로 표시합니다 .

방법 2의 작동 방식에 대한 설명은 계속 읽으십시오. 이 명령으로 보여주는 몇 가지 흥미로운 기능이 있습니다.

  • color()... — color라는 bash 함수를 만듭니다.
  • set -o pipefail— 이것은 출력이 다른 명령으로 파이프되는 명령의 오류 리턴 코드를 유지하는 쉘 옵션입니다. 이것은 외부 쉘에서 pipefail 옵션을 변경하지 않도록 괄호로 작성된 서브 쉘에서 수행됩니다.
  • "$@"— 함수에 대한 인수를 새 명령으로 실행합니다. "$@"에 해당"$1" "$2" ...
  • 2>&1- 리디렉션 stderr에 명령을 stdout가되도록 sedstdin.
  • >&3— 축약 형으로 1>&3, stdout새로운 임시 파일 디스크립터로 리디렉션 됩니다 3. 나중에 3다시 라우팅됩니다 stdout.
  • sed ...- 위의 리디렉션 때문에 sed'들 stdin은 IS stderr실행 된 명령. 그 기능은 각 라인을 컬러 코드로 둘러싸는 것입니다.
  • $'...' 백 슬래시로 이스케이프 된 문자를 이해하도록하는 bash 구성
  • .* — 전체 줄과 일치합니다.
  • \e[31m — 다음 문자가 빨간색이되도록하는 ANSI 이스케이프 시퀀스
  • &sed일치하는 전체 문자열 (이 경우 전체 줄)로 확장 되는 대체 문자입니다.
  • \e[m — 색상을 재설정하는 ANSI 이스케이프 시퀀스.
  • >&2- 대한 속기 1>&2이 리디렉션 sed의가 stdoutstderr.
  • 3>&1— 임시 파일 디스크립터를 3로 리디렉션합니다 stdout.

9
최고의 답변 +1! 절대적으로 과소 평가되었습니다!
muhqu

3
훌륭한 답변과 더 나은 설명
Daniel Serodio

추가 리디렉션을 모두 수행해야하는 이유는 무엇입니까? 과잉 것 같습니다
qodeninja

1
작동시키는 방법이 zsh있습니까?
Eyal Levin

1
ZSH는 속기 리디렉션 양식을 인식하지 못합니다. 2 개만 더 zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m,'1>&2)3>&1
있으면됩니다

26

stderred를 확인할 수도 있습니다 : https://github.com/sickill/stderred


와우,이 유틸리티는 훌륭합니다. 필요한 유일한 것은 모든 사용자를 위해 설치하는 적절한 저장소를 가지고 한 줄로 더 많은 작업을 수행 할 필요가 없습니다.
sorin

별도의 터미널에서 빌드 스크립트를 사용하여 테스트했을 때 제대로 작동하는 것처럼 보였지만 전역에서 (in .bashrc) 사용하는 것이 주저합니다 . 그래도 고마워!
Joel Purra

2
OS X El Capitan에서는 이것이 작동하는 방식 (DYLD_INSERT_LIBRARIES)이 SIP로 보호되기 때문에 시스템 바이너리에서 "파손"됩니다. 따라서 다른 답변에 제공된 bash 옵션을 사용하는 것이 좋습니다.
hmijail

1
맥 OS가 따르십시오에 대한 @hmijail는 github.com/sickill/stderred/issues/60 그래서 우리는 해결 방법을 찾을 수 있습니다, 부분 중 하나는 이미 존재하지만 약간의 버그입니다.
sorin

15

stderr를 영구적으로 빨간색 으로 만드는 bash 방법은 'exec'를 사용하여 스트림을 리디렉션합니다. bashrc에 다음을 추가하십시오.

exec 9>&2
exec 8> >(
    while IFS='' read -r line || [ -n "$line" ]; do
       echo -e "\033[31m${line}\033[0m"
    done
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'

나는 이것을 이전에 게시했다 : STDOUT 및 STDERR의 글꼴 색상을 설정하는 방법



1
이것은 가장 좋은 답변입니다. 설치 / 필요한 sudo 권한없이 쉽게 구현할 수 있으며 모든 명령에 일반화 할 수 있습니다.
Luke Davis

1
불행히도 이것은 명령 체인 (명령 && nextCommand || errorHandlerCommand)에서 잘 작동하지 않습니다. 오류 출력은 errorHandlerCommand 출력 뒤에옵니다.
carlin.scott

1
마찬가지로, 이것을 source ~/.bashrc두 번 사용하면 터미널이 기본적으로 잠 깁니다.
Dolph

@ Dolf : 내 bashrc 에서이 코드를 다시로드하지 못하게하는 주변 if 문으로 이것을 쉽게 보호합니다. 그렇지 않으면 문제는 리디렉션이 이미 발생한 후 리디렉션 'exec 9> & 2'입니다. > 2가 원래 가리키는 위치를 알고 있다면 상수로 변경하십시오.
gospes


7

순수한 배쉬로 Balázs Pozsár의 답변을 구현하는 래퍼 스크립트를 만들었습니다. $ PATH 및 접두사 명령에 저장하여 출력을 채색하십시오.

    #! / bin / bash

    만약 [$ 1 == "--help"]; 그때
        echo "명령을 실행하고 발생한 모든 오류를 채색합니다"
        echo "예 :`basename $ {0}`wget ..."
        echo "(c) o_O Tync, ICQ # 1227-700, 즐기십시오!"
        출구 0
        fi

    # 모든 오류를 포착하는 임시 파일
    TMP_ERRS = $ (mktemp)

    # 실행 명령
    "$ @"2>> (행을 읽는 동안 echo -e "\ e [01; 31m $ line \ e [0m"| tee --append $ TMP_ERRS; done)
    EXIT_CODE = $?

    # 모든 오류를 다시 표시
    [-s "$ TMP_ERRS"] 인 경우; 그때
        echo -e "\ n \ n \ n \ e [01; 31m === 오류 === \ e [0m"
        고양이 $ TMP_ERRS
        fi
    rm -f $ TMP_ERRS

    # 마무리
    $ EXIT_CODE 종료


2
"완료"뒤에 "| tee ..."를 넣으면보다 효율적으로 만들 수 있습니다.
Juliano

3

이런 기능을 사용할 수 있습니다


 #!/bin/sh

color() {
      printf '\033[%sm%s\033[m\n' "$@"
      # usage color "31;5" "string"
      # 0 default
      # 5 blink, 1 strong, 4 underlined
      # fg: 31 red,  32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
      # bg: 40 black, 41 red, 44 blue, 45 purple
      }
string="Hello world!"
color '31;1' "$string" >&2

stderr에 인쇄하기 위해> & 2를 추가합니다.


4
문제를 해결하지 못했습니다. OP가 관심을 갖는 stdout에서 stderr를 분리하는 방법을 제공하지 않았습니다.
Jeremy Visser

1

O_o Tync 스크립트의 약간 수정 된 버전이 있습니다. OS X Lion 용으로 이러한 모드를 만들어야했는데 랩핑 된 명령이 실행되기 전에 스크립트가 완료되기 때문에 완벽하지 않습니다. 수면을 추가했지만 더 좋은 방법이 있다고 확신합니다.

#!/bin/bash

   if [ $1 == "--help" ] ; then
       echo "Executes a command and colorizes all errors occured"
       echo "Example: `basename ${0}` wget ..."
       echo "(c) o_O Tync, ICQ# 1227-700, Enjoy!"
       exit 0
       fi

   # Temp file to catch all errors
   TMP_ERRS=`mktemp /tmp/temperr.XXXXXX` || exit 1

   # Execute command
   "$@" 2> >(while read line; do echo -e "$(tput setaf 1)$line\n" | tee -a $TMP_ERRS; done)
   EXIT_CODE=$?

   sleep 1
   # Display all errors again
   if [ -s "$TMP_ERRS" ] ; then
       echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
       cat $TMP_ERRS
   else
       echo "No errors collected in $TMP_ERRS"
   fi
   rm -f $TMP_ERRS

   # Finish
   exit $EXIT_CODE

1

이 솔루션은 나를 위해 일했습니다 : https://superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr

이 기능을 내 .bashrc또는 에 넣었습니다 .zshrc.

# Red STDERR
# rse <command string>
function rse()
{
    # We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
    # Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
    ((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}

그런 다음 예를 들면 다음과 같습니다.

$ rse cat non_existing_file.txt

나에게 빨간색 출력을 줄 것이다.


리디렉션 종료 코드에 대해 set -o pipefail;이전 (eval에 추가 할 수 있습니다
kvaps

또한 "인수에 공백을 보존하기 위해 to eval을 추가하십시오
kvaps


0

fifos를 사용하는 버전

mkfifo errs
stdbuf -o0 -e0 -i0 grep . foo | while read line; do echo -e "\e[01;31m$line  \e[0m" >&2; done &
stdbuf -o0 -e0 -i0 sh $script 2>errs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.