この場合、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モードで実行されていない限り(たとえば、それ自体で呼び出される場合など)、実行時にスクリプトが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ここにShabanが必要です。zshbash#! /bin/bash -

shebangを使用bash ./inner.shまたは使用すると、新しいインタプリタインスタンスが正しく実行され、execve()プロセスメモリが完全に正しく消去されます。

関連情報