以 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"
。
我的限制:
- 文件可以是任何格式:文本、图片、视频等,因此我无法对其进行解码。
- 我无法将文件创建为
root
和 chown
到 userA
因为即使 root 也无法访问该位置。
在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 脚本。
我正在尝试将字节写入文件。一般来说,可以简单地做:
...
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
和chown
到userA
因为即使 root 也无法访问该位置。
在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 脚本。