Ich habe ein merkwürdiges Problem beim Einstellen der Linux-Umgebung von Java (1.6); speziell die Variable "PATH".
Kurz gesagt, ich habe eine Pipeline zum Ausführen nativer Prozesse, die java.lang.ProcessBuilder
verwendet. Der Benutzer kann optional die Umgebungsvariablen über ein HashMap
namens environment
:
Die Variable env
wird richtig gesetzt, wenn ich sie mit einem korrekten Wert für die Variable PATH an die Konsole ablege. Die Ausführung des Prozesses führt jedoch zu einem geworfenen Exception
:
java.io.IOException: error=2, No such file or directory
Der gleiche Prozess läuft mit identischen Umgebungsvariablen in der Terminal-Shell. Um dies zu testen, habe ich Eclipse nach der Einstellung der Umgebung im Terminal ausgeführt. In diesem Fall wird der ProcessBuilder
Prozess korrekt ausgeführt.
Was also passieren muss ist, dass ProcessBuilder
nicht die Umgebung verwendet, die ich dafür eingestellt habe, sondern stattdessen die aktuelle Systemumgebung.
Ich kann online keine befriedigenden Antworten auf dieses Problem finden. Vielleicht ist dies ein Betriebssystem-spezifisches Problem? Oder etwas anderes, das ich vermisse?
Ich glaube nicht, dass es ein Bug ist, ich denke, es ist ein Problem mit Ihrem Verständnis der Grenzen und Rollen der Umgebungsvariablen im Spiel. ProcessBuilder.environment()
enthält Umgebungsvariablen, die für den erzeugten Prozess "prozesslokal" sind. Sie sind nicht systemweit oder anmeldeweit und beeinflussen nicht einmal die Umgebung, in der der ProcessBuilder ausgeführt wird.
Die ProcessBuilder.environment()
-Karte enthält prozesslokale Variablen, die vom erzeugten Prozess nur gesehen werden. Offensichtlich ist eine Voraussetzung für die erzeugte Verarbeitung, die ProcessBuilder.environment()
zu sehen, ein erfolgreicher Launch des Prozesses, was ein Punkt ist, von dem ich nicht einmal überzeugt bin, dass er es überhaupt schafft.
Soweit ich weiß, ist es nicht wirklich möglich (aus Java), den gerade laufenden Prozess "PATH" zu ändern, was ich denke, was Sie erwarten (oder tun können). Also denke ich Sie müssen ProcessBuilder auf den vollständig qualifizierten Pfad zu der ausführbaren Datei verweisen, die Sie starten möchten (oder sicher sein, dass der PATH korrekt eingerichtet wurde, bevor Sie die JVM starten, die den ProcessBuilder verwendet, was Sie in Ihrer Arbeit getan haben "Szenario, um es vor dem Starten der IDE im Terminal zu setzen."
Sie müssen verstehen, dass Umgebungsvariablen lokal für die Verarbeitung von Kontexten sind. Ein neuer Prozess erhält eine Kopie der Umgebung des übergeordneten Elements, aber jede Kopie ist unabhängig. Änderungen im übergeordneten Element wirken sich nicht auf vorhandene untergeordnete Elemente aus (nur neue) und Änderungen in untergeordneten Elementen wirken sich nicht auf die übergeordneten oder neuen untergeordneten Elemente des <übergeordneten Elements> aus.
In Ihrem Fall erstellt der Java-Prozess einen untergeordneten Prozess und fügt eine modifizierte PATH
-Variable in den Kontext des Kindes ein. Dies hat keinen Einfluss auf den Java-Prozess. Der untergeordnete Prozess ist keine Shell, daher ignoriert er die Variable PATH
. Der Prozess wird direkt mit OS-Diensten erstellt. Diese schauen in den Kontext des Java-Prozesses, der die alte PATH
-Variable enthält, es sei denn, Sie ändern die Umgebung in der Shell bevor Sie den Java-Prozess starten.
Um Ihr Problem zu beheben, haben Sie zwei Möglichkeiten:
Untersuchen Sie die Variable PATH
in Java, teilen Sie sie in Pfadelemente und suchen Sie manuell nach der ausführbaren Datei. Sie können dann ProcessBuilder
mit dem absoluten Pfad aufrufen und das neue PATH
in das Kind einfügen, damit die Enkelkinder den richtigen Pfad haben.
Ruft eine Shell auf, um den untergeordneten Prozess zu starten. Die Shell verwendet ihren Pfad (den Sie über die Umgebung weitergeben können).
Der zweite Fall funktioniert so:
PATH
. "sh", "-c", "cmd args"
oder "cmd.exe", "/c", "cmd args"
) PATH
finden und den korrekten Befehl ausführen. Der Nachteil des zweiten Falles besteht darin, dass Sie die Argumente für den Befehl ( args
) korrekt entweichen und / oder zitieren müssen, da Leerzeichen und andere Sonderzeichen zu Problemen führen können.
Ich denke, du hast Recht. Der aktuell ausgeführte Java-Code verwendet nicht die Umgebungsvariablen, die Sie für den untergeordneten Prozess vorbereiten, den Sie ausführen. Sie könnten eine intermediäre ausführbare Datei oder ein Skript erstellen, an das Sie Variablen übergeben können, damit Ihr Programm ausgeführt wird.
Eine Sache, die aus dem ProcessBuilder-Javadoc hervorgeht, ist, dass Sie die Umgebungsvariablen mit der Methode environment () abrufen und dann die zurückgegebene Karte ändern können. Jeder nachfolgende Prozess, der von dieser ProcessBuilder-Instanz gestartet wird, hat Ihre Änderungen.
Dies scheint ein echtes Problem mit Java und externen Prozessen zu sein
das Folgende auf Windows 7 und Java 7 (32bit)
%Vor%erzeugt
%Vor%was bedeutet, dass die Umgebung der laufenden Programme und die Umgebung der Unterprozesse eine Pfadvariable enthalten sollte, die genau den Wert 'xbox' hat (z. B. Unsinn, es gibt kein Verzeichnis xbox irgendwo auf meinem PC)
nur für das Protokoll:
%Vor%ergibt genau das gleiche Ergebnis.
wenn ich renne
%Vor%mit diesem Prozess Builder und Umgebung bekomme ich
%Vor%das ist die (deutsche) Ausgabe von
%Vor%Dasselbe passiert, wenn ich
benutze %Vor%Und beachte, dass meine Umgebung so klein ist, weil ich die native Umgebung ersetzt habe. Das bedeutet, dass das ganze Programm genau diese zwei Umgebungsvariablen hat.
Tags und Links java environment-variables processbuilder