从Python子进程模块启动模块Shell命令

1 投票
3 回答
3453 浏览
提问于 2025-04-16 23:57

我正在尝试运行VNC服务器,但在此之前我需要先执行一个命令:'module load vnc'。

如果我在已经加载的bash终端中输入 which module,系统会提示找不到这个命令,虽然它实际上是可以用的。这看起来像是一个内置命令。

换句话说,我似乎需要同时执行两个命令 module load vnc;vncserver :8080 -localhost,而我正在写一个脚本来从Python启动它。

我尝试了不同的方式使用 subprocess.Popen,比如:

subprocess.Popen('module load vnc;vncserver :8080 -localhost', shell=True) 

结果返回了 127 的退出代码,或者提示 command not found

subprocess.Popen('module load vnc;vncserver :8080 -localhost', shell=False)

显示了

File <path>/subprocess.py line 621, in \__init__    
                                   errread, errwrite)
OSError: [Errno 2] No such file or directory.

如果我指定 shell=True,它会从 /bin/sh 执行,但我需要的是从 /bin/bash 执行。

指定 executable='/bin/bash' 并没有帮助,因为它加载了一个新的bash终端,但它是以字符串的形式启动,而不是作为一个进程,也就是说,我在 ps 列表中看到的命令和我想要启动的命令是完全一样的。

请问你能给我一些建议,如何通过subprocess模块启动这个命令吗?是否可以在 shell=False 的情况下启动它?

3 个回答

0

你可以在Python脚本中使用module这个命令。这个module命令是由一种叫做环境模块的软件提供的,它还提供了一个叫python.py的初始化脚本。

在Python脚本中运行这个初始化脚本,就可以启用module这个Python功能。如果环境模块安装在/usr/share/Modules这个路径下,你可以在/usr/share/Modules/init/python.py找到这个脚本。

下面的代码可以启用module的Python功能:

import os
exec(open('/usr/share/Modules/init/python.py').read())

之后,你就可以加载你的模块并启动你的应用程序了:

module('load', 'vnc')
subprocess.Popen(['vncserver', ':8080', '-localhost'])
0

如果你想在不使用 shell=False 的情况下实现这个功能,可以把它分成两个 Popen 调用。

subprocess.check_call('module load vnc'.split())
subprocess.Popen('vncserver :8080 -localhost'.split())
2

环境模块通常只是为你修改几个环境变量。其实你可以完全跳过 module load whatever 这一步,直接不依赖这些模块。我建议

subprocess.Popen(['/possibly/path/to/vncserver', ':8080', '-localhost'], 
                 env={'WHATEVER': 'you', 'MAY': 'need'})

根本就不要加载这个模块。

如果你还是想用这种基本的方法,那你可以自己启动 bash,使用 Popen(['bash',...

撰写回答