Un guión similar, sin sudo
resultados, pero similares:
$ cat script.sh
#!/bin/bash
sed -e 's/^/--/'
whoami
$ bash < script.sh
--whoami
$ dash < script.sh
itvirta
Con bash
, el resto del script va como entrada para sed
, con dash
, el shell lo interpreta.
Corriendo strace
en esos: dash
lee un bloque del script (ocho kB aquí, más que suficiente para contener todo el script), y luego 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|...
Lo que significa que el controlador de archivo está al final del archivo y sed
no verá ninguna entrada. La parte restante está almacenada en el interior dash
. (Si el script fuera más largo que el tamaño de bloque de 8 kB, la parte restante sería leída por sed
).
Bash, por otro lado, busca el final del ú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|...
Si la entrada proviene de una tubería, como aquí:
$ cat script.sh | bash
no se puede rebobinar, ya que no se pueden buscar tuberías y enchufes. En este caso, Bash recurre a la lectura de la entrada de un carácter a la vez para evitar una sobre lectura. ( fd_to_buffered_stream()
ininput.c
) Hacer una llamada de sistema completo para cada byte no es muy efectivo en principio. En la práctica, no creo que las lecturas sean una gran sobrecarga en comparación, por ejemplo, con el hecho de que la mayoría de las cosas que hace el shell implican generar procesos completamente nuevos.
Una situación similar es esta:
echo -e 'foo\nbar\ndoo' | bash -c 'read a; head -1'
El subshell debe asegurarse de que read
solo lea la primera línea nueva, para que head
vea la siguiente línea. (Esto funciona dash
también con ).
En otras palabras, Bash hace todo lo posible para admitir la lectura de la misma fuente para el script en sí y para los comandos ejecutados desde él. dash
no lo hace El zsh
, y ksh93
empaquetado en Debian van con Bash en esto.
sudo su
: unix.stackexchange.com/questions/218169/…