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 meo 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 mepueda usar este script tanto normalmente como con sudo?

sudo su. Solo corresudo -io en susudo -slugar.sudo -icambia la ubicación a/root.sudo suosudo -sno 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.shaquí, ejecutarlo consh, que en Ubuntu 16.04 está vinculadodash. La expresión condicional[[es unbashcomando compuesto , por lodashque 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.shconbashesto, simplemente asumistebash, lo mismo ocurre con lasudo susubshell.fuente
/bin/sh.echo $0Me da el nombre de la secuencia de comandos:./test.sh)/proc/$$/exepuntos. También puede probar varias variables como$BASH_VERSION,$ZSH_VERSIONetc. (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
sudodefecto intentará ejecutar el archivo usando/bin/sh. No pude encontrarlo documentado en ninguna parte, pero lo confirme comprobando elsudocódigo fuente donde encontré lo siguiente en el archivopathnames.h:Esto significa "establecer si la variable
_PATH_BSHELLno está definida, establecerla en/bin/sh". Luego, en elconfigurescript incluido en el tarball fuente, tenemos:Este bucle buscará
/bin/bash,/usr/bin/sh,/sbin/sh,/usr/sbin/sho/bin/kshy selecciona el_PATH_BSHELLque lo que se encontró por primera vez . Dado que/bin/shfue el primero en la lista y existe,_PATH_BSHELLse establece en/bin/sh. El resultado de todo esto es que el shell predeterminado de asudomenos que se defina lo contrario es/bin/sh.Por lo tanto,
sudose ejecutará de manera predeterminada las cosas usando/bin/shy, en Ubuntu, que es un enlace simbólico adashun 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.shNo
sudo; en ausencia de una línea shebang, su shell intentará ejecutar el archivo en sí. Como está ejecutandobash, esto funcionarábash ./test.shy funcionará de manera efectiva .sudo suseguido de./test.sh.Aquí, está comenzando un nuevo shell para el usuario
root. Esto será cualquier shell definido en la$SHELLvariable de entorno para ese usuario y, en Ubuntu, el shell predeterminado de root esbash:sudo ./test.shAquí, está permitiendo
sudoejecutar el comando directamente. Dado que su shell predeterminado es/bin/shcomo se explicó anteriormente, esto hace que ejecute el script con/bin/sh, que esdashy falla, yadashque no comprende[[.Nota : los detalles de cómo
sudoestablece el shell predeterminado parecen ser un poco más complejos. Traté de cambiar los archivos mencionados en mi respuesta para señalar/bin/bashperosudotodaví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 porsudodefecto essh) sigue en pie.fuente
/bin/shel mensaje de error, ¿qué otra cosa podría ser? La pregunta se responde maravillosamente en Qué shell usa sudo · SO , vea también laman sudosección EJECUCIÓN DE MANDOS . Resultasudoque no usa un caparazón intermedio .execvellamada 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.