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