在Python脚本中使用sudo

61
我正在尝试编写一个小脚本,每次执行该脚本时都会挂载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


不使用“/etc/fstab”的原因是什么? - mensi
1
@mensi 是的,我正在练习使用Python来实现这种目的。 - Roman Rdgz
1
你需要通过标准输入传递密码,查看此链接 https://dev59.com/HHVC5IYBdhLWcg3w2lGI#165662。 - Eun
2
如果你不知道自己在做什么,就避免使用shell=True。如果你不能在没有它的情况下使事情正常工作,那就学习它是什么以及它是如何工作的(然后通常你就可以了)。 - tripleee
这个回答解决了你的问题吗?从Python脚本以超级用户身份运行命令 - miken32
14个回答

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

0
import os 
os.system("echo TYPE_YOUR_PASSWORD_HERE | sudo -S TYPE_YOUR_LINUX_COMMAND")

打开你的IDE并运行上面的代码。请将TYPE_YOUR_PASSWORD_HERE和TYPE_YOUR_LINUX_COMMAND更改为你的Linux管理员密码和所需的Linux命令,然后运行你的Python脚本。你的输出将显示在终端上。愉快编程 :)


0

我选择的解决方案是,在开发电脑上将密码以明文形式放在环境文件中是可以的,而在代码库和GitLab Runner中使用变量进行掩码处理。

使用 .dotenv 将密码放在本地机器的 .env 文件中,不要将 .env 提交到 Git 中。 在 GitLab 变量中添加相同的变量。

.env 文件包含:
PASSWORD=superpass

from dotenv import load_dotenv
load_dotenv()

subprocess.run(f'echo {os.getenv("PASSWORD")} | sudo -S rm  /home//folder/filetodelete_created_as_root.txt', shell=True, check=True)

这在本地和GitLab中都可以工作。没有明文密码提交到仓库。

是的,你可以争论运行一个带有shell true的sudo命令有点疯狂,但如果你需要从一个具有root权限的docker写入主机文件,并且需要以编程方式删除它们,那么这是可行的。


由于您的回答目前写得不清楚,请[编辑]以添加更多细节,帮助其他人了解它如何回答提出的问题。您可以在帮助中心找到有关撰写良好答案的更多信息。 - user11717481

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)

如果没有使用.flush(),密码将无法到达sudo,因为stdin被缓冲。

在Python 2.7中,默认情况下使用Popenbufsize=0,不需要使用stdin.flush()

为了安全起见,在受保护的目录中创建密码文件:

mkdir --mode=700 ~/.prot_dir
nano ~/.prot_dir/passwd.txt
chmod 600 ~/.prot_dir/passwd.txt 

在开始时,您的Python脚本从~/.prot_dir/passwd.txt读取密码

with open(os.environ['HOME'] +'/.prot_dir/passwd.txt') as f:
    password = f.readline().rstrip()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接