Uno script simile, senza sudo
, ma risultati simili:
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
Con bash
, il resto dello script va come input per sed
, con dash
, la shell lo interpreta.
In esecuzione strace
su quelli: dash
legge un blocco dello script (otto KB qui, più che sufficiente per contenere l'intero script), e quindi genera 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|...
Ciò significa che il filehandle è alla fine del file e sed
non vedrà alcun input. La parte rimanente viene bufferizzata all'interno dash
. (Se lo script fosse più lungo della dimensione del blocco di 8 kB, la parte rimanente verrebbe letta da sed
.)
Bash, d'altra parte, cerca di nuovo alla fine dell'ultimo 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 l'ingresso proviene da una pipe, come qui:
$ cat script.sh | bash
il riavvolgimento non può essere eseguito, poiché i tubi e le prese non sono ricercabili. In questo caso, Bash torna a leggere l'input di un carattere alla volta per evitare di leggere troppo. ( fd_to_buffered_stream()
ininput.c
) Effettuare una chiamata di sistema completa per ogni byte non è molto efficace in linea di principio. In pratica, non credo che le letture saranno un grande sovraccarico rispetto, ad esempio, al fatto che la maggior parte delle cose che la shell comporta generano processi completamente nuovi.
Una situazione simile è questa:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
La subshell deve assicurarsi di read
leggere solo la prima riga nuova, in modo che head
veda la riga successiva. (Funziona dash
anche con questo.)
In altre parole, Bash fa di tutto per supportare la lettura della stessa fonte per lo script stesso e per i comandi eseguiti da essa. dash
non lo fa. Il zsh
, e ksh93
confezionato in Debian, va con Bash su questo.
sudo su
: unix.stackexchange.com/questions/218169/…