Python获取CSH并将setenv传递给新的子进程

时间:2013-05-24 22:12:21

标签: python testing subprocess csh

我正在尝试使用python为我的团队编写一些组件测试,然后我遇到了一个测试程序,它告诉测试人员来源csh文件。这个文件有一堆setenv命令和别名。链中的下一个可执行文件需要所有这些环境变量。我想设计一些方法来提取所有的env变量并将它们传递给链中的下一个过程。

我看了下面的问题,这几乎是我需要的: Emulating Bash 'source' in Python

它将所有导出的bash环境变量推送到字典中,然后我可以将其传递给下一个进程。问题是这似乎只适用于export而不适用于csh setenv命令。

如果无法做到这一点,是否有办法使用子进程命令(如/bin/sh -c script.csh)运行.csh文件,然后运行需要这些环境变量作为该进程的子进程的进程(以便它可以继承它的环境变量吗?)

基本上,我有一个包含一系列setenv变量的进程和脚本,并且该进程需要在包含所有这些环境变量的环境中运行。

感谢您的帮助,

4 个答案:

答案 0 :(得分:0)

您考虑过John Kugelman's solution了吗? 那将是最简单的方法。

但是,如果由于某种原因,您需要或希望Python成为这些脚本之间的中介,那么您可以使用以下内容来获取脚本并检索环境变量。 (编辑:感谢abarnert和Keith Thompson提供正确的csh命令。)

如果script.csh包含

setenv foo bar

然后

import subprocess
import os
import json
PIPE = subprocess.PIPE
output = subprocess.check_output(
    '''source script.csh; python -c "import os, json; print(json.dumps(dict(os.environ)))"''',
    shell=True, executable='/bin/csh')
env = json.loads(output)
print(env['foo'])

产量

bar

答案 1 :(得分:0)

执行此操作的最简单方法是让csh获取安装脚本,然后运行其他脚本。例如:

setup.csh:

setenv foo bar

script.csh:

echo $foo

runner.py:

import subprocess
csh_command = 'source ./setup.csh && ./script.csh'
subprocess.check_call(['/bin/csh', '-c', csh_command])

如果您只想使用链接问题中的代码,您只需更改正则表达式即可。只需将export替换为setenv,将=替换为\s+

答案 2 :(得分:0)

因此script.csh包含设置某些环境变量的setenv命令。

/bin/sh -c script.csh只会执行脚本;一旦脚本完成,环境变量就会丢失。即使这假设script.csh是可执行的;如果它的意思是来源,它不必是,也可能不应该是。

要使环境变量设置可见,script.csh必须由csh进程来源

这是一个粗略的概述:

/bin/csh -c 'source script.csh ; python -c ...'

python -c ...进程将能够查看环境变量。执行上述命令的进程不会。

更复杂的解决方案是这样的:

printenv > before.txt
/bin/csh -c 'source script.csh ; printenv' > after.txt

然后比较before.txtafter.txt,看看环境发生了哪些变化。 (或者您可以通过其他方式捕获输出。)这样做的好处是让调用进程看到修改后的环境,或者至少获取有关它的信息。

请注意,在某些特殊情况下,您可能无法从printenv的输出中确定环境。例如,如果$FOO的值为"10\nBAR=20",则该值将显示在printenv的输出中:

FOO=10
BAR=20

看起来像$FOO 10$BAR20。 (在环境变量值中添加换行符实际上并不少见;我的$TERMCAP当前设置为21行的文本块。

您可以通过编写自己的printenv替换来避免这种情况,该替换打印出明确的环境表示。

答案 3 :(得分:0)

这对我来说可以从Shell脚本(调用其他Shell脚本)获取环境。您可以执行类似的操作将环境读入字典,然后使用os.environ更改环境。

    import subprocess

    SAPENVCMD = "/bin/csh -c \'source ~/.cshrc && env\'"
    envdict = {}

    def runcommand(command):
        ps = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        out,err = ps.communicate()
        outlist = out.split('\n')
        if ps.returncode == 0:
           return outlist
        else:
           return None

    def elist2dict(dict,list):
        for entry in list:
            if entry is not None:
               pos = entry.find('=')
               key = entry[:pos]
               pos += 1
               value = entry[pos:]
               dict.setdefault(key,value)

    def env2dict(dict,ENVCMD):
        envlist = runcommand(ENVCMD)
        elist2dict(dict,envlist)


    env2dict(envdict,SAPENVCMD)

    v = envdict["SAPSYSTEMNAME"]
    print v