상위 쉘 here-document는 dash의 하위 명령과 작동하지 않지만 bash는 작동하는 이유는 무엇입니까?

상위 쉘 here-document는 dash의 하위 명령과 작동하지 않지만 bash는 작동하는 이유는 무엇입니까?

dash저는 debianstretch에서 실행 중이고 다음 명령( 및 ) 은 모두 bashbash에 입력됩니다. 결코 사용자로 실행되지 않는
것 같습니다whoami시험아래 코드와 같이 대시로 표시됩니다.

$ sudo dash << 'end'
> su test
> whoami
> end
root
$ sudo bash << 'end'
> su test
> whoami
> end
test

답변1

다음 예를 고려하십시오.

$ cat f
grep pos /proc/self/fdinfo/0
IFS= read -r var
echo A
echo B
printf '%s\n' "var=$var"
$ bash < f
pos:    29
B
var=echo A
$ dash < f
pos:    85
A
B
var=

보시다시피, 명령을 실행하면 grepstdin의 위치는 파일의 끝이고 의 dash명령 다음에 나오는 개행 문자 바로 뒤에 있습니다.grepbash

명령 echo A은 에 의해 실행되지만 dash의 경우 bash는 입력으로 주어진다 read.

dash명령을 실행하기 전에 전체 입력(실제로는 텍스트 블록)을 한 번에 한 줄씩 읽습니다 .bash

이렇게 하려면 bash개행 문자를 지나 읽지 않도록 한 번에 한 바이트씩 읽어야 하지만 입력이 일반 파일인 경우( f위의 내 파일의 경우와 같으며 문서에도 적용됩니다) 여기서) bash는 dash파이프를 사용하는 동안 이를 임시 파일로 구현합니다 . Linux에서 볼 bash수 있듯이 청크로 읽고 줄 끝으로 역추적하여 최적화합니다 .strace

$ strace -e 읽기,lseek bash < f
[...]
lseek(0, 0, SEEK_CUR) = 0
읽기(0, "grep pos /proc/self/fdinfo/0\nIFS"...,85) = 85
lseek(0, -56, SEEK_CUR) = 29
포지션: 29
[...]

$ strace -e 읽기, lseek 대시 < f
읽기(0, "grep pos /proc/self/fdinfo/0\nIFS"...,8192) = 85
포지션: 85
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12422, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
읽기(0,"",1) = 0
[...]

stdin이 터미널 장치인 경우 각각은 read()터미널에서 전송한 라인을 반환하므로 일반적으로 bash및 에서 유사한 동작을 볼 수 있습니다 dash.

귀하의 경우에는 다음과 같이 할 수 있습니다.

sudo dash << 'end-of-script'
su test <<"end"
whoami
end
end-of-script

또는 더 나은:

sudo sh -c '
  su test -c whoami
'

또는 더 나은 방법은 다음과 같습니다.

sudo -u test whoami

답변2

Bash와 Dash는 stdin의 입력을 다르게 처리합니다. 명령을 실행할 때( su여기) Bash는 명령을 실행하게 한 줄 뒤의 stdin에서 시간 섹션 파이프에서 한 단어를 읽거나 거꾸로 살펴보는 방식으로 읽기 위치를 조심스럽게 유지합니다. 입력이 파일에서 오는지 확인하십시오. Dash는 신경 쓰지 않고 단지 전체 블록을 읽습니다.

이는 표준 입력과 그 안의 읽기 위치가 셸과 하위 프로세스 간에 공유되기 때문에 중요합니다.

따라서 Bash를 사용할 때 를 읽고 su test\nwhoami\n첫 번째 개행 이후로 돌아가서 시작합니다. su이는 이제 whoami\n입력에 표시됩니다.

Dash의 경우 읽고 su test\nwhoami\n시작 su하고 입력이 표시되지 않고 종료된 다음 Dash가 시작됩니다 whoami.


여기서도 같은 것을 볼 수 있습니다. Dash를 사용하면 date명령을 실행하고 read빈 입력을 얻는 반면 Bash를 사용하면 라인은 read입니다 x.

$ cat test.sh
read x
date
echo "variable x = '$x'"
$ cat test.sh | bash
variable x = 'date'
$ cat test.sh | dash
Sat Aug 24 12:25:23 EEST 2019
variable x = ''

내가 설명하면POSIX 설명shBash의 신중한 행동이 필요하다는 점은 맞습니다. 반면 Dash의 여유로운 접근 방식은 이에 맞지 않습니다.

STDIN
[...] 쉘이 표준 입력을 사용하고 표준 입력도 사용하는 명령을 호출하는 경우, 쉘은 명령이 실행을 시작할 때 표준 입력 파일 포인터가 읽고 있는 명령 바로 뒤를 가리키는지 확인해야 합니다. 호출된 명령으로 읽을 문자가 셸에서 소비되는 방식으로 미리 읽어서는 안 됩니다.

그만한 가치가 있는 만큼 Busybox의 쉘은 Dash와 유사하게 작동하며, 제가 테스트한 다른 모든 쉘은 Bash의 기능을 수행합니다.

관련 정보