programing

stdout과 stderr을 쉘 스크립트의 두 가지 다른 프로세스로 파이프합니까?

copyandpastes 2021. 1. 19. 08:17
반응형

stdout과 stderr을 쉘 스크립트의 두 가지 다른 프로세스로 파이프합니까?


난 그냥하는 pipline이

 command1 | command2

따라서 command1의 stdout은 command2로 이동하고 command1의 stderr는 터미널 (또는 쉘의 stdout이있는 곳)으로 이동합니다.

command3stdout이 여전히 command2로 이동하는 동안 command1의 stderr을 세 번째 프로세스 ( ) 로 파이프 할 수 있습니까?


다른 파일 설명자 사용

{ command1 2>&3 | command2; } 3>&1 1>&2 | command3

다른 파일 디스크립터는 3 개에서 9 개까지 최대 7 개까지 사용할 수 있습니다.
더 많은 설명이 필요하면 질문 해주세요. 설명 할 수 있습니다 ;-)

테스트

{ { echo a; echo >&2 b; } 2>&3 | sed >&2 's/$/1/'; } 3>&1 1>&2 | sed 's/$/2/'

산출:

b2
a1

두 개의 로그 파일을 생성합니다.
1. stderr전용
2. stderrstdout

{ { { command 2>&1 1>&3; } | tee err-only.log; } 3>&1; } > err-and-stdout.log

경우 command입니다 echo "stdout"; echo "stderr" >&2우리는 그런 식으로 테스트 할 수 있습니다 :

$ { { { echo out>&3;echo err>&1;}| tee err-only.log;} 3>&1;} > err-and-stdout.log
$ head err-only.log err-and-stdout.log
==> err-only.log <==
err

==> err-and-stdout.log <==
out
err

허용 된 대답은 stdout의 반대가 stderr됩니다. 다음은 그것들을 보존하는 방법입니다 (이 목적에 대한 인터넷 검색이이 포스트를 불러 오기 때문에) :

{ command 2>&1 1>&3 3>&- | stderr_command; } 3>&1 1>&2 | stdout_command

주의:

  • 3>&-fd 3이에서 상속되는 것을 방지하기 위해 필요합니다 command. ( command내부 작업 에 따라 예상치 못한 결과가 발생할 수 있습니다 .)

부품 설명 :

  1. 먼저 바깥 쪽 부분 :

    1. 3>&1- 3 전략 중 에 대한 { ... }어떤 설정되어 1 전략 중 (즉되었다 stdout)
    2. 1>&2- 1 전략 중 을 위해 { ... }무엇을 설정 2 전략 중 (즉되었다 stderr)
    3. | stdout_command- FD 1 (하였다 stdout통해 파이프되어)stdout_command
  2. 내부 부분은 외부 부분에서 파일 설명자를 상속합니다.

    1. 2>&1- 2 전략 중 을 위해 command무엇으로 설정되어 1 전략 중을 했다 (즉, stderr외부 부분에 따라)
    2. 1>&3- 1 전략 중 을 위해 command무엇으로 설정되어 3 전략 중을 했다 (즉, stdout외부 부분에 따라)
    3. 3>&-- FD 3 에 대해 command아무것도 설정 (즉 폐쇄 )
    4. | stderr_command- FD 1 (하였다 stderr통해 파이프되어)stderr_command

예:

foo() {
    echo a
    echo b >&2
    echo c
    echo d >&2
}

{ foo 2>&1 1>&3 3>&- | sed -u 's/^/err: /'; } 3>&1 1>&2 | sed -u 's/^/out: /'

산출:

out: a
err: b
err: d
out: c

(주문의 a -> cb -> d사이에 동기화 어떤 형태가 없기 때문에 항상 확정 될 것 stderr_command하고 stdout_command.)


stderr을 stdout으로 리디렉션하기 만하면됩니다.

{ command1 | command2; } 2>&1 | command3

주의 : stdout (있는 경우) commnd3도 읽습니다 command2.
이를 방지하려면 commnd2stdout 을 버릴 수 있습니다 .

{ command1 | command2 >/dev/null; } 2>&1 | command3

However, to keep command2 stdout (e.g. in the terminal),
then please refer to my other answer more complex.

Test

{ { echo -e "a\nb\nc" >&2; echo "----"; } | sed 's/$/1/'; } 2>&1 | sed 's/$/2/'

output:

a2
b2
c2
----12

Using process substitution:

command1 > >(command2) 2> >(command3)

See http://tldp.org/LDP/abs/html/process-sub.html for more info.


The same effect can be accomplished fairly easily with a fifo. I'm not aware of a direct piping syntax for doing it (though it would be nifty to see one). This is how you might do it with a fifo.

First, something that prints to both stdout and stderr, outerr.sh:

#!/bin/bash

echo "This goes to stdout"
echo "This goes to stderr" >&2

Then we can do something like this:

$ mkfifo err
$ wc -c err &
[1] 2546
$ ./outerr.sh 2>err | wc -c
20
20 err
[1]+  Done                    wc -c err

That way you set up the listener for stderr output first and it blocks until it has a writer, which happens in the next command, using the syntax 2>err. You can see that each wc -c got 20 characters of input.

Don't forget to clean up the fifo after you're done if you don't want it to hang around (i.e. rm). If the other command wants input on stdin and not a file arg, you can use input redirection like wc -c < err too.


Pipe stdout as usual, but use Bash process substitution for the stderr redirection:

some_command 2> >(command of stderr) | command of stdout

Header: #!/bin/bash

ReferenceURL : https://stackoverflow.com/questions/9112979/pipe-stdout-and-stderr-to-two-different-processes-in-shell-script

반응형