将 sudo 与 Python 脚本结合使用

2025-01-07 08:44:00
admin
原创
146
摘要:问题描述:我正在尝试编写一个小脚本,以便每次执行该脚本时挂载 VirtualBox 共享文件夹。我想用 Python 来做这件事,因为我正在尝试学习它来编写脚本。问题是我需要权限才能启动 mount 命令。我可以用 sudo 运行该脚本,但我更喜欢自己使用 sudo。我已经知道将密码写入.py 文件并不安全,...

问题描述:

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


解决方案 1:

许多答案都集中在如何使您的解决方案有效,而很少有人认为您的解决方案是一种非常糟糕的方法。如果您真的想“实践学习”,为什么不练习使用好的解决方案呢?硬编码您的密码是学习错误的方法!

mount如果您真正想要的是该卷的无密码,那么可能根本sudo不需要!那么我可以建议其他方法吗?

  • /etc/fstab按照mensi 的建议使用。使用选项usernoauto让普通用户安装该卷。

  • 用于无密码操作:使用以下命令为您的脚本Polkit配置文件并放入.policy`<allow_any>yes</allow_any>`/usr/share/polkit-1/actions

  • 编辑/etc/sudoers以允许您的用户使用sudo而无需输入密码。正如@Anders所建议的,您可以将此类使用限制为特定命令,从而避免您的帐户中存在无密码的无限根权限。有关 的更多详细信息,请参阅此答案/etc/sudoers

以上所有方法都允许无密码 root 权限,无需您硬编码密码。选择任何一种方法,我都可以更详细地解释。

至于为什么编码密码是一个非常糟糕的想法,下面有几个不错的链接可供进一步阅读:

  • 为什么编程时不应该硬编码密码

  • 如何保守秘密(硬编码密码的替代方案)

  • 哪种方式更安全?硬编码凭证还是将其存储在数据库中?

  • 使用硬编码凭证是一种危险的编程错误:CWE

  • 硬编码密码仍然是一个关键的安全漏洞

解决方案 2:

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')

解决方案 3:

将密码传递给sudo的标准输入:

#!/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 + '
')[1]

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

解决方案 4:

  • 在 sudo 命令中使用 -S 选项,它告诉从“stdin”而不是终端设备读取密码。

  • 告诉 Popen 从 PIPE 读取 stdin。

  • 将密码作为参数发送到通信方法,发送到进程的 stdin PIPE。不要忘记在密码末尾添加换行符“\n”。

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

解决方案 5:

subprocess.Popen创建一个进程并打开管道等。您要做的就是:

  • 启动进程sudo -S

  • 启动进程mypass

  • 启动进程mount -t vboxsf myfolder /home/myuser/myfolder

这显然行不通。您需要将参数传递给 Popen。如果您查看其文档,您会注意到第一个参数实际上是参数列表。

解决方案 6:

我在 python 3.5 中用过这个。我使用subprocess模块来实现。像这样使用密码非常不安全

subprocess模块将命令作为字符串列表,因此可以使用split()预先创建列表,或稍后传递整个列表。阅读文档了解更多信息。

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

解决方案 7:

有时需要回车:

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

解决方案 8:

请尝试模块 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
')
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 !")

解决方案 9:

要限制以 sudo 身份运行的内容,您可以运行

python non_sudo_stuff.py
sudo -E python -c "import os; os.system('sudo echo 1')"

无需存储密码。该-E参数将您当前用户的环境传递给进程。请注意,您的 shell 在第二个命令后将具有 sudo 权限,因此请谨慎使用!

解决方案 10:

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 脚本。您的输出将显示在终端上。祝您编码愉快 :)

解决方案 11:

我知道最好不要在脚本中硬编码 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

解决方案 12:

它适用于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 +'
').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 

在启动你的 py 脚本时从 ~/.prot_dir/passwd.txt 读取密码

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

解决方案 13:

您可以使用SSHScript。以下是示例代码:

## filename: example.spy 
sudoPassword = 'mypass'
command = 'mount -t vboxsf myfolder /home/myuser/myfolder'
$$echo @{sudoPassword} | sudo -S @{command}

或者,只需一行(几乎与在控制​​台上运行相同)

## filename: example.spy 
$$echo mypass | sudo -S mount -t vboxsf myfolder /home/myuser/myfolder

然后在控制台上运行它

sshscript example.spy

其中“sshscript”是 SSHScript 的 CLI(由 pip 安装)。

解决方案 14:

我正在采用的解决方案是,因为开发电脑上环境文件中纯文本格式的密码是可以的,并且 repo 和 gitlab 运行器中的变量被屏蔽了。

使用 .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 中均可行。无需向 repo 提交明文密码。

是的,您可以争辩说运行 sudo 命令 w shell tr​​ue 有点疯狂,但如果您有从 docker w root 写入主机的文件,并且您需要以编程方式删除它们,那么这是可行的。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用