web-dev-qa-db-fra.com

Exécuter un script Shell dans le Shell actuel avec l'autorisation Sudo

Pour exécuter un script Shell dans le Shell actuel, nous devons utiliser une commande . ou source Mais pourquoi cela ne fonctionne-t-il pas avec une permission Sudo?

J'ai un script avec une autorisation d'exécution appelée setup.sh. Quand j'utilise un point, j'obtiens ceci:

$ Sudo . ./setup.sh 
Sudo: .: command not found

La commande source produit également une erreur similaire. Est-ce que je manque quelque chose? Que dois-je faire pour exécuter le script avec l'autorisation Sudo dans le même shell?

Merci d'avance..

34
shar

Ce que vous essayez de faire est impossible. votre Shell actuel fonctionne sous votre ID utilisateur habituel (c'est-à-dire que, sans root, l'accès Sudo vous donnerait), et il n'y a aucun moyen de lui accorder un accès root . Sudo crée un nouveau processus * sub * qui s'exécute en tant que root. Le sous-processus peut être simplement un programme standard (par exemple, Sudo cp ... exécute le programme cp dans un processus racine) ou un sous-shell racine, mais il ne peut pas ne pas être le shell actuel.

(En réalité, il est encore plus impossible que cela, car la commande Sudo est elle-même exécutée en tant que sous-processus du shell actuel - ce qui signifie qu'il est déjà trop tard pour qu'il puisse faire quoi que ce soit dans le "shell actuel", il s'exécute.)

25
Gordon Davisson

Je ne sais pas si cela enfreint les règles, mais 

Sudo bash script.sh

semble fonctionner pour moi. 

85
JaseC

Je pense que vous ne comprenez pas la différence entre rechercher et exécuter un script.

L'exécution d'un script signifie créer un nouveau processus et exécuter le programme. Le programme peut être un script Shell ou tout autre type de programme. S'agissant d'un sous-processus, toute variable d'environnement modifiée dans le programme n'affectera pas Shell.

La création d'un script ne peut être utilisée qu'avec un script bash (si vous exécutez bash). Il tape efficacement les commandes comme si vous les aviez faites. Ceci est utile car il permet à un script de modifier les variables d'environnement dans le shell.


L'exécution d'un script est simple, il vous suffit de taper le chemin d'accès au script. . est le répertoire en cours. Donc, ./script.sh exécutera le fichier script.sh dans le répertoire en cours. Si la commande est un fichier unique (par exemple, script.sh), tous les dossiers de la variable PATH seront vérifiés pour trouver le script. Notez que le répertoire actuel n’est pas dans PATH, vous ne pouvez donc pas exécuter un fichier script.sh dans le répertoire actuel en exécutant script.sh. Vous devez exécuter ./script.sh (à moins que le répertoire actuel ne se trouve dans PATH, par exemple, vous pouvez exécuter ls en le /bin dir).

La recherche d'un script n'utilise pas PATH, elle recherche simplement le chemin. Notez que source n'est pas un programme - sinon, il ne serait pas possible de modifier les variables d'environnement dans le shell actuel. Il s’agit en fait d’une commande construite par bash. Recherchez /bin et /usr/bin - vous n'y trouverez pas de programme source. Donc, pour créer un fichier script.sh dans le répertoire en cours, il suffit d'utiliser source script.sh


Comment Sudo interagit-il avec cela? Bien Sudo prend un programme et l’exécute en tant que root. Par exemple, Sudo ./script.sh exécute script.sh dans un sous-processus mais en tant que root.

Que fait Sudo source ./script.sh cependant? Rappelez-vous source n'est pas un programme (plutôt un shell intégré)? Sudo attend cependant un nom de programme et recherche donc un programme nommé source. Il n'en trouve pas et échoue. Il n'est pas possible de créer un fichier fonctionnant en tant que root sans créer de nouveau sous-processus, car vous ne pouvez pas modifier le programme d'exécution du programme (dans ce cas, bash) après son démarrage.

Je ne suis pas sûr de ce que vous vouliez réellement, mais j'espère que cela vous éclaircira.


Voici un exemple concret. Créez le fichier script.sh dans votre répertoire actuel avec le contenu:

#!/bin/bash    
export NEW_VAR="hello"
whoami
echo "Some text"

Rendez-le exécutable avec chmod +x script.sh.

Observez maintenant ce qui se passe avec bash:

> ./script.sh
david
Some text
> echo $NEW_VAR

> Sudo ./script.sh
root
Some text
> echo $NEW_VAR

> source script.sh
david
Some text
> echo $NEW_VAR
hello
> Sudo source script.sh
Sudo: source: command not found
29
David Miani

En principe, Sudo attend un exécutable (commande) à suivre et vous fournissez un .

D'où l'erreur.

Essayez ceci $ Sudo setup.sh 


5
loxxy

Même la première réponse est absolument brillante, vous voudrez probablement exécuter uniquement le script sous Sudo.

Vous devez spécifier le chemin absolu comme:

Sudo /home/user/example.sh
Sudo ~/example.sh

(les deux fonctionnent)

CELA NE FONCTIONNERA PAS!

Sudo /bin/sh example.sh
Sudo example.sh

Il reviendra toujours

Sudo: bin/sh: command not found
Sudo: example.sh: command not found
0
Martin Kovaľ

Si tu veux vraiment "ExecuteAppeler un script Shell dans le Shell actuel avec l'autorisation Sudo "vous pouvez utiliser exec pour ...

remplace le shell par un programme donné (en l'exécutant, pas en tant que nouveau processus)

J'insiste sur le remplacement de "execute" par "call" car le premier a un sens qui inclut la création d'un nouveau processus et d'une nouvelle ID, où le second est ambigu et laisse une place à la créativité, dont je suis plein. 

Considérez ce cas test et examinez de près le pid 1337

# Don't worry, the content of this script is cat'ed below
$ ./test.sh -o foo -p bar

User ubuntu is running...
 PID TT       USER     COMMAND
 775 pts/1    ubuntu   -bash
1408 pts/1    ubuntu    \_ bash ./test.sh -o foo -p bar
1411 pts/1    ubuntu        \_ ps -t /dev/pts/1 -fo pid,tty,user,args

User root is running...
 PID TT       USER     COMMAND
 775 pts/1    ubuntu   -bash
1337 pts/1    root      \_ Sudo ./test.sh -o foo -p bar
1412 pts/1    root          \_ bash ./test.sh -o foo -p bar
1415 pts/1    root              \_ ps -t /dev/pts/1 -fo pid,tty,user,args

Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)

#!/usr/bin/env bash

echo; echo "User $(whoami) is running..."
ps -t $(tty) -fo pid,tty,user,args

if [[ $EUID > 0 ]]; then
    # exec replaces the current process effectively ending execution so no exit is needed.
    exec Sudo "$0" "$@"
fi

echo; echo "Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)"; echo
cat $0

Voici un autre test utilisant Sudo -s

$ ps -fo pid,tty,user,args; ./test2.sh
  PID TT       USER     COMMAND
10775 pts/1    ubuntu   -bash
11496 pts/1    ubuntu    \_ ps -fo pid,tty,user,args

User ubuntu is running...
  PID TT       USER     COMMAND
10775 pts/1    ubuntu   -bash
11497 pts/1    ubuntu    \_ bash ./test2.sh
11500 pts/1    ubuntu        \_ ps -fo pid,tty,user,args

User root is running...
  PID TT       USER     COMMAND
11497 pts/1    root     Sudo -s
11501 pts/1    root      \_ /bin/bash
11503 pts/1    root          \_ ps -fo pid,tty,user,args

$ cat test2.src
echo; echo "User $(whoami) is running..."
ps -fo pid,tty,user,args

$ cat test2.sh
#!/usr/bin/env bash

source test2.src

exec Sudo -s < test2.src

Et un test plus simple en utilisant Sudo -s

$ ./exec.sh
bash's PID:25194    user ID:7809
systemd(1)───bash(23064)───bash(25194)───pstree(25196)

Finally...
bash's PID:25199    user ID:0
systemd(1)───bash(23064)───Sudo(25194)───bash(25199)───pstree(25201)

$ cat exec.sh
#!/usr/bin/env bash

pid=$$
id=$(id -u)
echo "bash's PID:$pid    user ID:$id"
pstree -ps $pid

# the quoted EOF is important to prevent Shell expansion of the $...
exec Sudo -s <<EOF
echo
echo "Finally..."
echo "bash's PID:\$\$    user ID:\$(id -u)"
pstree -ps $pid
EOF
0
Bruno Bronosky