以 Python 中的不同用户身份写入文件

Write to a file as a different user in Python

我正在尝试将字节写入文件。一般来说,可以简单地做:

...
fb = file.read() # this contains the bytes to copy

with open("/tmp/", "wb") as out:
    out.write(fb)

它工作得很好,但我正在努力让它与 subprocess 一起工作。为什么?因为我需要在不同用户的所有权下创建输出文件 - 比如 userA。我看到的唯一可能的方法是用户模拟。下面的例子:

# runs as root

import subprocess

def run(cmd, **kwargs):
    popen = subprocess.Popen(
        cmd.split(),
        stdout=kwargs.pop("stdout", subprocess.PIPE),
        stderr=kwargs.pop("stderr", subprocess.PIPE),
        user=kwargs.get("user")
    )
    popen.communicate()


dst = "/data/userA" # special (network) location that only userA can access (not even root)
byte_data = file.read() # this contains the bytes to copy
user = "userA"

with open(dst, mode="wb") as out_f:
    cmd = f"echo -n {byte_data}"
    run(cmd=cmd, user=user, stdout=out_f)

如果我发送一个txt文件,我的内容是b"text content"

我的限制:

在shell中,sudo tee有时用于替代输出重定向以确保正确的用户打开文件。

# Instead of sudo -u user foo > tmp.txt
foo | sudo -u user tee tmp.txt > /dev/null

您可以在 Python 中做同样的事情。请注意 subprocess.Popen 本身可以直接从您的输入文件中读取;你不需要构造一个人工命令。

# tee writes to any named files *and* standard output; by default,
# you probably want to redirect standard output to /dev/null
# or the equivalent.
def copy_to(src, dest_name, user, *, stdout=subprocess.devnull, **kwargs):
    subprocess.run(["tee", dest_name], user=user, stdin=src, **kwargs)

copy_to(file, "/data/userA", "userA")

本质上,这个 copy_to 只是 subprocess.run 的包装器,它使用给定的输入文件、输出文件 name 运行 tee,和用户。任何其他关键字参数将直接传递给 subprocess.run.

关键是 tee 打开输出文件进行写入,而不是您的 Python 脚本。