在python中使用SubAccess自动从普通用户切换到根用户

在python中使用SubAccess自动从普通用户切换到根用户,python,postgresql,shell,python-2.7,subprocess,Python,Postgresql,Shell,Python 2.7,Subprocess,问题: def popen_cmd_shell(command): print command process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)

问题:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist
我试图执行一个cmd,它从PostgreSQL数据库读取数据。我可以手动切换到root,然后切换到postgre用户并访问我想要的信息

我的问题是,当我运行它时,它只是挂起,什么也没发生

我有根密码,从当前用户切换时需要此密码,但没有提示我输入

我如何才能使其不挂起并提示密码

为了简单起见,下面的代码只执行“ls”

代码:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist
更新一个:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist
我无法在Linux SUSE上使用python 2.7以外的任何库。我只需要执行一个命令并退出

更新二:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist
我无法以root身份运行脚本,因为我需要执行其他要求我不是root的任务

更新三个:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist
根据勒巴顿的建议,我已经获得了登录到root的脚本,尽管ls命令从未作为root用户执行,但它是以我最初的用户身份执行的。当我运行该命令时,系统会提示我输入根密码,并将其从“@host”传输到“host”,而“host”只能执行exit命令。退出时,将显示所有已执行的命令输出

我不希望将用户密码存储在代码中,因为LeBarton拥有它。我如何以root用户身份执行命令并返回并继续脚本的其余部分,而不被锁定到新用户中并需要键入“exit”

“stderr=subprocess.STDOUT”似乎是导致它挂起的原因

代码:

回答:

def popen_cmd_shell(command):
    print command
    process = subprocess.Popen(command,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

    proc_stdout = process.communicate()[0].strip()    
    return proc_stdout

if __name__ == '__main__':
    querylist = popen_cmd_shell('su - root; ls;')

    print querylist
感谢tripleee的出色回答

我已经实现了我开始使用以下代码的目标:

if __name__ == '__main__':
    def subprocess_cmd(command):
        process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=False)
        proc_stdout = process.communicate()[0].strip()
        print proc_stdout

    subprocess_cmd(['su','-','root','-c','su -s /bin/sh  postgres -c \'psql -U msa ..........])

我只需要将我作为root用户执行的命令放在-c之后。因此,它现在切换到postgres用户,并在返回到正常用户后从root用户中查找所需的数据。

您是否只想访问PostgreSQL数据库?如果是这样,您根本不需要使用命令行

Python库psycopg2将允许向PostgreSQL server发送命令,更多信息如下:

然而,我建议使用诸如SQLAlchemy之类的ORM,它们使与数据库通信成为一项琐碎的任务。

您的命令如下

su - root; ls;
shell将其解释为

"su -root; ls;"
您可能没有在您的可执行文件中使用带空格的确切名称

尝试使用将其拆分为as列表

['su', '-', 'root', ';', 'ls', ';' ]
编辑


stdout=subprocess.PIPE,
导致程序挂起。如果您试图传入密码,请使用
process.communication('root password')
工作。

您误解了
su
的功能
su
创建特权子流程;它不会更改当前进程的权限。
su
之后的命令将在
su
完成后以您的正常权限执行

相反,您希望传递一个
-c
选项来指定要以提升的权限运行的命令。(另请参见。)

sudo
是专门为简化这类事情而设计的,因此您可能应该改用它

对特权命令的脚本化访问是一个棘手的话题。一种常见的方法是让您的命令执行特权操作,然后放弃其特权。从安全性和设计的角度来看,这种方法倾向于简化总体逻辑。您需要确保您的特权代码尽可能简单和简短——例如,在特权部分不进行解析

一旦特权代码得到正确的测试、审核和冻结,授予脚本所需的特权应该是一件简单的事情(尽管许多组织都是偏执狂,基本上无法为此类事情建立可行的策略)

无论采用哪种方法,在任何安全敏感上下文中都应该避免使用
shell=True
,而是将任何外部命令作为列表而不是单个字符串传递

popen_cmd_shell(['su', '-c', 'ls', '-', 'root'])
(也可以重命名函数,因为您特别不需要shell。显然,也可以将函数更改为指定
shell=False


同样,无论您是删除权限,还是通过
su
sudo

请求权限提升,这些安全问题都是有用的。为什么不简单地创建脚本,然后使用sudo以root用户身份运行脚本呢?您甚至不需要root来访问数据库。(1)您应该能够在不切换到root的情况下访问数据库。如果您不知道如何使用,请专门询问一个单独的问题(2)为了避免被询问root密码,请使用
sudo
,您可以将其配置为以root用户身份运行命令,而无需密码:
output=check_output(['sudo',get db data.sh'])
。在我的系统上,只需将一行文件放入
/etc/sudoers.d/
目录(3)就足够了。如果您需要传递根密码,但希望避免在源代码中对其进行硬编码,则可以使用
root\u password=getpass.getpass('root password:')
在运行时请求密码。否,您不应该在POSIX上使用带有
shell=True
的列表参数。不,
.communicate(input)
将不起作用,除非
stdin=PIPE
。此外,如果
su
直接从终端(而不是从stdin)接受密码,则它将不起作用。