GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué el documento principal Shell Here no funciona para el subcomando en Dash pero Bash funciona?

Estoy ejecutando Debian Stretch, todos los comandos a continuación (dash y bash ) se ingresa en bash.
El whoami parece que nunca se ejecuta como el usuario test en guión como en los códigos a continuación.

$ sudo dash << 'end'
> su test
> whoami
> end
root
$ sudo bash << 'end'
> su test
> whoami
> end
test

Respuesta aceptada:

Considere este ejemplo en su lugar:

$ cat f
grep pos /proc/self/fdinfo/0
IFS= read -r var
echo A
echo B
printf '%s\n' "var=$var"
$ bash < f
pos:    29
B
var=echo A
$ dash < f
pos:    85
A
B
var=

Como puede ver, en ese momento el grep se ejecuta el comando, la posición dentro de stdin está al final del archivo con dash , y justo después de la nueva línea que sigue al grep comando en bash .

El echo A el comando se ejecuta con dash pero en el caso de bash , se alimenta como entrada para read .

Lo que pasó es que dash leer toda la entrada (en realidad, un bloque de texto) mientras bash lea una línea a la vez antes de ejecutar los comandos.

Para hacerlo, bash necesitaría leer un byte a la vez para asegurarse de que no lea más allá de la nueva línea, pero cuando la entrada es un archivo normal (como en el caso de mi f archivo anterior, pero también para documentos aquí que bash implementa como archivos temporales, mientras que dash usa canalizaciones), bash lo optimiza leyendo por bloques y buscando hacia atrás hasta el final de la línea, que puedes ver con strace en Linux:

$ strace -e read,lseek bash < f
[...]
lseek(0, 0, SEEK_CUR)                   = 0
read(0, "grep pos /proc/self/fdinfo/0\nIFS"..., 85) = 85
lseek(0, -56, SEEK_CUR)                 = 29
pos:    29
[...]

$ strace -e read,lseek dash < f
read(0, "grep pos /proc/self/fdinfo/0\nIFS"..., 8192) = 85
pos:    85
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=12422, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
read(0, "", 1)                          = 0
[...]

Cuando stdin es un dispositivo terminal, cada read() devuelve las líneas enviadas por el terminal, por lo que generalmente verá un comportamiento similar en bash y dash .

En tu caso, podrías hacer:

sudo dash << 'end-of-script'
su test <<"end"
whoami
end
end-of-script

o mejor:

sudo sh -c '
  su test -c whoami
'

o incluso mejor:

sudo -u test whoami

Linux
  1. Personalización del shell Bash

  2. ¿Por qué la expresión regular funciona en X pero no en Y?

  3. ¿La razón por la que Bash Shell no le advierte sobre el desbordamiento aritmético, etc.?

  4. ¿Por qué el archivo de traducción de Bash no contiene todos los textos de error?

  5. ¿Por qué `zip` en un bucle For funciona cuando el archivo existe, pero no cuando no existe?

Linux – ¿Por qué Locale Es_mx funciona pero no Es?

¿Por qué este "mientras se lee" funciona en una terminal, pero no en un script de Shell?

¿Por qué Regex en Bash funciona solo si es una variable y no directamente?

¿Por qué Tomcat funciona con el puerto 8080 pero no con el 80?

¿Por qué Bash está en todas partes (en la mayoría, si no en todas, las distribuciones de Linux)?

¿Por qué 'dd' no funciona para crear un USB de arranque?