Python脚本执行Bash命令启动Java服务遇阻求助
解决Python脚本执行Java进程的阻塞与返回码问题
问题背景
我需要找到instrumentations和within的最小可用组合,手动验证时需依次执行以下两条命令:
sbt assembly
DATADOG_AGENT_IP=127.0.0.1 JAVA_HEAP_MS=1024m JAVA_HEAP_MX=2048m JAVA_HEAP_MS=1024m java -Dconfig.resource=/local-staging-db.conf -Xloggc:./log/gc.log -XX:+PrintGCDetails -javaagent:kanela-agent-1.0.17.jar -Djava.library.path=native -Duser.timezone=GMT -jar target/scala-2.12/sharaku-web-assembly-0.1-SNAPSHOT.jar
由于组合数量繁多,我编写Python脚本自动执行,但运行第二条Java命令时遇到以下问题:
- 使用
subprocess.run()执行时,进程始终不终止,无法执行后续代码; - 将环境变量整合到命令字符串中执行,结果与上述情况一致;
- 尝试
subprocess.Popen()虽能执行后续代码,但返回码为None,被判定为执行失败。
尝试1代码
command2 = """ java -Dconfig.resource=/local-staging-db.conf \ -Xloggc:./log/gc.log \ -XX:+PrintGCDetails \ -javaagent:kanela-agent-1.0.17.jar \ -Djava.library.path=native \ -Duser.timezone=GMT \ -jar target/scala-2.12/sharaku-web-assembly-0.1-SNAPSHOT.jar """ env = os.environ.copy() env['DATADOG_AGENT_IP'] = "127.0.0.1" env['JAVA_HEAP_MS'] = "1024m" env['JAVA_HEAP_MX'] = "2048m" # Execute the command result = subprocess.run(command2, shell=True, cwd=cwd2, env=env, text=True) time.sleep(10) print("hey") if result.returncode == 0: print("JAR completed successfully.", result.poll()) return True else: print("JAR failed with code:", result) return False
尝试2代码
command2 = """ DATADOG_AGENT_IP=127.0.0.1 JAVA_HEAP_MS=1024m JAVA_HEAP_MX=2048m JAVA_HEAP_MS=1024m java -Dconfig.resource=/local-staging-db.conf -Xloggc:./log/gc.log -XX:+PrintGCDetails -javaagent:kanela-agent-1.0.17.jar -Djava.library.path=native -Duser.timezone=GMT -jar target/scala-2.12/sharaku-web-assembly-0.1-SNAPSHOT.jar """ # Execute the command result = subprocess.run(command2, shell=True, cwd=cwd2, text=True)
尝试3(Popen)执行提示
JAR failed with code: <Popen: returncode: None args: ' DATADOG_AGENT_IP=127.0.0.1 JAVA_HEAP_M...>
解决方案
1. 解决subprocess.run()阻塞问题
你的Java进程是常驻服务进程(比如Web服务),启动后不会自动终止,subprocess.run()会一直等待进程结束,导致后续代码无法执行。如果验证逻辑不需要等待服务运行结束,而是启动后完成检查再终止进程,建议用subprocess.Popen()启动,执行验证后主动杀掉进程。
2. 正确处理subprocess.Popen()的返回码
Popen启动进程后不会等待它结束,直接获取returncode会得到None。需要在验证完成后终止进程,再通过wait()方法获取返回码:
import subprocess import os import time # 推荐将命令拆分为列表,避免shell=True的安全风险和解析问题 command2 = [ "java", "-Dconfig.resource=/local-staging-db.conf", "-Xloggc:./log/gc.log", "-XX:+PrintGCDetails", "-javaagent:kanela-agent-1.0.17.jar", "-Djava.library.path=native", "-Duser.timezone=GMT", "-jar", "target/scala-2.12/sharaku-web-assembly-0.1-SNAPSHOT.jar" ] env = os.environ.copy() env['DATADOG_AGENT_IP'] = "127.0.0.1" env['JAVA_HEAP_MS'] = "1024m" env['JAVA_HEAP_MX'] = "2048m" # 启动进程,禁用shell=True更安全 process = subprocess.Popen(command2, cwd=cwd2, env=env, text=True) # 等待服务启动完成(根据实际情况调整等待时间) time.sleep(15) # 这里添加你的验证逻辑:比如检查服务端口、日志内容、接口可用性等 # 示例:假设验证通过 validation_passed = True # 验证完成后终止进程 process.terminate() # 等待进程完全结束,获取返回码 return_code = process.wait() if validation_passed and return_code == 0: print("验证通过,JAR进程已正常终止") return True else: print(f"验证失败或进程异常终止,返回码: {return_code}") return False
3. 排查非常驻进程的阻塞问题
如果你的Java进程应该执行后自动退出,但出现阻塞,可能是进程卡在等待输入、日志缓冲区满等环节。可以捕获进程输出排查问题:
result = subprocess.run(command2, shell=True, cwd=cwd2, env=env, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print("STDOUT:", result.stdout) print("STDERR:", result.stderr)
通过输出内容判断进程卡住的原因,比如是否有未处理的输入请求、错误日志等。
内容的提问来源于stack exchange,提问作者Mariia Osipova
相关产品推荐
相关产品推荐

