我每次执行脚本时都试图编写一个小脚本来挂载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
答案 0 :(得分:44)
许多答案都集中在如何使您的解决方案有效,而很少有人建议您的解决方案是非常糟糕方法。如果你真的想练习学习"为什么不练习使用好的解决方案呢?硬编码密码正在学习错误的方法!
如果您真正想要的是该卷的无密码mount
,那么 可能不需要sudo
!我可以建议其他方法吗?
建议使用/etc/fstab
作为mensi。使用选项user
和noauto
让常规用户装载该卷。
使用Polkit
进行无密码操作:使用.policy
为您的脚本配置<allow_any>yes</allow_any>
文件,然后放在/usr/share/polkit-1/actions
修改/etc/sudoers
以允许您的用户在不输入密码的情况下使用sudo
。
以上所有内容都允许无密码root权限,不需要您对密码进行硬编码。选择任何方法,我可以更详细地解释它。
至于为什么硬编码密码是个坏主意,这里有一些很好的链接可供进一步阅读:
答案 1 :(得分:28)
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')
答案 2 :(得分:16)
将密码传递给sudo
的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]
注意:您可以配置无密码sudo或SUDO_ASKPASS
命令,而不是在源代码中硬编码密码。
答案 3 :(得分:3)
subprocess.Popen
创建一个进程并打开管道和东西。你在做什么:
sudo -S
mypass
mount -t vboxsf myfolder /home/myuser/myfolder
显然不会起作用。你需要将参数传递给Popen。如果你看一下its documentation,你会发现第一个参数实际上是一个参数列表。
答案 4 :(得分:3)
在sudo命令中使用-S选项,它告诉从'stdin'而不是终端设备读取密码。
告诉Popen从PIPE读取stdin。
通过将密码用作通信方法的参数,将密码发送到进程的stdin PIPE。不要忘记在密码末尾添加一个换行符号'\ n'。
sp = Popen(cmd , shell=True, stdin=PIPE)
out, err = sp.communicate(_user_pass+'\n')
答案 5 :(得分:1)
请尝试模块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 !")
答案 6 :(得分:1)
要限制您作为sudo运行的内容,您可以运行
python non_sudo_stuff.py
sudo -E python -c "import os; os.system('sudo echo 1')"
无需存储密码。 -E
参数将当前用户的env传递给进程。请注意,在第二个命令之后,shell将具有sudo priveleges,因此请谨慎使用!
答案 7 :(得分:0)
有时需要回车:
os.popen("sudo -S %s"%(command), 'w').write('mypass\n')
答案 8 :(得分:0)
我知道不要在脚本中硬编码sudo密码。但是,出于某种原因,如果您无权修改/etc/sudoers
或更改文件所有者,则Pexpect是一种可行的替代方案。
这是一个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
答案 9 :(得分:0)
我将它用于python 3.5。我是使用 subprocess 模块完成的。使用这样的密码非常不安全。
subprocess模块将命令作为字符串列表,因此要么事先使用 split()创建列表,要么稍后传递整个列表。阅读文档以获取更多信息。
<activity
android:name="com.google.android.gms.ads.AdActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
tools:replace="android:theme"
/>
答案 10 :(得分:0)
它适用于python 2.7和3.8:
from subprocess import Popen, PIPE
from shlex import split
proc = Popen(split('sudo -S %s' % command), bufsize=0, stdout=PIPE, stdin=PIPE, stderr=PIPE)
proc.stdin.write((password +'\n').encode()) # write as bytes
proc.stdin.flush() # need if not bufsize=0 (unbuffered stdin)
如果缓冲了stdin,则没有.flush()
的密码将不会达到sudo
。
在python 2.7中,Popen
默认使用bufsize=0
,而stdin.flush()
则不需要。
为了安全使用,请在受保护的目录中创建密码文件:
mkdir --mode=700 ~/.prot_dir
nano ~/.prot_dir/passwd.txt
chmod 600 ~/.prot_dir/passwd.txt
从〜/ .prot_dir / passwd.txt开始,您的py脚本读取密码
with open(os.environ['HOME'] +'/.prot_dir/passwd.txt') as f:
password = f.readline().rstrip()