首页 > 解决方案 > 是 sudo 和脚本中的用户

问题描述

我有一个 python 脚本,它必须在有和没有 sudo 以及不同的命令开关的情况下按顺序运行。

顺序是由于每个部分都依赖于上一部分所做的更改,并且使用 sudo 运行的部分需要 sudo 运行,而其他部分不应使用 sudo 运行。

一个大大减少的 3 部分示例脚本来说明这些部分,需要 root/sudo,不需要 root/sudo

#!/usr/bin/env python

import os
import sys


def update():
    if os.geteuid() != 0:
        print("The --config function must run as root.")
        raise SystemExit(0)

    print("About to upgrade your OS")
    os.system("apt-get -y update; apt-get -y dist-upgrade")


def build():
    if os.geteuid() == 0:
        print("This function should not be run as root.")
        raise SystemExit(0)

    if not os.path.isdir("source"):
        os.system("git clone https://path.to/source/source.git")
    else:
        os.system("(chdir source; git pull)")
    os.chdir("source")
    os.system("make")


def install():
    "Install software & start service " \
        "once everything has been tested."
    if os.geteuid() != 0:
        print("The --install function must run as root.")
        raise SystemExit(0)

    os.chdir("source")
    os.system("make install")
    os.system("systemctl daemon-reload")
    os.system("systemctl enable software.service")
    
if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in ("--update", "--build", "--install":
        raise SystemExit(1)
    
    if sys.argv[1] == "--update":
        update()
    if sys.argv[1] == "--build":
        build()
    if sys.argv[1] == "--install":
        install()

# end

当前方法

sudo ./script --update
./script --build
sudo ./script --install

有没有办法让单个脚本可以使用 sudo 运行,但随后可以作为使用 sudo 运行脚本的非 root 用户执行某些部分?

我想达到什么

sudo ./script

然后在 sudo 下运行“更新”,作为运行“sudo ./script”的用户运行“构建”,在 sudo 下运行“安装”等。

无法使用另一个脚本来调用每个现有命令,因为在运行其中一个部分时会达到 sudo 超时,并且出于政治原因无法更改超时。

tl:dr 是否可以使用 sudo 运行 python 脚本,将 python 脚本放到普通用户运行部分脚本,然后返回以 sudo 运行?

标签: pythonsudo

解决方案


您可以使用subprocess.call(command, user = "me")if python >= 3.9 或在命令前加上sudo -U normal_userif not。

# start with sudo ./script

from os.path import realpath
import sys, subprocess

script = realpath(sys.argv[0])

# parsing command line for sections omitted

# execute_section functions omitted

if section:
    return execute_section(section)

# execution of sections

# python >= 3.9
execute_section("section1") # executed as root
subprocess.call([script, "--session2"], user = "me")
execute_section("section3") # executed as root
subprocess.call([script, "--session4"], user = "me")
execute_section("section5") # executed as root

对于 python < 3.9,使用类似:

subprocess.call(["sudo", "-U", "me", script, "--session2"])

您还可以使用fabric中的Invoke库。

为了在 python 中构建一个完整、高效的构建系统,我使用waf


推荐阅读