我正在尝试使用python为我的团队编写一些组件测试,然后我遇到了一个测试程序,它告诉测试人员来源csh文件。这个文件有一堆setenv命令和别名。链中的下一个可执行文件需要所有这些环境变量。我想设计一些方法来提取所有的env变量并将它们传递给链中的下一个过程。
我看了下面的问题,这几乎是我需要的: Emulating Bash 'source' in Python
它将所有导出的bash环境变量推送到字典中,然后我可以将其传递给下一个进程。问题是这似乎只适用于export
而不适用于csh setenv
命令。
如果无法做到这一点,是否有办法使用子进程命令(如/bin/sh -c script.csh
)运行.csh文件,然后运行需要这些环境变量作为该进程的子进程的进程(以便它可以继承它的环境变量吗?)
基本上,我有一个包含一系列setenv变量的进程和脚本,并且该进程需要在包含所有这些环境变量的环境中运行。
感谢您的帮助,
答案 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.txt
和after.txt
,看看环境发生了哪些变化。 (或者您可以通过其他方式捕获输出。)这样做的好处是让调用进程看到修改后的环境,或者至少获取有关它的信息。
请注意,在某些特殊情况下,您可能无法从printenv
的输出中确定环境。例如,如果$FOO
的值为"10\nBAR=20"
,则该值将显示在printenv
的输出中:
FOO=10
BAR=20
看起来像$FOO
10
而$BAR
是20
。 (在环境变量值中添加换行符实际上并不少见;我的$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