web-dev-qa-db-ger.com

Verwenden von Sudo mit Python-Skript

Ich versuche, ein kleines Skript zu schreiben, um bei jeder Ausführung des Skripts einen gemeinsam genutzten VirtualBox-Ordner bereitzustellen. Ich möchte es mit Python machen, weil ich versuche, es für das Scripting zu lernen.

Das Problem ist, dass ich Berechtigungen zum Starten des Mount-Befehls benötige. Ich könnte das Skript als Sudo ausführen, aber ich bevorzuge es, Sudo für sich allein zu machen.

Ich weiß bereits, dass es nicht sicher ist, Ihr Kennwort in eine .py-Datei zu schreiben, aber wir sprechen hier von einer virtuellen Maschine, die überhaupt nicht kritisch ist: Ich möchte nur auf das .py-Skript klicken, damit es funktioniert.

Das ist mein Versuch:

#!/usr/bin/env python
import subprocess

sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'

subprocess.Popen('Sudo -S' , Shell=True,stdout=subprocess.PIPE)
subprocess.Popen(sudoPassword , Shell=True,stdout=subprocess.PIPE)
subprocess.Popen(command , Shell=True,stdout=subprocess.PIPE)

Meine Python-Version ist 2.6

28
Roman Rdgz
sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'
p = os.system('echo %s|Sudo -S %s' % (sudoPassword, command))

Probieren Sie es aus und lassen Sie es mich wissen, wenn es funktioniert. :-)

Und das hier:

os.popen("Sudo -S %s"%(command), 'w').write('mypass')

31
Aniket Inge

Viele Antworten konzentrieren sich darauf, wie Sie Ihre Lösung zum Laufen bringen können, während nur wenige darauf hinweisen, dass Ihre Lösung ist ein sehr schlechter Ansatz. Wenn Sie wirklich "üben lernen wollen", warum sollten Sie nicht mit guten Lösungen üben? Durch das Festcodieren Ihres Passworts wird der Ansatz von falsch gelernt!

Wenn Sie wirklich ein passwortloses mount für dieses Volume wünschen, wird Sudo möglicherweise nicht benötigt überhaupt! Darf ich andere Ansätze vorschlagen?

  • Verwenden Sie /etc/fstab als mensi vorgeschlagen. Verwenden Sie die Optionen user und noauto, damit reguläre Benutzer dieses Volume mounten können.

  • Verwenden Sie Polkit für passwortlose Aktionen: Konfigurieren Sie eine .policy-Datei für Ihr Skript mit <allow_any>yes</allow_any> und legen Sie sie unter /usr/share/polkit-1/actions ab.

  • Bearbeiten Sie /etc/sudoers, damit Ihr Benutzer Sudo verwenden kann, ohne Ihr Kennwort einzugeben.

Alle oben genannten Berechtigungen erlauben ein kennwortloses Root-Privileg. Sie müssen Ihr Kennwort jedoch nicht hartcodieren. Wählen Sie einen Ansatz und ich kann ihn näher erläutern.

Für warum ist es eine sehr schlechte Idee, Kennwörter fest zu codieren. Hier sind ein paar gute Links zum Lesen:

40
MestreLion

So übergeben Sie das Passwort an Sudos stdin:

#!/usr/bin/env python
from subprocess import Popen, PIPE

Sudo_password = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()

p = Popen(['Sudo', '-S'] + command, stdin=PIPE, stderr=PIPE,
          universal_newlines=True)
Sudo_Prompt = p.communicate(Sudo_password + '\n')[1]

Hinweis: Sie können möglicherweise den Sudo- oder Sudo_ASKPASS-Befehl ohne Kennworteingabe konfigurieren, anstatt Ihr Kennwort im Quellcode fest zu codieren.

