2015-11-05 143 views
0

我试图编写一个用于构建某些软件的python包装器。我需要使用不同的配置自动创建数百次,这意味着我不能只是autogen.sh ; ./configure ; make ; make install。我使用的一些配置需要运行有条件地设置一些环境变量的脚本。我要的是能够做这样的事情:运行多个shell命令并等待结果的Python脚本

command = './autogen.sh' 
ret = subprocess.call(command.split()) 
if ret != 0: 
    sys.exit(ret) 

command = './script.sh ; ./configure <configure-flags>' 
ret = subprocess.call(command.split()) 
if ret != 0: 
    sys.exit(ret) 

command = 'make' 
ret = subprocess.call(command.split()) 
if ret != 0: 
    sys.exit(ret) 

command = 'make install' 
ret = subprocess.call(command.split()) 
if ret != 0): 
    sys.exit(ret) 

我遇到的问题是,在script.sh设置环境变量没有得到保存configure。我在Sending multiple commands to a bash shell which must share an environment中看到了部分解决方案,但涉及将命令刷新到stdin并轮询一个结果,当您有一个非常长的makefile时(我的大约需要10-20分钟),它不会真正起作用,它也不会给出你是我需要知道的构建是否成功的返回值。

有没有人知道更好的方法来做到这一点?

回答

0

这里的基本问题是环境变量只能“向下”(从父到子)复制,从不“向上”(从子到父)。你的python脚本是父母。它运行一个shell命令,因此它是一个孩子; shell运行更多命令,这些命令是shell的子进程(因此也是Python进程的孙子)。

为了使环境变量保持不变,您需要以某种方式向上导入它们。究竟是如何取决于你。一个常用的技术(在shell脚本和Python中使用)是让导出器打印它想要设置的值,然后让shell或Python进程读取输出并进行设置。 (我看这就是你链接到的确实后)

例如,子进程可能会打印:

CONFIG_PATH=/path/to/config/file 

(或export添加相同),然后外壳只会eval这个。这意味着很大的信任:如果孩子的过程打印rm -rf /例如?在执行之前,可以将规则(例如正则表达式匹配)应用于输出,甚至可以手动(或自动)分析它,但在验证步骤之后才执行结果。

另一种方法是将配置写入文件,并让父文件读取该文件。这是几乎相同的技术,但使用通信软件仓库的文件,而不是摆弄stdin和stdout。它还有几个问题(命名文件,并知道何时读取它)。

(有,当然,用Python编写的许多构建和/或测​​试框架。我不会推荐任何一种特定的,因为我没有跟他们说太多的经验。)

+0

我实际上不是所有的挑剔环境从一个'调用(被保存)'到另一个。我只需在每个'call()'中调用安装脚本即可。 –

+0

“如果子进程打印'rm -rf /'”如果子进程直接执行'rm -rf /'怎么办? –

+0

@thatotherguy:的确如此。 :-)然而,我正考虑使用较窄的通信渠道来运行更多的大型系统,这些系统可以隔离(不同的UID,甚至可以在不同的虚拟机上运行)等子项。 – torek

1

如果你有一个脚本来设置你想要访问的变量,你必须提供它(类似于其他语言所称的“include”)。

而不是

command = './script.sh ; ./configure <configure-flags>' 
ret = subprocess.call(command.split()) 

你可以做

command = ["bash", "-c", "source script.sh; ./configure"] 
subprocess.call(command) 
相关问题