在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之前設置

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM