I’m trying to write a small script to mount a VirtualBox shared folder each time I execute the script. I want to do it with Python, because I’m trying to learn it for scripting.
The problem is that I need privileges to launch mount command. I could run the script as sudo, but I prefer it to make sudo by its own.
I already know that it is not safe to write your password into a .py file, but we are talking about a virtual machine that is not critical at all: I just want to click the .py script and get it working.
This is my attempt:
#!/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)
My python version is 2.6
sudoPassword = 'mypass' command = 'mount -t vboxsf myfolder /home/myuser/myfolder' p = os.system('echo %s|sudo -S %s' % (sudoPassword, command))
Try this and let me know if it works. 🙂
And this one:
os.popen("sudo -S %s"%(command), 'w').write('mypass')
Many answers focus on how to make your solution work, while very few suggest that your solution is a very bad approach. If you really want to “practice to learn”, why not practice using good solutions? Hardcoding your password is learning the wrong approach!
If what you really want is a password-less
mount for that volume, maybe
sudo isn’t needed at all! So may I suggest other approaches?
/etc/fstabas mensi suggested. Use options
noautoto let regular users mount that volume.
Polkitfor passwordless actions: Configure a
.policyfile for your script with
<allow_any>yes</allow_any>and drop at
/etc/sudoersto allow your user to use
sudowithout typing your password. As @Anders suggested, you can restrict such usage to specific commands, thus avoiding unlimited passwordless root priviledges in your account. See this answer for more details on
All the above allow passwordless root privilege, none require you to hardcode your password. Choose any approach and I can explain it in more detail.
As for why it is a very bad idea to hardcode passwords, here are a few good links for further reading:
- Why You Shouldn’t Hard Code Your Passwords When Programming
- How to keep secrets secret
(Alternatives to Hardcoding Passwords)
- What’s more secure? Hard coding credentials or storing them in a database?
- Use of hard-coded credentials, a dangerous programming error: CWE
- Hard-coded passwords remain a key security flaw
To pass the password to
#!/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')
Note: you could probably configure passwordless sudo or
SUDO_ASKPASS command instead of hardcoding your password in the source code.
Use -S option in the sudo command which tells to read the password from ‘stdin’ instead of the terminal device.
Tell Popen to read stdin from PIPE.
Send the Password to the stdin PIPE of the process by using it as an argument to communicate method. Do not forget to add a new line character, ‘n’, at the end of the password.
sp = Popen(cmd , shell=True, stdin=PIPE) out, err = sp.communicate(_user_pass+'n')
subprocess.Popen creates a process and opens pipes and stuff. What you are doing is:
- Start a process
- Start a process
- Start a process
mount -t vboxsf myfolder /home/myuser/myfolder
which is obviously not going to work. You need to pass the arguments to Popen. If you look at its documentation, you will notice that the first argument is actually a list of the arguments.
I used this for python 3.5. I did it using subprocess module.Using the password like this is very insecure.
The subprocess module takes command as a list of strings so either create a list beforehand using split() or pass the whole list later. Read the documentation for moreinformation.
#!/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()
sometimes require a carriage return:
os.popen("sudo -S %s"%(command), 'w').write('mypassn')
Please try module pexpect. Here is my 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 mytooln') 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 !")