16
jfs
  • Verwenden Sie die Option -S im Sudo-Befehl, um das Kennwort von 'stdin' anstelle des Endgeräts zu lesen.

  • Sagen Sie Popen, dass er stdin von PIPE lesen soll.

  • Senden Sie das Kennwort an die Standard-PIPE des Prozesses, indem Sie es als Argument für die Kommunikationsmethode verwenden. Vergessen Sie nicht, am Ende des Passworts ein neues Zeilenzeichen '\ n' hinzuzufügen.

sp = Popen(cmd , Shell=True, stdin=PIPE)
out, err = sp.communicate(_user_pass+'\n')   
3
Hubert Vijay

subprocess.Popen erstellt einen Prozess und öffnet Pipes und so. Was Sie tun, ist:

  • Prozess starten Sudo -S
  • Prozess starten mypass
  • Prozess starten mount -t vboxsf myfolder /home/myuser/myfolder

das wird offensichtlich nicht funktionieren. Sie müssen die Argumente an Popen übergeben. Wenn Sie seine Dokumentation betrachten, werden Sie feststellen, dass das erste Argument tatsächlich eine Liste der Argumente ist.

3
mensi

Bitte versuchen Sie es mit dem Modul pexpect. Hier ist mein Code:

import pexpect
remove = pexpect.spawn('Sudo dpkg --purge mytool.deb')
remove.logfile = open('log/expect-uninstall-deb.log', 'w')
remove.logfile.write('try to dpkg --purge mytool\n')
if remove.expect(['(?i)password.*']) == 0:
    # print "successfull"
    remove.sendline('mypassword')
    time.sleep(2)
    remove.expect(pexpect.EOF,5)
else:
    raise AssertionError("Fail to Uninstall deb package !")
1
user2951688

Um zu begrenzen, was Sie als Sudo ausführen, können Sie laufen

python non_Sudo_stuff.py
Sudo -E python -c "import os; os.system('Sudo echo 1')"

ohne das Passwort speichern zu müssen. Der Parameter -E übergibt die Env des aktuellen Benutzers an den Prozess. Beachten Sie, dass Ihre Shell nach dem zweiten Befehl über Sudo-Berechtigungen verfügt. Gehen Sie also vorsichtig vor!

1
crizCraig

manchmal eine Wagenrückgabe erforderlich: 

os.popen("Sudo -S %s"%(command), 'w').write('mypass\n')
0
user2095717

Ich weiß, es ist immer vorzuziehen, das Sudo-Passwort im Skript nicht fest zu codieren. Wenn Sie jedoch nicht berechtigt sind, /etc/sudoers zu ändern oder den Besitzer der Datei zu ändern, ist Pexpect aus irgendeinem Grund eine mögliche Alternative.

Hier ist eine Python-Funktion Sudo_exec als Referenz:

import platform, os, logging
import subprocess, pexpect

log = logging.getLogger(__name__)

def Sudo_exec(cmdline, passwd):
    osname = platform.system()
    if osname == 'Linux':
        Prompt = r'\[Sudo\] password for %s: ' % os.environ['USER']
    Elif osname == 'Darwin':
        Prompt = 'Password:'
    else:
        assert False, osname

    child = pexpect.spawn(cmdline)
    idx = child.expect([Prompt, pexpect.EOF], 3)
    if idx == 0: # if prompted for the Sudo password
        log.debug('Sudo password was asked.')
        child.sendline(passwd)
        child.expect(pexpect.EOF)
return child.before
0
Jeremy Kao

Ich habe dies für Python 3.5 verwendet. Ich habe es mit dem Modul subprocess gemacht. Die Verwendung dieses Passworts ist sehr unsicher.

Das Modul subprocess nimmt den Befehl als Liste von Strings an. Erstellen Sie also zuvor eine Liste mit split () oder übergeben Sie die gesamte Liste später. Lesen Sie die Dokumentation für weitere Informationen.

#!/usr/bin/env python
import subprocess

sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()

cmd1 = subprocess.Popen(['echo',sudoPassword], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['Sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)

output = cmd2.stdout.read.decode()
0
Nandesh