【问题标题】:Run a shell command from Django从 Django 运行 shell 命令
【发布时间】:2011-03-03 11:57:35
【问题描述】:

我正在 Django 中开发一个网页(使用 apache 服务器),它需要调用一个 shell 命令来启用/禁用一些守护进程。我正在尝试使用

os.system(service httpd restart 1>$HOME/out 2>$HOME/error)

并且此命令不返回任何内容。知道如何解决这个问题吗?

【问题讨论】:

    标签: python django apache


    【解决方案1】:

    这是我用于从我的一个 django 应用程序启动进程的代码:

      import subprocess
      process = subprocess.Popen(['python', 'manage.py', 'some_command'])
    

    在你的情况下是:

    import subprocess     
    process = subprocess.Popen(['service', 'httpd', 'restart'])
    

    (您还需要处理 stdout 和 stderr - 不确定是否添加 '1>$HOME/out')适用于 Popen。有documentation for subprocess

    【讨论】:

    • 为什么要使用subprocess 而不是内置的Django call_command 方法来运行./manage.py some_command?在此处查看完整的建议解决方案:*.com/a/40063425/1224827
    【解决方案2】:

    尝试在 Shell 中运行命令:

    import subprocess
    r = subprocess.call("service httpd restart 1>$HOME/out 2>$HOME/error", shell=True)
    

    【讨论】:

    • 参数的正确拼写是“shell”,而不是“Shell”。
    【解决方案3】:

    我将跳过我强烈建议您关于让 Web 应用程序启动和停止系统进程的含义的部分,并尝试回答这个问题。

    您的 django 应用程序不应使用 root 用户运行,这可能是启动和停止服务所必需的。您可以通过以下方式克服这个问题:

    • 创建一个使用seteuid的脚本
    • 为该文件设置 uid 属性

    脚本类似于

    #!/usr/bin/python <- or wherever your python interpreter is
    import os
    os.seteuid(0)
    os.system("service httpd restart 1>$HOME/out 2>$HOME/error")
    

    要允许将有效 UID 设置为 root (0),您必须在 shell 中以 root 身份运行:

    chown root yourscript.py
    chmod u+s yourscript.py
    chmod a+x yourscript.py
    

    应该这样做。在您的 Django 应用程序中,您现在可以调用 os.system('yourscript.py') 以使用 root 权限运行命令。

    最后,我相信您传递给os.system() 的命令不是您想要的,因为您谈论启用和禁用守护进程,而您所做的只是重新启动 apache... turn 似乎是你的 django 正在运行的地方,所以在实践中你会杀死你自己的 webapp。

    【讨论】:

    • 这对大多数用户不起作用,因为出于安全原因,脚本中不允许 seteuid 操作。如果它确实有效,任何人都可以执行 "python -c 'import os; os.setuid(0);os.setgid(0);os.system("sh")'" 来获得一个 root shell!