なしの同様のスクリプトですが、sudo結果は同様です。
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
を使用するbashと、残りのスクリプトはへの入力として使用されsed、を使用するdashと、シェルがスクリプトを解釈します。
straceそれらで実行:dashスクリプトのブロックを読み取り(ここでは8 kB、スクリプト全体を保持するのに十分な量)、次に生成しsedます。
read(0, "#!/bin/bash\nsed -e 's/^/--/'\nwho"..., 8192) = 36
stat("/bin/sed", {st_mode=S_IFREG|0755, st_size=73416, ...}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|...
つまり、ファイルハンドルはファイルの最後にあり、sed入力は表示されません。内でバッファリングされている残りの部分dash。(スクリプトが8 kBのブロックサイズよりも長い場合、残りの部分はによって読み取られsedます。)
一方、bashは最後のコマンドの終わりまでシークします。
read(0, "#!/bin/bash\nsed -e 's/^/--/'\nwho"..., 36) = 36
stat("/bin/sed", {st_mode=S_IFREG|0755, st_size=73416, ...}) = 0
...
lseek(0, -7, SEEK_CUR) = 29
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|...
次のように、入力がパイプからのものである場合:
$ cat script.sh | bash
パイプとソケットがシークできないため、巻き戻しを実行できません。この場合、Bashは一度に1文字ずつ入力を読み取るようにフォールバックし、読み過ぎを防ぎます。(fd_to_buffered_stream()中にinput.c各バイトのための完全なシステムコールを行う)は、原則的に非常に効果的ではありません。実際には、読み取りが大きなオーバーヘッドになるとは思いません。たとえば、シェルが行うほとんどのことはまったく新しいプロセスの生成を伴うという事実とは異なります。
同様の状況はこれです:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
サブシェルはread、最初の改行のみを読み取るようにしheadて、次の行が見えるようにする必要があります。(これも動作しdashます。)
言い換えると、Bashは、スクリプト自体とそれから実行されるコマンドの同じソースの読み取りをサポートするために、追加の長さを採用しています。dashしません。zsh、およびksh93Debianのパッケージには、この上のBashで行きます。
sudo su:unix.stackexchange.com/questions/218169/…–