En Ubuntu 16.04.3, tengo un script bash muy simple:
test.sh
[[ 0 == 0 ]] && result="true" || result="false"
echo $result
echo $USER $SHELL $0
Cuando lo llamo como usuario no root me
o como root
, funciona como se esperaba. Si lo uso sudo ./test.sh
, se queja de un error de sintaxis:
$ ./test.sh
true
me /bin/bash ./test.sh
$ sudo su
# ./test.sh
true
root /bin/bash ./test.sh
# exit
$ sudo ./test.sh
./test.sh: 1: ./test.sh: [[: not found
false
root /bin/bash ./test.sh
¿Qué podría estar causando esto? ¿Cómo puedo solucionarlo para que me
pueda usar este script tanto normalmente como con sudo
?
sudo su
. Solo corresudo -i
o en susudo -s
lugar.sudo -i
cambia la ubicación a/root
.sudo su
osudo -s
no cambie la ubicación del directorio.-s
.Respuestas:
Cada script comienza con un Shebang , sin él, el shell que inicia su script no sabe qué intérprete debe ejecutar su script 1 y podría, como en el caso de
sudo ./script.sh
aquí, ejecutarlo consh
, que en Ubuntu 16.04 está vinculadodash
. La expresión condicional[[
es unbash
comando compuesto , por lodash
que no sabe cómo manejarlo y arroja el error que encontró.La solución aquí es agregar
como la primera línea de tu guión. Puede obtener el mismo resultado cuando lo llama explícitamente con
sudo bash ./script.sh
, pero un shebang es el camino a seguir.Para verificar qué shell ejecuta su script, agréguelo
echo $0
. Eso no es lo mismo queecho $SHELL
, citando wiki.archlinux.org :1: Como comenzaste
./test.sh
conbash
esto, simplemente asumistebash
, lo mismo ocurre con lasudo su
subshell.fuente
/bin/sh
.echo $0
Me da el nombre de la secuencia de comandos:./test.sh
)/proc/$$/exe
puntos. También puede probar varias variables como$BASH_VERSION
,$ZSH_VERSION
etc. (pero el guión no establece ninguna de esas variables)Como explicó @dessert , el problema aquí es que su script no tiene una línea shebang . Sin un shebang, por
sudo
defecto intentará ejecutar el archivo usando/bin/sh
. No pude encontrarlo documentado en ninguna parte, pero lo confirme comprobando elsudo
código fuente donde encontré lo siguiente en el archivopathnames.h
:Esto significa "establecer si la variable
_PATH_BSHELL
no está definida, establecerla en/bin/sh
". Luego, en elconfigure
script incluido en el tarball fuente, tenemos:Este bucle buscará
/bin/bash
,/usr/bin/sh
,/sbin/sh
,/usr/sbin/sh
o/bin/ksh
y selecciona el_PATH_BSHELL
que lo que se encontró por primera vez . Dado que/bin/sh
fue el primero en la lista y existe,_PATH_BSHELL
se establece en/bin/sh
. El resultado de todo esto es que el shell predeterminado de asudo
menos que se defina lo contrario es/bin/sh
.Por lo tanto,
sudo
se ejecutará de manera predeterminada las cosas usando/bin/sh
y, en Ubuntu, que es un enlace simbólico adash
un shell compatible con POSIX mínimo:La
[[
construcción es una característica bash, no está definida por el estándar POSIX y no se entiende pordash
:En detalle, en las tres invocaciones que probaste:
./test.sh
No
sudo
; en ausencia de una línea shebang, su shell intentará ejecutar el archivo en sí. Como está ejecutandobash
, esto funcionarábash ./test.sh
y funcionará de manera efectiva .sudo su
seguido de./test.sh
.Aquí, está comenzando un nuevo shell para el usuario
root
. Esto será cualquier shell definido en la$SHELL
variable de entorno para ese usuario y, en Ubuntu, el shell predeterminado de root esbash
:sudo ./test.sh
Aquí, está permitiendo
sudo
ejecutar el comando directamente. Dado que su shell predeterminado es/bin/sh
como se explicó anteriormente, esto hace que ejecute el script con/bin/sh
, que esdash
y falla, yadash
que no comprende[[
.Nota : los detalles de cómo
sudo
establece el shell predeterminado parecen ser un poco más complejos. Traté de cambiar los archivos mencionados en mi respuesta para señalar/bin/bash
perosudo
todavía estaba predeterminado/bin/sh
. Por lo tanto, debe haber otros lugares en el código fuente donde se define el shell predeterminado. Sin embargo, el punto principal (que porsudo
defecto essh
) sigue en pie.fuente
/bin/sh
el mensaje de error, ¿qué otra cosa podría ser? La pregunta se responde maravillosamente en Qué shell usa sudo · SO , vea también laman sudo
sección EJECUCIÓN DE MANDOS . Resultasudo
que no usa un caparazón intermedio .execve
llamada al sistema que está predeterminadash
. Y no, los shells intermedios son irrelevantes, no se trata del shell que ejecuta el comando sino del intérprete de shell utilizado para leer el script de shell dado. Entonces, no, no inicia un shell intermedio, pero aún necesita un intérprete de shell para los scripts de shell.