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
name__, 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 résoudre le problème de sorte que me
puisse utiliser ce script à la fois normalement et avec Sudo
name__?
Comme @ dessert expliqué , 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 pouvais pas le trouver documenté nulle part, mais j'ai confirmé en vérifiant le code source Sudo
où j'ai trouvé ce qui suit dans le fichier pathnames.h
:
#ifndef _PATH_BSHELL
#define _PATH_BSHELL "/bin/sh"
#endif /* _PATH_BSHELL */
Cela signifie "défini si la variable _PATH_BSHELL
n'est pas définie, définissez-la sur /bin/sh
". Ensuite, dans le script configure
inclus dans l’archive source, nous avons:
for p in "/bin/bash" "/usr/bin/sh" "/sbin/sh" "/usr/sbin/sh" "/bin/ksh" "/usr/bin/ksh" "/bin/bash" "/usr/bin/bash"; do
if test -f "$p"; then
found=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $p" >&5
$as_echo "$p" >&6; }
cat >>confdefs.h <<EOF
#define _PATH_BSHELL "$p"
EOF
break
fi
done
Cette boucle recherchera /bin/bash
, /usr/bin/sh
, /sbin/sh
, /usr/sbin/sh
ou /bin/ksh
et définira ensuite le _PATH_BSHELL
sur selon celui trouvé en premier . Étant donné que /bin/sh
était le premier de la liste et qu'elle existe, _PATH_BSHELL
est défini sur /bin/sh
. Le résultat de tout cela est que le shell par défaut de Sudo
name__, sauf indication contraire, est /bin/sh
.
Donc, Sudo
utilisera par défaut /bin/sh
et, sous Ubuntu, un lien symbolique vers dash
name__, un shell minimal compatible POSIX:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 27 2015 /bin/sh -> dash
La construction [[
est une fonctionnalité bash, elle n'est pas définie par le standard POSIX et n'est pas comprise par dash
name__:
$ bash -c '[[ true ]] && echo yes'
yes
$ dash -c '[[ true ]] && echo yes'
dash: 1: [[: not found
En détail, dans les trois invocations que vous avez essayées:
./test.sh
Non Sudo
name__; En l'absence d'une ligne Shebang, votre shell tentera d'exécuter le fichier lui-même. Puisque vous exécutez bash
name__, ceci exécutera effectivement bash ./test.sh
et fonctionnera.
Sudo su
suivi de ./test.sh
.
Ici, vous démarrez un nouveau shell pour l'utilisateur root
name__. Ce sera ce que Shell sera défini dans la variable d'environnement $Shell
pour cet utilisateur et, sous Ubuntu, le shell par défaut de la racine sera bash
name__:
$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
Sudo ./test.sh
Ici, vous laissez Sudo
exécuter directement la commande. Comme son shell par défaut est /bin/sh
comme expliqué ci-dessus, le script est alors exécuté avec /bin/sh
, qui est dash
et échoue car dash
ne comprend pas [[
.
Remarque : les détails de la manière dont Sudo
définit le shell par défaut semblent un peu plus complexes. J'ai essayé de changer les fichiers mentionnés dans ma réponse pour qu'ils pointent vers /bin/bash
mais Sudo
était toujours par 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 (Sudo
par défaut à sh
name__) est toujours valable.