에코 또는 인쇄 /dev/stdin /dev/stdout /dev/stderr

에코 또는 인쇄 /dev/stdin /dev/stdout /dev/stderr

/dev/stdin, /dev/stdout 및 /dev/stderr의 값을 인쇄하고 싶습니다.

내 간단한 스크립트는 다음과 같습니다.

#!/bin/bash
echo your stdin is : $(</dev/stdin)
echo your stdout is : $(</dev/stdout)
echo your stderr is : $(</dev/stderr)

나는 다음 파이프라인을 사용합니다.

[root@localhost home]# ls | ./myscript.sh
[root@localhost home]# testerr | ./myscript.sh

작동하는 것 같지만 $(</dev/stdin)사람들이 사용한 다른 문제도 발견했습니다. "${1-/dev/stdin}"시도했지만 성공하지 못했습니다.

답변1

stdin, stdout그리고 stderr그렇습니다개울부착파일 설명자프로세스에 대해 각각 0, 1, 2입니다.

터미널이나 터미널 에뮬레이터의 대화형 쉘 프롬프트에서 3개의 파일 설명자는 모두 동일한 파일 설명자를 참조합니다.파일 설명 열기/dev/pts/0이는 읽기+쓰기 모드에서 터미널 또는 의사 터미널 장치 파일(유사)을 열어 얻을 수 있습니다.

리디렉션을 사용하지 않고 대화형 셸에서 스크립트를 실행하면 스크립트가 이러한 파일 설명자를 상속합니다.

Linux에서 , /dev/stdin는 각각 에 대한 심볼릭 링크 /dev/stdout이며 /dev/stderr, 이 파일 설명자에서 열리는 실제 파일에 대한 특수 심볼릭 링크입니다./proc/self/fd/0/proc/self/fd/1/proc/self/fd/2

이는 stdin, stdout, stderr이 아니며 stdin, stdout, stderr가 어떤 파일로 이동하는지 식별하는 특수 파일입니다(다른 시스템에서는 이러한 특수 파일이 있는 Linux와 다릅니다).

stdin에서 무언가를 읽는 것은 파일 설명자 0(참조된 파일의 위치를 ​​가리킴 /dev/stdin)에서 읽는 것을 의미합니다.

그러나$(</dev/stdin) ).

읽기+쓰기 모드에서 터미널 장치를 여는 특별한 경우를 제외하고 stdout 및 stderr은 일반적으로 읽기 위해 열리지 않습니다. 사용할 수 있는 스트림이어야 합니다.에게 편지를 쓰다. 따라서 파일 설명자 1에서 읽는 것은 일반적으로 작동하지 않습니다. Linux에서는 열기 /dev/stdout또는 /dev/stderr읽기(그림 참조 $(</dev/stdout))가 작동하고 stdout이 이동하는 파일에서 읽을 수 있습니다(stdout이 파이프인 경우 파이프의 다른 쪽 끝에서 읽습니다. 소켓 인터페이스인 경우 실패합니다). 왜냐하면 당신은 할 수 없기 때문입니다열려 있는소켓).

우리의 경우 스크립트는 리디렉션 없이 터미널의 대화형 쉘 프롬프트에서 실행되며 모든 /dev/stdin, /dev/stdout 및 /dev/stderr은 /dev/pts/x 터미널 장치 파일이 됩니다.

이러한 특수 파일을 읽으면 터미널에서 보낸 내용(키보드에 입력한 내용)이 반환됩니다. 이를 작성하면 텍스트가 터미널로 전송됩니다(표시용).

echo $(</dev/stdin)
echo $(</dev/stderr)

동일할 것입니다. 확장하려면 쉘이 /dev/pts/0을 열고 빈 줄을 $(</dev/stdin)누를 때까지 입력한 내용을 읽습니다 . ^D그런 다음 확장에 전달된 확장(후행 줄 바꿈 및 분할+glob이 포함된 입력)을 전달한 echo다음 이를 표준 출력(표시용)으로 출력합니다.

그러나:

echo $(</dev/stdout)

존재하다 bash(그리고 bash오직$(...)), 내부적으로 stdout이 리디렉션되었음을 인식하는 것이 중요합니다 . 이제는 파이프라인입니다. 의 경우 bash하위 셸 프로세스는 파일(여기 /dev/stdout)의 내용을 읽고 이를 파이프에 쓰는 반면 상위 프로세스는 확장을 위해 다른 쪽 끝에서 읽습니다.

