web-dev-qa-db-fra.com

exécution d'une commande en tant que super utilisateur à partir d'un script python

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!

40
Silfheed

Essayez de donner le chemin complet vers Apache2ctl.

15
dwc

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 ...

25
Mike Boers

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é

12
Michael Loo

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.

5
Harley Holcombe

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() 
4
Nandesh

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.

1
jturi

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())
1
Josh Correia