stdout과 stderr을 시각적으로 분리하여 인터리브되지 않고 쉽게 식별 할 수있는 방법을 찾고 있습니다. 이상적으로 stdout과 stderr는 화면에 별도의 영역 (예 : 다른 열)이 표시됩니다. 예를 들어 다음과 같은 출력이 표시됩니다.
~$ some command
some useful output info
ERROR: an error
more output
ERROR: has occurred
another message
~$
대신 다음과 같이 보일 것입니다.
~$ some command |
some useful output info |
more output | ERROR: an error
another message | ERROR: has occurred
~$ |
답변
GNU screen
의 수직 분할 기능을 사용할 수 있습니다 .
#! /bin/bash -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP
FIFO=$tmpdir/FIFO
mkfifo "$FIFO" || exit
conf=$tmpdir/conf
cat > "$conf" << 'EOF' || exit
split -v
focus
screen -t stderr sh -c 'tty > "$FIFO"; read done < "$FIFO"'
focus
screen -t stdout sh -c 'read tty < "$FIFO"; eval "$CMD" 2> "$tty"; echo "[Command exited with status $?, press enter to exit]"; read prompt; echo done > "$FIFO"'
EOF
CMD="$*"
export FIFO CMD
screen -mc "$conf"
예를 들어 다음과 같이 사용하려면
that-script 'ls / /not-here'
아이디어는 세로 분할 레이아웃으로 두 개의 화면 창을 시작하는 임시 conf 파일로 화면을 실행한다는 것입니다. 첫 번째에서는 stderr이 두 번째에 연결된 상태에서 명령을 실행합니다.
우리는 두 번째 창에 tty 장치를 첫 번째 창에 전달하기 위해 명명 된 파이프를 사용하고 명령이 완료되면 첫 번째 창에 두 번째 창에 알려줍니다.
파이프 기반 접근 방식과 비교할 때의 다른 장점은 명령의 stdout 및 stderr이 여전히 tty 장치에 연결되어있어 버퍼링에 영향을 미치지 않는다는 것입니다. 두 창을 모두 독립적으로 위아래로 스크롤 할 수 있습니다 ( screen
의 복사 모드 사용).
bash
해당 스크립트 와 대화식으로 쉘을 실행 하면 프롬프트가 두 번째 창에 표시되는 반면, 쉘은 첫 번째 창에 입력 한 내용을 읽습니다. 쉘은 stderr에서 프롬프트를 출력합니다.
의 경우 bash
1, 에코 당신은 또한과 두 번째 창에 나타납니다 입력 한 내용의 에코 (의 경우 readline에 쉘에 의해 출력 bash
표준 오류에는)뿐만 아니라. 다른 쉘 등으로 ksh93
, 그것은 첫 번째 창에 (표시됩니다 에코 당신이 쉘을 넣어하지 않는 한, 상기 단말 장치 드라이버에 의해 출력이 아닌 쉘) emacs
또는 vi
와 모드 set -o emacs
나 set -o vi
.
답변
이것은 annotate-output
Debian ANNOTATE-OUTPUT (1) 스크립트를 기반으로하는 못생긴 솔루션 입니다. 이것이 당신이 찾고있는 것인지 확실하지 않지만 시작할 수있는 것입니다 :
#!/bin/bash
readonly col=150 # column to start error output
add_out ()
{
while IFS= read -r line; do
echo "$1: $line"
done
if [ ! -z "$line" ]; then
echo -n "$1: $line"
fi
}
add_err ()
{
while IFS= read -r line; do
printf "%*s %s %s: %s\n" $col "|" "$1" "$line"
done
if [ ! -z "$line" ]; then
printf "%*s %s: %s" $col "$1" "$line"
fi
}
cleanup() { __st=$?; rm -rf "$tmp"; exit $__st; }
trap cleanup 0
trap 'exit $?' 1 2 13 15
tmp=$(mktemp -d --tmpdir annotate.XXXXXX) || exit 1
OUT=$tmp/out
ERR=$tmp/err
mkfifo $OUT $ERR || exit 1
add_out OUTPUT < $OUT &
add_err ERROR < $ERR &
echo "I: Started $@"
"$@" > $OUT 2> $ERR ; EXIT=$?
rm -f $OUT $ERR
wait
echo "I: Finished with exitcode $EXIT"
exit $EXIT
당신은 사용하여 테스트 할 수 있습니다 ./this_script another_script
또는 command
.
답변
나는 당신의 질문의 다음 부분을 분석하려고 노력할 것입니다 :
대신 다음과 같이 보일 것입니다.
~ $ 명령 유용한 출력 정보 | 더 많은 출력 | 오류 : 오류 다른 메시지 | 오류 : 발생했습니다 ~ $
원하는 것을 분해하고 싶다면 :
1) stdout
스트림은 각 줄을 a로 끝내지 CR LF
않고 대신 ‘|’ 캐릭터. 이것은 물론 두 개의 스트림을 정렬하지 않으며 정렬은 문제가 아닙니다. 왜냐하면 미래에 추가되는 행의 길이를 예측해야하기 때문에 stdout
불가능합니다.
2) 정렬을 잊어 버렸다고 가정하면 stderr
각 라인의 시작 부분에 “ERROR :”를 추가하는 파이프 라인에 의해 처리 된 후 단순히 출력 할 것 입니다. 나는 간단한 스크립트를 작성하여 이것이 매우 쉽다고 생각하고 stderr
항상이 스크립트를 통해 나오는지 확인하십시오 .
그러나 다음과 같은 출력이 생성됩니다.
~ $ 명령 유용한 출력 정보 | 더 많은 결과 | 오류 : 오류 다른 메시지 | 오류 : 발생했습니다
실제로 도움이되지 않는 것은 무엇입니까? 또한 나는 믿지 않는다, 그것은 당신이 무엇을 겪고 있는지입니다!
초기 질문의 문제는 두 스트림이 모두 비동기식으로 작성 될 수 있다는 사실과 관련하여 스트림에 추가 된 각 줄의 직렬 특성을 고려하지 않는다는 것입니다.
가장 가까운 해결책은 사용하는 것 ncurses
입니다.
보다.
[ http://www.tldp.org/HOWTO/html_single/NCURSES-Programming-HOWTO/]
[ http://invisible-island.net/ncurses/ncurses-intro.html#updating]
두 스트림을 모두 버퍼링하고 결합하여 두 버퍼에서 요소를 가져 오는 세 번째 버퍼를 생성해야합니다. 그런 다음, 터미널 화면을 지우고 세 번째 버퍼가 변경 될 때마다 다시 페인트하여 세 번째 버퍼를 터미널 화면에 덤프하십시오. 그러나 이것이 ncurses
작동 하는 방식 이므로 휠을 재발 명하고 거기에서 가져 가지 않는 이유는 무엇입니까?
어쨌든 터미널 화면이 완전히 그려지는 방식을 인계해야합니다 ! 다시 인쇄 한 화면의 텍스트를 원하는대로 다시 정렬하십시오. 터미널 문자가있는 비디오 게임과 매우 유사합니다.
내 대답이 당신이 무엇을 추구하는지의 한계를 명확히하는 데 도움이되기를 바랍니다 …
이것을 반복하는 것에 대해 실례하지만, 당신이 보여준 것에 대한 가장 큰 문제는 스트림 stdout
과 stderr
스트림 의 “프로세서”가 미래 라인의 길이를 미리 정렬하여 올바르게 정렬하는 방법입니다.