You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下如何用Python以非root用户免密执行sudo命令

解决Python项目中免密执行sudo service命令的问题

问题场景

我在开发一个Python项目时遇到了这样的问题:项目需要执行sudo命令查询MongoDB服务的运行状态,现有代码用sudo python3 app.py启动时能正常返回active(running)或inactive(dead)这类状态结果,但直接用python3 app.py运行时,终端会反复要求输入当前用户的密码,我希望实现免密执行这些特定的sudo命令。

我的现有代码如下:

cmd = "sudo service mongodb status > " + status_logs
subprocess.call(cmd, shell=True)
cmd = "grep \'" + search_tag + "\' " + status_logs
status_string = str(subprocess.check_output(cmd, shell=True))
start = status_string.index(":") + len(":")
end = status_string.index(')', start)
status = status_string[start:end]
status = status + ")"
status = status.replace(" ", "")

附当前的/etc/sudoers文件内容:

This file MUST be edited with the 'visudo' command as root.
Please consider adding local content in /etc/sudoers.d/ instead of
directly modifying this file.
See the man page for details on how to write a sudoers file.

Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin: /usr/bin:/sbin:/bin:/snap/bin"

Host alias specification
User alias specification
Cmnd alias specification
User privilege specification

root ALL=(ALL:ALL) ALL

Members of the admin group may gain root privileges

%admin ALL=(ALL) ALL

Allow members of group sudo to execute any command

%sudo ALL=(ALL:ALL) ALL

See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d


解决方案:配置sudo免密权限

要实现免密执行service mongodb status命令,你需要修改sudo的权限配置,这里推荐两种安全的方式:

方式一:直接修改sudoers文件(需用visudo)

  • 打开sudoers配置文件(必须用visudo命令,它会做语法检查,避免配置错误导致sudo失效):
    sudo visudo
    
  • 在文件末尾添加一行内容,替换your_username为你的实际用户名:
    your_username ALL=(ALL) NOPASSWD: /usr/sbin/service mongodb status
    

    注意:必须写service命令的绝对路径,你可以用which service命令确认路径,通常是/usr/sbin/service。

  • 保存并退出:按Esc键,输入:wq后回车。

方式二:使用sudoers.d目录(更推荐,避免修改主配置文件)

sudo允许将自定义配置放在/etc/sudoers.d/目录下,这样不会污染主sudoers文件:

  • 创建一个新的配置文件:
    sudo touch /etc/sudoers.d/mongodb-status
    
  • 编辑这个文件:
    sudo nano /etc/sudoers.d/mongodb-status
    
  • 在文件中添加同样的内容(替换your_username):
    your_username ALL=(ALL) NOPASSWD: /usr/sbin/service mongodb status
    
  • 保存退出(按Ctrl+O,回车,再按Ctrl+X),然后修改文件权限为sudo要求的0440:
    sudo chmod 0440 /etc/sudoers.d/mongodb-status
    

代码优化建议(可选)

你的现有代码使用了shell=True和临时日志文件,存在一定安全风险(如果search_tag来自外部输入可能引发命令注入),同时用字符串索引提取状态也不够健壮(服务输出格式变化时会出错)。推荐优化后的代码:

import subprocess
import re

def get_mongodb_status():
    try:
        # 使用绝对路径的service命令,避免shell=True,直接捕获输出
        result = subprocess.check_output(
            ['sudo', '/usr/sbin/service', 'mongodb', 'status'],
            stderr=subprocess.STDOUT,
            text=True
        )
        # 用正则表达式匹配状态,更健壮
        status_match = re.search(r':\s*(active\(running\)|inactive\(dead\))', result)
        if status_match:
            # 去除空格返回结果
            return status_match.group(1).replace(" ", "")
        else:
            return "无法识别服务状态"
    except subprocess.CalledProcessError as e:
        return f"命令执行失败: {e.output.strip()}"

# 调用示例
print(get_mongodb_status())

这个版本的代码更安全,也不需要临时文件,正则匹配的方式能更好地适应服务输出格式的微小变化。


内容的提问来源于stack exchange,提问作者S Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:02:31