首页 > 解决方案 > 使用 JAVA_OPTS 调用 java jar 文件的 Python 子进程调用

问题描述

我正在尝试从我的 python 脚本对构建在 jar 中的 java 类进行子进程调用。我在 AWS Batch 的 docker 容器上运行 python 代码。我在 Dockerfile 中设置了CLASSPATH环境变量以包含包含 jar 文件的目录。

ENV CLASSPATH /path/to/dir/containing/jar/file

当我将带有参数的整个命令作为字符串传递给子进程时,它工作正常。

runnable_command = "java $JAVA_OPTS " \
                   "RunCommand " \
                   "-b arg_b"

sp = subprocess.Popen(runnable_command,
                      stdin=subprocess.PIPE,
                      stdout=subprocess.PIPE,
                      stderr=subprocess.STDOUT,
                      close_fds=True,
                      shell=True,
                      universal_newlines=True,
                      env=os.environ)

result, stderr_data = sp.communicate()
print(result)

但为此,我必须创建具有安全风险的变量“shell=True”。所以我修改了变量“shell = False”并将命令和参数作为列表传递给子进程。这也很好。

runnable_command = ["/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.252.b09-2.x86_64/jre/bin/java", "$JAVA_OPTS", "<ClassName>"]

但是,我在 Dockerfile 中设置JAVA_OPTS环境变量以将 log4j 配置文件传递给 JVM。

ENV JAVA_OPTS="-Dlog4j.configurationFile=/opt/amazon/lib/log4j2.xml"

这很重要,因为我想将日志从这个 java 脚本传输到我的 python 脚本。当我将JAVA_OPTS添加到命令时,它失败并出现以下错误:

runnable_command = ["/usr/lib/jvm/java-1.8.0-jdk-1.8.0.252.b09-2.x86_64/jre/bin/java", "$JAVA_OPTS", "<ClassName>"]

我无法将 JAVA_OPTS 传递给子进程命令中的 args 列表。它无法找到 log4j.xml 文件。我从stackoverflow关注了这个问题,但即使在将JAVA_OPTS添加到“env”参数之后,它也会失败并出现同样的错误。

'错误:无法找到或加载主类 $JAVA_OPTS\n'

此外,当我将参数作为列表传递时,我无法运行“java”,但我不得不传递 java 可执行文件的绝对路径。

有人可以帮我解决以下问题吗?

  1. 如何将 log4j 配置传递给这个 java 命令?
  2. 为什么在使用列表而不是字符串运行子进程时必须将绝对路径传递给 java 命令?

标签: javapythonsubprocesslog4jjava-opts

解决方案


推荐阅读