J'essaye donc d'obtenir un processus à exécuter en tant que super utilisateur à partir d'un script python utilisant un sous-processus. Dans le shell ipython quelque chose comme
proc = subprocess.Popen('Sudo apach2ctl restart',
Shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
fonctionne bien, mais dès que je le colle dans un script, je commence à obtenir: Sudo: apach2ctl: command not found
.
Je suppose que cela est dû à la façon dont Sudo gère les environnements sur Ubuntu. (J'ai aussi essayé Sudo -E apche2ctl restart
et Sudo env path=$PATH Apache2ctl restart
sans succès)
Donc, ma question est essentiellement, si je veux exécuter Apache2ctl restart
en tant que super utilisateur qui invite l'utilisateur à saisir son mot de passe en cas de besoin, comment dois-je procéder? Je n'ai aucune intention de stocker des mots de passe dans le script.
Modifier:
J'ai essayé de passer les commandes en tant que chaîne et en jetons dans une liste. Dans l'interpréteur python, avec une chaîne, j'obtiendrai l'invite de mot de passe correctement (ne fonctionne toujours pas dans un script python comme dans mon problème d'origine), un liste donne simplement l'écran d'aide pour Sudo.
Modifier 2:
Donc, ce que je comprends, c'est que même si Popen fonctionnera avec certaines commandes comme des chaînes lorsque Shell = True, cela prendra
proc = subprocess.Popen(['Sudo','/usr/sbin/Apache2ctl','restart'])
sans 'Shell = True' pour faire fonctionner Sudo.
Merci!
Essayez de donner le chemin complet vers Apache2ctl.
Essayer:
subprocess.call(['Sudo', 'apach2ctl', 'restart'])
Le sous-processus doit accéder au vrai stdin/out/err pour qu'il puisse vous inviter et lire votre mot de passe. Si vous les définissez en tant que canaux, vous devez saisir vous-même le mot de passe dans ce canal.
Si vous ne les définissez pas, alors il saisit sys.stdout, etc ...
Une autre façon consiste à rendre votre utilisateur sans mot de passe Sudo user
.
Tapez ce qui suit sur la ligne de commande:
Sudo visudo
Ajoutez ensuite ce qui suit et remplacez le <username>
avec votre:
<username> ALL=(ALL) NOPASSWD: ALL
Cela permettra à l'utilisateur d'exécuter la commande Sudo
sans avoir à demander de mot de passe (y compris l'application lancée par ledit utilisateur. Cela pourrait cependant être un risque pour la sécurité
Vous devez utiliser Popen comme ceci:
cmd = ['Sudo', 'Apache2ctl', 'restart']
proc = subprocess.Popen(cmd, Shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Il attend une liste.
Je l'ai utilisé pour python 3.5. Je l'ai fait en utilisant le module sous-processus). mot de passe comme celui-ci est très peu sûr .
Le module sous-processus prend la commande comme une liste de chaînes donc créez une liste au préalable en utilisant split () ou passez la liste entière plus tard. Lisez la documentation pour plus d'informations.
Ce que nous faisons ici est l'écho du mot de passe, puis en utilisant le tube nous le transmettons au Sudo via l'argument '-S'.
#!/usr/bin/env python
import subprocess
Sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()
cmd1 = subprocess.Popen(['echo',Sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['Sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)
output = cmd2.stdout.read().decode()
J'ai essayé toutes les solutions, mais cela n'a pas fonctionné. Je voulais exécuter des tâches de longue durée avec Celery mais pour celles-ci, j'avais besoin d'exécuter la commande Sudo chown avec subprocess.call ().
C'est ce qui a fonctionné pour moi:
Pour ajouter des variables d'environnement sûr, en ligne de commande, tapez:
export MY_Sudo_PASS="user_password_here"
Pour tester si cela fonctionne:
echo $MY_Sudo_PASS
> user_password_here
Pour l'exécuter au démarrage du système, ajoutez-le à la fin de ce fichier:
nano ~/.bashrc
#.bashrc
...
existing_content:
Elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
...
export MY_Sudo_PASS="user_password_here"
Vous pouvez ajouter tous vos mots de passe, noms d'utilisateur, hôtes, etc. de variables d'environnement ici plus tard.
Si vos variables sont prêtes, vous pouvez exécuter:
Mettre à jour:
echo $MY_Sudo_PASS | Sudo -S apt-get update
Ou pour installer Midnight Commander
echo $MY_Sudo_PASS | Sudo -S apt-get install mc
Pour démarrer Midnight Commander avec Sudo
echo $MY_Sudo_PASS | Sudo -S mc
Ou depuis python Shell (ou Django/Celery), pour changer récursivement la propriété du répertoire:
python
>> import subprocess
>> subprocess.call('echo $MY_Sudo_PASS | Sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', Shell=True)
J'espère que ça aide.
La façon la plus sûre de procéder consiste à demander le mot de passe au préalable, puis à le diriger vers la commande. Demander le mot de passe évitera d'avoir le mot de passe enregistré n'importe où dans votre code et il n'apparaîtra pas non plus dans votre historique bash. Voici un exemple:
from getpass import getpass
from subprocess import Popen, PIPE
password = getpass("Please enter your password: ")
# Sudo requires the flag '-S' in order to take input from stdin
proc = Popen("Sudo -S apach2ctl restart".split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())