在python脚本中设置环境变量,并运行相关应用

1. 问题

在自动化应用的时候 ,有时候环境变量与运行需要不一致。这时候有两种选择:

  1. 改变节点环境变量,使得其和运行需求保持一致;
  2. 在自动化脚本中设置环境变量,其范围只在脚本运行环境中有效。

显然,当需要运行多个自动化脚本,每个的需求不一致的时候,选择2是更好的设计。

2. 解决方案和案例

假设我们有两个java的运行版本,一个是本节点上的java,版本7;另一个是云盘上共享的版本8。我们需要运行elasticsearch 6.2.3,它需要java8。而我们不希望更新节点上的java:

  • java 8路径:/shared/java8/bin
  • elasticsearch 6.2.3路径:/opt/elasticsearch6.2.3/bin
  •  elasticsearch用户:elasticsearch
import subprocess, re, os, socket, resource, pwd, crypt, logging, sys, platform

def demote(user_uid, user_gid):
def result():
os.setgid(user_gid)
os.setuid(user_uid)
return result class setuputil:
@staticmethod
def run_command(args, username=None, usercwd=None):
try:
if username:
pw_record = pwd.getpwnam(username)
env = os.environ.copy()
env['HOME'] = pw_record.pw_dir
env['LOGNAME'] = username
env['USER'] = username
if usercwd:
env['PWD'] = usercwd
p = subprocess.Popen(args, preexec_fn=demote(pw_record.pw_uid, pw_record.pw_gid),
cwd=usercwd, env=env, close_fds=True)
else:
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds = True) outputs = p.communicate()
for out in outputs:
if out:
return (p.returncode, out)
except OSError as os_e:
return (os_e.errno, os_e.strerror)
except ValueError as val_e:
return (val_e.errno, val_e.strerror)
else:
return (p.returncode, outputs) @staticmethod
def java_version():
java_ver_pattern = '\"(\d+\.\d+).*\"'
java_cmd = "java"
if 'JAVA_HOME' in os.environ:
java_cmd = os.environ['JAVA_HOME'] + "/bin/java"
version = subprocess.check_output([java_cmd, '-version'], stderr=subprocess.STDOUT)
if version:
return re.search(java_ver_pattern, version).groups()[0]
else:
return None @staticmethod
def start_app(es_exec, pid_file, es_user):
rtcode, msg = setuputil.run_command([es_exec, '-d', '-p', pid_file], es_user)
if rtcode:
return (rtcode, msg)
else:
return (0, "OK") MIN_JAVA_VERSION = 1.8

ELASTIC_USER = 'elastic'
ELASTIC_PASSWORD = 'elastic'
ELASTIC_PID = '/tmp/elasticpid' def main():
# set up java home
os.environ['JAVA_HOME'] = '/shared/java8' j_ver = setuputil.java_version()
if not j_ver or float(j_ver) < MIN_JAVA_VERSION:
logging.error("Java isn't installed or java version is not up to date: %s", j_ver if j_ver else "None")
return (1, "Java isn't installed or java version is not up to date: %s"%(j_ver if j_ver else "None")) rtcode, msg = setuputil.start_app('/opt/elasticsearch6.2.3/bin/elasticsearch', ELASTIC_PID, ELASTIC_USER)
if rtcode:
logging.error("Failed to start elasticsearch: %d, %s", rtcode, msg)
return (rtcode, msg)
else:
logging.debug("Start elasticsearch: %s", msg)
return (0, None) if __name__ == '__main__':
main()

3. 注意的问题

有几个需要注意的问题:

  • 环境变量的适用范围(scope)
    • 一般只在运行的当前shell有效
    • 就上例而言,JAVA_HOME只在运行脚本的进程里是有效
  • 在哪里设置环境变量?
    • 需要在运行命令之前设置  
    • 就上例而言,JAVA_HOME需要在运行java版本检查,和运行elasticsearch之前设置

  

上一篇:android项目 之 记事本(11) ----- 加入数据库


下一篇:React Native IOS ---基础环境搭建(前端架构师)