Java 在jar中复制'export'命令以设置环境变量
场景 在使用ProcessBuilder执行一系列命令时,我注意到当前无法设置环境变量,使其在执行一组命令后保持“已知” 问题 如何在Java 在jar中复制'export'命令以设置环境变量,java,command-line,environment-variables,processbuilder,Java,Command Line,Environment Variables,Processbuilder,场景 在使用ProcessBuilder执行一系列命令时,我注意到当前无法设置环境变量,使其在执行一组命令后保持“已知” 问题 如何在.jar文件中重新创建export taskdata=/var/taskd命令的效果* 尝试0 提供了一种为每个特定命令设置环境变量的方法,但是当我执行该解决方案的.jar并检查环境变量$u在执行后是否仍然设置时,我发现它不是。而执行后,$taskdata仍保持设置。举例说明: a@DESKTOP-desktopName:/mnt/e$ echo $TASKDDA
.jar
文件中重新创建export taskdata=/var/taskd
命令的效果*
尝试0
提供了一种为每个特定命令设置环境变量的方法,但是当我执行该解决方案的.jar
并检查环境变量$u
在执行后是否仍然设置时,我发现它不是。而执行后,$taskdata
仍保持设置。举例说明:
a@DESKTOP-desktopName:/mnt/e$ echo $TASKDDATA
a@DESKTOP-desktopName:/mnt/e$ TASKDDATA=/var/taskd
a@DESKTOP-desktopName:/mnt/e$ echo $TASKDDATA
/var/taskd
a@DESKTOP-desktopName:/mnt/e$ sudo java -jar autoInstallTaskwarrior.jar
[sudo] password for a:
Process ended with rc=0
Standard Output:
util/
Standard Error:
a@DESKTOP-desktopName:/mnt/e$ echo $TASKDDATA
/var/taskd
a@DESKTOP-desktopName:/mnt/e$ echo $u
尝试1
对于单个命令,环境变量可以使用我在中编写的解决方案:。但是,这不会为第二个命令保留taskvariable,在该命令中需要再次设置它。但是,使用export命令时,不需要再次设置环境变量。具体来说,当java代码完成并且用户希望输入任何需要环境变量的附加命令时,这种差异就会显现出来。在这种情况下,用户需要首先再次键入export命令
尝试2
当打开一个新shell以使用sudo-s
获取根权限时,会出现另一个区别。不仅在.jar
文件中设置环境需要为每个单独的命令重新设置环境,而且环境变量不会传递给具有根权限的新shell。例如,执行以下命令:
commandLines[53] = new String[4];
commandLines[53][0] = "sudo";
commandLines[53][1] = "-s";
commandLines[53][2] = "taskdctl";
commandLines[53][3] = "start";
commands[53].setCommandLines(commandLines[53]);
commands[53].setEnvVarContent("/var/taskd");
commands[53].setEnvVarName("TASKDDATA");
commands[53].setWorkingPath("/usr/share/taskd/pki");
commandLines[54] = new String[5];
commandLines[54][0] = "sudo";
commandLines[54][1] = "-s";
commandLines[54][2] = "task";
commandLines[54][3] = "sync";
commandLines[54][4] = "init";
commands[54].setCommandLines(commandLines[54]);
commands[54].setEnvVarContent("/var/taskd");
commands[54].setEnvVarName("TASKDDATA");
commands[54].setWorkingPath("/usr/share/taskd/pki");
返回:
53RUNNINGCOMMAND=sudo -s taskdctl start
The TASKDDATA variable must be set.
54RUNNINGCOMMAND=sudo -s task sync
Could not connect to 0.0.0.0 53589
Sync failed. Could not connect to the Taskserver.
Syncing with 0.0.0.0:53589
注1
在执行.jar
之前,使用:taskdata=/var/taskd sudo java-jar autoInstallTaskwarrior.jar
设置环境变量$taskdata=/var/taskd
,不能确保环境变量$taskdata
在执行.jar
文件后仍然可用。此外,它超出了问题的范围,因为它不是在.jar
文件中设置的,而是在.jar
文件之外设置的
注2
我理解将export
命令用作processbuilder执行的命令是不合适的,就像cd
命令一样
*这就是为什么问题的重点是重现设置环境变量的“长期/持久”效果/可用性,而不是“如何执行导出命令”
当我执行该解决方案的.jar并检查环境变量$u在执行后是否仍然设置时,我发现它不是
这是预期的行为。一些操作系统支持全局“环境”变量的概念。但不是UNIX。在类UNIX操作系统中,每个进程都有自己的环境变量的私有副本。一个进程不能修改另一个进程的环境。这也是为什么更改进程中的当前工作目录不会更改其父进程的cwd。每个进程都有自己的cwd
解决该限制的通常方法是,子进程将var=val对写入stdout,然后父shell计算该输出以在其环境中设置vars。为了便于说明,假设该命令是以下名为myscript.sh的shell脚本,而不是Java程序:
#!/bin/sh
echo VAR_A=val_a
echo VAR_B=val_b
然后父shell会执行此操作
export $(./myscript.sh)
感谢您解释为什么这是预期行为。在你的回答中,我忽略了如何在
.jar
文件中实现它。我是否可以从你的回答中得出:0。仅仅使用一个.jar
文件是不可能的?1.这可能是可能的,但这是我最接近的近似值(XY问题已解决,但不是来自.jar
文件)?2.您暗示-,但我误解了您的解决方案是如何在.jar
文件中运行的。我将尝试从.jar
文件中以命令的形式运行export$(./myscript.sh)
,以测试您的实现。假设这就是您想要的。我认为应该实现的结果是:56RUNNINGCOMMAND=export$(./myscript.sh)java.io.IOException:无法运行程序“export”(在目录“/mnt/e/somefolder”中):错误=2,没有这样的文件或目录
。(我首先运行了chmod+xmyscript.sh
并验证了myscript.sh
位于/mnt/e/somefolder
)因此导出
被视为一个程序,而不是shell的语法。因此,我目前不明白您的答案是如何在.jar
文件中实现的。任何详细说明都将不胜感激@a、 t.导出
不是一个程序。这是一个shell内置命令。如果没有父shell的合作,jar程序无法修改父shell的环境。解决方案是让.jar
程序将var=value
对写入其标准输出流,并让父shell将它们导出到其环境中。我的myscript.sh示例只是一个简单的示例。无论是在.jar
文件中运行的程序、shell脚本还是用其他语言编写的程序,都是完全无关的。