用Python脚本使用sudo

我试图写一个小脚本来挂载一个VirtualBox共享文件夹,每次我执行脚本。 我想用Python来做,因为我正在尝试学习脚本。

问题是我需要启动mount命令的权限。 我可以运行脚本作为sudo,但我更喜欢它自己做sudo。

我已经知道把你的密码写入一个.py文件是不安全的,但是我们正在谈论的是一个并不重要的虚拟机:我只是想点击.py脚本来让它工作。

这是我的尝试:

#!/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) 

我的Python版本是2.6

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

试试这个,让我知道如果它的作品。 🙂

和这个:

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

许多答案着重于如何使你的解决scheme工作,而很less有人提出你的解决scheme是一个非常糟糕的方法 。 如果你真的想“练习学习”,为什么不练习使用好的解决scheme呢? 硬编码您的密码正在学习错误的方法!

如果你真的想要的是一个无密码的mount量,也许sudo根本就不需要! 那么我可以build议其他方法吗?

  • 用mensibuild议使用/etc/fstab 。 使用选项usernoauto让普通用户挂载该卷。

  • 使用Polkit进行无密码操作:使用<allow_any>yes</allow_any>为脚本configuration.policy文件,然后放在/usr/share/polkit-1/actions

  • 编辑/etc/sudoers以允许你的用户使用sudo而不用input你的密码。

以上所有都允许使用无密码的root权限,但不要求您对密码进行硬编码。 select任何方法,我可以更详细地解释它。

将密码传递给sudo的标准input:

 #!/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] 

注意:你可以configuration无密码的sudo或SUDO_ASKPASS命令,而不是在源代码中硬编码你的密码。

subprocess.Popen进程subprocess.Popen创build一个进程并打开pipe道和东西。 你在做什么是:

  • 开始一个进程sudo -S
  • 启动一个进程mypass
  • 启动进程mount -t vboxsf myfolder /home/myuser/myfolder

这显然不起作用。 你需要把论据传递给Popen。 如果你看看它的文档 ,你会注意到第一个参数实际上是一个参数列表。

有时需要回车:

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

请尝试模块pexpect。 这是我的代码:

 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 !") 

我知道总是不要在脚本中硬编码sudo密码。 但是,由于某种原因,如果您没有权限修改/etc/sudoers或更改文件所有者,则Pexpect是可行的select。

这是一个Python函数sudo_exec供您参考:

 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 
  • 在sudo命令中使用-S选项,它告诉从“stdin”而不是terminal设备读取密码。

  • 告诉Popen从PIPE读取stdin。

  • 通过使用它作为参数来传递方法,将密码发送到进程的stdin PIPE。 不要忘记在密码末尾添加一个新的行字符'\ n'。

 sp = Popen(cmd , shell=True, stdin=PIPE) out, err = sp.communicate(_user_pass+'\n')