在Python脚本中,以不同的用户身份执行“ls”命令

3
大家好,以下是我想做的事情:我的脚本将以root身份运行,我希望能够以不同的用户身份执行各种命令(例如ls、rm、touch等)。
我的问题在于使用preexec_fn=os.setuid(userid))会将父进程的userid也设置为该值。请问有什么建议吗?是否preexec_fn不适用于此目的?另外需要指出的是,这需要按照twisted的方式实现(我可能不太了解)。是否getProcessOutputAndValue是正确的方法?如果是,如何实现类似这样的操作?
print 'uid is %s' % os.getuid()
cmdstr = ['ls']
process = subprocess.Popen(cmdstr,stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setuid(10033))
print 'uid of parent after child startup is %s' % os.getuid()
process.wait()
print 'uid of parent after child finished is %s' % os.getuid()

输出:

uid is 0
uid of parent after child startup is 10033
uid of parent after child finished is 10033

为什么你不使用 os.listdir (用于列出目录内容), os.utime (用于修改文件时间戳), shutil (用于删除文件或目录) 或 os.remove ) ? - kurumi
Kurumi,因为我需要以提供的用户身份执行这些命令(实际上是在NFS目录上)。有没有办法让os.listdir作为特定用户/用户ID执行? - helpmelearn
你的意思是想以root身份运行脚本,但是以用户身份运行命令?我认为通常情况下,你会使用sudo或su来实现这个目的。你可以使用sudo切换到用户身份,然后执行Python脚本。 - kurumi
@kurumi,这正是我的意思。我以root身份运行脚本,而我需要以另一个用户的身份运行ls/rm命令(因为操作将在一个NFS文件上进行,我实际上想通过执行该用户/userid的ls/rm命令来验证权限)。 - helpmelearn
2个回答

5
你的问题在于当你只想传递一个回调函数给Popen时,却意外地调用了preexec_fn。
尝试使用以下代码替代:
def my_preexec_fn():
    os.setuid(10033)
process = subprocess.Popen(cmdstr,stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=my_preexec_fn)

哎呀,那真是一个简单的修复。谢谢。我想这是 Python 的一个小缺陷,没有捕捉到 preexec_fn 没有设置为可调用对象这一事实 —— 照我写的,它将被设置为 os.setuid(10033) 的返回值,这是 'NoneType'! - helpmelearn
helpmelearn,你把rlibby的答案标记为“最佳答案”,但你没有点赞它(既然它很有用,你应该点赞它 :))。 - tzot
@TZ:我曾尝试过那样做,但当时我还没有那个能力(我对这个网站还太新了)。 :) - helpmelearn

1

rlibby的回答是正确和充分的,但我想添加以下选项来创建回调:

import functools as ft
my_preexec_fn= ft.partial(os.setuid, 10033)

@TZ:我不知道这里的partial是什么意思。而且文档也没有很好地解释它(在我看来)。你能否详细说明一下?谢谢。 - helpmelearn
@helpmelearn:假设有一个函数callable,它需要两个参数arg1和arg2。 partial=functools.partial(callable,arg1)分配了一个“部分”可调用对象,只需要arg2即可。以operator.mul为例,它是一个接受两个参数的乘法运算符。mult3=functools.partial(operator.mul,3)将会分配给mult3一个仅需要一个参数的可调用对象,返回值为参数乘以3。 - tzot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接