이 경우 bash는 상위 프로세스의 공동 프로세스를 어떻게 알 수 있으며 shebang 라인이 이를 변경하는 이유는 무엇입니까?

이 경우 bash는 상위 프로세스의 공동 프로세스를 어떻게 알 수 있으며 shebang 라인이 이를 변경하는 이유는 무엇입니까?

outer.sh:

ls -l /proc/$$/exe
coproc cat
./inner.sh
kill $!

inner.sh:

ls -l /proc/$$/exe
set | grep COPROC || echo No match found
coproc cat
kill $!

을 실행하면 ./outer.sh다음이 인쇄됩니다.

lrwxrwxrwx 1 joe joe 0 Jun 16 22:47 /proc/147876/exe -> /bin/bash
lrwxrwxrwx 1 joe joe 0 Jun 16 22:47 /proc/147879/exe -> /bin/bash
No match found
./inner.sh: line 3: warning: execute_coproc: coproc [147878:COPROC] still exists

COPROC자식에는 및 가 설정되어 있지 않으므로 COPROC_PID부모의 자식이 나에게 이 경고를 줄 수 있는지 어떻게 알 수 있습니까?

#!/bin/bash또한 의 맨 위에 추가하거나 from 대신 inner.sh호출하면 경고가 사라지는 것을 발견했습니다. bash 하위 프로세스를 통해 실행되는데 왜 이것이 변경됩니까?bash ./inner.sh./inner.shouter.sh

답변1

shebang이 없는 스크립트는 POSIX 호환 인터프리터로 해석됩니다 sh. 이것은 실제로 POSIX 스크립트를 작성하는 POSIX 방식입니다. POSIX는 shebang을 지정하지 않습니다. 하지만 실제로 shebang을 사용하는 것이 더 이식 가능하고 안정적입니다. 여기에 좋은 예가 있습니다.

bash 쉘은 POSIX sh 인터프리터입니다. bash(일부 버전, 일부 사용자 정의 빌드 및 일부 환경)는 실제로 제가 아는 유일한 FLOSS 셸입니다.인증됨런타임이 규정을 준수합니다 sh(런타임 아님 bash).

shebang 없이 스크립트를 실행할 때 bash는 execve()ENOEXEC를 반환하고 바이너리처럼 보이지 않는지 확인한 후 이를 하위 파일에서 해석하고 상태를 기본값으로 재설정하여 실행을 시뮬레이션합니다.

그러나 이는 스크립트 자체가 POSIX 모드에서 실행되지 않는 한(예: 자체로 호출되는 경우) run 시 스크립트가 bashPOSIX sh 스크립트가 아닌 bash 스크립트로 해석됨을 의미합니다.bashsh

$ cat a
alias uname='echo hi'
uname
$ zsh -c ./a
hi
$ sh ./a
hi
$ bash -c ./a
Linux
$ (exec -a sh bash -c ./a)
hi

호출 시 ash 언어 대신 언어(별칭 무시)로 해석되는 방식을 이해합니다.bashbash

~$ strace -qqfe execve bash -c ./a
execve("/usr/bin/bash", ["bash", "-c", "./a"], 0x7fff0081a820 /* 66 vars */) = 0
execve("./a", ["./a"], 0x55b18b3a4660 /* 66 vars */) = -1 ENOEXEC (Exec format error)
[pid 123559] execve("/usr/bin/uname", ["uname"], 0x55b18b3a4660 /* 66 vars */) = 0
Linux
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=123559, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---

해석 스크립트를 bash실행하지 않는 방법을 참조하세요 .sh

당신이 얻는 사실 warning: execute_coproc: coproc [147878:COPROC] still exists은 버그이며 bash그 상태를 제대로 재설정할 수 없습니다.

어쨌든 coproc이는 키워드가 아니므 sh로 shebang-less 스크립트에서는 자리를 차지하지 않습니다. 구현은 완전히 다르지만 (그리고 보조 프로세스는 ksh에서 옵니다) coproc여기 에 셔뱅이 있어야 합니다.zshbash#! /bin/bash -

shebang을 사용 bash ./inner.sh하거나 사용하면 새 인터프리터 인스턴스가 올바르게 실행되고 execve()프로세스 메모리가 완전히 올바르게 지워집니다.

관련 정보