Dans Ubuntu 16.04.3, j'ai un script bash très simple:
test.sh
[[ 0 == 0 ]] && result="true" || result="false"
echo $result
echo $USER $SHELL $0
Lorsque je l'appelle en tant qu'utilisateur non root me
ou en tant que root
, cela fonctionne comme prévu. Si j'utilise sudo ./test.sh
, il se plaint d'une erreur de syntaxe:
$ ./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'est-ce qui peut causer cela? Comment puis-je le corriger pour me
pouvoir utiliser ce script à la fois normalement et avec sudo
?
sudo su
. Exécutez simplementsudo -i
ou à lasudo -s
place.sudo -i
change l'emplacement en/root
.sudo su
ousudo -s
ne changez pas l'emplacement du répertoire.-s
.Réponses:
Chaque script commence par un Shebang , sans lui le shell qui démarre votre script ne sait pas à quel interprète doit exécuter votre script 1 et pourrait - comme dans le cas
sudo ./script.sh
ici - l'exécuter avecsh
lequel, dans Ubuntu 16.04 est liédash
. L' expression conditionnelle[[
est unebash
commande composée ,dash
elle ne sait donc pas comment la gérer et renvoie l'erreur que vous avez rencontrée.La solution ici est d'ajouter
comme première ligne de votre script. Vous pouvez obtenir le même résultat lorsque vous l'appelez explicitement avec
sudo bash ./script.sh
, mais un shebang est le chemin à parcourir.Pour vérifier quel shell exécute votre script, ajoutez-
echo $0
y. Ce n'est pas la même choseecho $SHELL
, citant wiki.archlinux.org :1: Comme vous avez commencé
./test.sh
avecbash
celabash
, il en va de même pour lesudo su
sous - shell.la source
/bin/sh
.echo $0
Me donne le nom du script:./test.sh
)/proc/$$/exe
pointe vers. Aussi , vous pouvez tester différentes variables comme$BASH_VERSION
,$ZSH_VERSION
, etc. (mais tiret ne précise pas une telle variable)Comme l'a expliqué @dessert , le problème ici est que votre script n'a pas de ligne shebang . Sans shebang,
sudo
tentera par défaut d'exécuter le fichier à l'aide de/bin/sh
. Je ne l'ai trouvé nulle part, mais j'ai confirmé en vérifiant lesudo
code source où j'ai trouvé ce qui suit dans le fichierpathnames.h
:Cela signifie "définir si la variable
_PATH_BSHELL
n'est pas définie, définissez-la sur/bin/sh
". Ensuite, dans leconfigure
script inclus dans l'archive tar source, nous avons:Cette boucle cherchera
/bin/bash
,/usr/bin/sh
,/sbin/sh
,/usr/sbin/sh
ou/bin/ksh
et définit ensuite la_PATH_BSHELL
à celui qui a été trouvé en premier . Étant donné qu'il/bin/sh
était le premier de la liste et qu'il existe,_PATH_BSHELL
est défini sur/bin/sh
. Le résultat de tout cela est que le shell par défaut desudo
sauf indication contraire est/bin/sh
.Donc,
sudo
par défaut, les choses seront exécutées en utilisant/bin/sh
et, sur Ubuntu, c'est un lien symbolique versdash
un shell compatible POSIX minimal:La
[[
construction est une fonctionnalité bash, elle n'est pas définie par la norme POSIX et n'est pas comprise pardash
:En détail, dans les trois invocations que vous avez essayées:
./test.sh
Non
sudo
; en l'absence d'une ligne de shebang, votre shell tentera d'exécuter le fichier lui-même. Puisque vous exécutezbash
, cela fonctionnerabash ./test.sh
et fonctionnera efficacement .sudo su
suivi de./test.sh
.Ici, vous lancez un nouveau shell pour l'utilisateur
root
. Ce sera le shell défini dans la$SHELL
variable d'environnement pour cet utilisateur et, sur Ubuntu, le shell par défaut de root estbash
:sudo ./test.sh
Ici, vous laissez
sudo
exécuter directement la commande. Étant donné que son shell par défaut est/bin/sh
comme expliqué ci-dessus, cela lui fait exécuter le script/bin/sh
, ce qui estdash
et il échoue cardash
ne comprend pas[[
.Remarque : les détails de la
sudo
définition du shell par défaut semblent être un peu plus complexes. J'ai essayé de changer les fichiers mentionnés dans ma réponse pour pointer vers,/bin/bash
mais j'étaissudo
toujours en défaut/bin/sh
. Il doit donc y avoir d'autres endroits dans le code source où le shell par défaut est défini. Néanmoins, le point principal (parsudo
défautsh
) est toujours d'actualité.la source
/bin/sh
le message d'erreur - quoi d'autre pourrait-il être possible? La question est admirablement répondue dans Quel shell sudo utilise · SO , voir aussiman sudo
, section EXÉCUTION DE COMMANDE . Il s'avère quesudo
n'utilise pas un shell intermédiaire !execve
appel système qui est par défautsh
. Et non, les shells intermédiaires ne sont pas pertinents, il ne s'agit pas du shell qui exécute la commande mais de l'interpréteur de shell utilisé pour lire le script shell donné. Donc non, il ne lance pas de shell intermédiaire mais il a toujours besoin d'un interpréteur de shell pour les scripts shell.