Um script semelhante, sem sudo , mas resultados semelhantes:
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
Com bash , o restante do script entra como entrada para sed , com dash , o shell o interpreta.
Executando strace sobre eles: dash lê um bloco do script (oito kB aqui, mais do que suficiente para manter todo o script) e, em seguida, gera 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|...
O que significa que o filehandle está no final do arquivo e sed não verá nenhuma entrada. A parte restante sendo armazenada em buffer em dash . (Se o script fosse maior que o tamanho de bloco de 8 kB, a parte restante seria lida por sed .)
Bash, por outro lado, busca voltar ao final do último comando:
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|...
Se a entrada vem de um pipe, como aqui:
$ cat script.sh | bash
O rebobinamento não pode ser feito, pois canos e soquetes não são procurados. Neste caso, o Bash volta a ler a entrada um caractere de cada vez para evitar a sobreposição. ( fd_to_buffered_stream() in input.c ) Fazendo uma chamada completa do sistema para cada byte não é muito eficaz em princípio. Na prática, não creio que as leituras sejam um grande gasto comparativamente, por ex. ao fato de que a maioria das coisas que o shell envolve envolve a criação de novos processos.
Uma situação semelhante é esta:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
O subshell precisa garantir que read apenas leia a primeira nova linha, para que head veja a próxima linha. (Isso funciona com dash também.)
Em outras palavras, o Bash vai a comprimentos adicionais para suportar a leitura da mesma fonte para o próprio script e para os comandos executados a partir dele. dash não. O zsh e ksh93 empacotados no Debian vão com o Bash.