이 경우 하위 bash 프로세스가 열리면 /dev/stdout실제로 파이프의 읽기 끝이 열립니다. 아무것도 나오지 않을 것입니다. 교착 상태입니다.

스크립트의 stdout이 가리키는 파일에서 읽으려면 다음을 사용하여 해결할 수 있습니다.

 { echo content of file on stdout: "$(</dev/fd/3)"; } 3<&1

그러면 fd 1이 fd 3에 복사되므로 /dev/fd/3은 /dev/stdout과 동일한 파일을 가리킵니다.

다음 스크립트를 사용하십시오.

#! /bin/bash -
printf 'content of file on stdin: %s\n' "$(</dev/stdin)"
{ printf 'content of file on stdout: %s\n' "$(</dev/fd/3)"; } 3<&1
printf 'content of file on stderr: %s\n' "$(</dev/stderr)"

실행할 때:

echo bar > err
echo foo | myscript > out 2>> err

그러면 다음이 표시됩니다 out.

content of file on stdin: foo
content of file on stdout: content of file on stdin: foo
content of file on stderr: bar

/dev/stdin, 에서 읽고 싶지 않고 대신 stdin, stdout 및 stderr에서 읽으려는 경우 /dev/stdout( /dev/stderr이는 훨씬 덜 의미가 있음) 다음을 수행할 수 있습니다.

#! /bin/sh -
printf 'what I read from stdin: %s\n' "$(cat)"
{ printf 'what I read from stdout: %s\n' "$(cat <&3)"; } 3<&1
printf 'what I read from stderr: %s\n' "$(cat <&2)"

두 번째 스크립트를 다시 시작하는 경우:

echo bar > err
echo foo | myscript > out 2>> err

당신은 볼 수 있습니다 out:

what I read from stdin: foo
what I read from stdout:
what I read from stderr:

그리고 err:

bar
cat: -: Bad file descriptor
cat: -: Bad file descriptor

stdout 및 stderr의 경우 cat파일 설명자가 이미 열려 있으므로 실패합니다.글쓰기$(cat <&3)그러나 읽지 않으면 과의 확장은 $(cat <&2)공허하다.

당신이 그것을 호출하는 경우 :

echo out > out
echo err > err
echo foo | myscript 1<> out 2<> err

( <>잘림 없이 읽기+쓰기 모드로 열림) 다음과 같이 표시됩니다 out.

what I read from stdin: foo
what I read from stdout:
what I read from stderr: err

그리고 err:

err

printf이전 항목이 with의 내용을 덮어쓰고 그 이후에는 해당 파일의 stdout 위치를 그대로 두었기 때문에 stdout에서 아무것도 읽히지 않는다는 것을 알 수 있습니다 . 예를 들어, 더 큰 텍스트를 그린 경우:outwhat I read from stdin: foo\nout

echo 'This is longer than "what I read from stdin": foo' > out

그런 다음 다음을 입력할 수 있습니다 out.

what I read from stdin: foo
read from stdin": foo
what I read from stdout: read from stdin": foo
what I read from stderr: err

$(cat <&3)첫 번째 항목 이후 남은 내용을 읽는 방법 보기printf 이렇게 하면 표준 출력 위치도 그곳으로 이동됩니다.다음 출력 printf이후에 무엇을 읽을 지 결정합니다.

답변2

stdout그리고 stderr출력이므로 읽을 수는 없고 쓰기만 할 수 있습니다. 예를 들어:

echo "this is stdout" >/dev/stdout
echo "this is stderr" >/dev/stderr

프로그램은 기본적으로 표준 출력에 기록하므로 첫 번째 출력은 다음과 같습니다.

echo "this is stdout"

다른 방법으로 stderr를 리디렉션할 수 있습니다.

echo "this is stderr" 1>&2

답변3

myscript.sh:

#!/bin/bash
filan -s

그런 다음 다음을 실행하십시오.

$ ./myscript.sh
    0 tty /dev/pts/1
    1 tty /dev/pts/1
    2 tty /dev/pts/1

$ ls | ./myscript.sh
    0 pipe 
    1 tty /dev/pts/1
    2 tty /dev/pts/1

$ ls | ./myscript.sh > out.txt
$ cat out.txt
    0 pipe 
    1 file /tmp/out.txt
    2 tty /dev/pts/1

filan먼저 설치 해야 할 수도 있습니다 sudo apt install socat.

관련 정보