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
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')
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:
So übergeben Sie das Passwort an Sudo
s 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.
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')
subprocess.Popen
erstellt einen Prozess und öffnet Pipes und so. Was Sie tun, ist:
Sudo -S
mypass
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.
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 !")
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!
manchmal eine Wagenrückgabe erforderlich:
os.popen("Sudo -S %s"%(command), 'w').write('mypass\n')
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
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()