我正在使用 Runtime.getRuntime().exec(...) 从 Tomcat web 应用程序中执行 python 脚本。当我在我的开发环境中时一切都很顺利(Eclipse 通过 Sysdeo-Plugin 运行我的本地 Tomcat(位于 /home/me/opt/tomcat))。当我在生产环境(= Debian Squeeze)中运行我的 web 应用程序时,会出现此问题。
我使用的是官方 debian 软件包中的 tomcat6。它使用用户“tomcat6”通过 /etc/init.d 自动启动(使用“ps aux | grep tomcat6”验证)。我正在执行我的简单 python 脚本:
Process p = Runtime.getRuntime().exec("python /home/me/exec-test.py")
p.waitFor();
//read the stdout and stderr
Python 脚本很简单:
#!/usr/bin/python
import sys, os, getpass
def main(argv):
print "Working dir: " +os.getcwd()
userShell = os.environ.get('SHELL')
print "$SHELL set to: " +userShell
print "Executing as user: "+getpass.getuser()
if __name__ == "__main__":
main(sys.argv[1:])
如果从 eclipse 运行 tomcat 的输出是:
Working dir: /home/me/opt/tomcat
$SHELL set to: /bin/bash
Executing as user: me
当使用 debian 包中的 tomcat6 运行时:
Working dir: /var/lib/tomcat6
$SHELL set to: /bin/bash
Executing as user: root
为什么是分叉执行python脚本以“root”身份运行?难道不应该是拥有 tomcat6 进程(=运行 JVM)的同一个用户吗?我是否遗漏了某些内容,或者获取进程用户的 python 调用不正确?
我也尝试过使用 Apache Commons Exec 得到相同的结果。
结果是,当我使用一个更复杂的 python 脚本来调用本地应用程序(/usr/local/bin/local-app),它在生产环境中失败。它不知何故无法访问本地应用程序。同样,在我的开发环境中一切正常。这与我的观察有关吗?
问题在于, Tomcat 进程自身并没有以 root 身份启动 Python 脚本,而是继承了启动 Tomcat 的用户的权限 。
在你的生产环境中,Tomcat 是以 root 身份启动的 (使用
/etc/init.d
),这是一种常见的做法,以便 Tomcat 可以绑定到特权端口(例如 80 和 443)。 然而,
即使 Tomcat 本身以 root 身份运行,它也会降低其子进程的权限
,包括你的 Java 代码启动的 Python 脚本。
你的 Python 脚本显示为以 root 身份运行的原因是你的
/etc/init.d
启动脚本没有明确地将用户切换到
tomcat6
。因此,启动的 Python 脚本继承了启动脚本的权限,即 root 用户。
为了解决这个问题,你需要修改你的
/etc/init.d
脚本,以便在启动 Tomcat 之前将用户切换到
tomcat6
。 你可以使用
su
或者
sudo
命令来实现这一点。以下是一个使用
su
命令的示例:
# ... 其他启动脚本内容 ...
su - tomcat6 -c "/usr/bin/java ... [Tomcat 启动命令]"
# ... 其他启动脚本内容 ...
修改完启动脚本后,重启 Tomcat,然后再次运行你的 web 应用程序。 现在,你的 Python 脚本应该会以
tomcat6
用户的身份运行,并且你应该能够访问
/usr/local/bin/local-app
。
此外,为了安全起见, 不建议以 root 身份运行 Tomcat 。 如果你不需要绑定到特权端口,最好配置 Tomcat 以使用非特权用户运行。
标签:java,python,tomcat,debian,exec From: 15925481