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

发布于 2025-01-16 11:14:12 字数 1189 浏览 3 评论 0原文

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

...
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"

我的限制:

  • 文件可以是任何格式:文本、图像、视频等,因此我无法解码它。
  • 我无法以 root 身份创建该文件并将其 chownuserA,因为即使 root 也无法访问该位置。

I am trying to write bytes to a file. Generally, one could simply do:

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

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

It works perfectly, but I am trying to make it work with subprocess. Why? Because I need the output file to be created under the ownership of a different user - say userA. And the only way possible I am seeing is user impersonation. An example below:

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

If I send a txt file, my content is b"text content".

My limitations:

  • File can be of any format: text, images, video, etc. therefore I can't decode it.
  • I can't create the file as root and chown it to userA since not even root can access that location.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

远昼 2025-01-23 11:14:12

在 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 的包装器,它使用给定的输入文件、输出文件名称运行tee em> 和用户。任何其他关键字参数都将直接传递给 subprocess.run

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

In shell, sudo tee is sometimes used to replace output redirection to ensure that the correct user opens the file.

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

You can do the same thing in Python. Note that subprocess.Popen itself can read directly from your input file; you don't need to construct an artificial command.

# 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")

Essentially, this copy_to is just a wrapper around subprocess.run that runs tee using the given input file, output file name, and user. Any other keyword arguments will be passed directly to subprocess.run.

The key is that tee opens the output file for writing, not your Python script.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文