Java 在jar中复制'export'命令以设置环境变量

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

场景

在使用ProcessBuilder执行一系列命令时,我注意到当前无法设置环境变量,使其在执行一组命令后保持“已知”

问题

如何在
.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脚本还是用其他语言编写的程序,都是完全无关的。