Festlegen der Umgebung für ProcessBuilder

8

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 :

setzen %Vor%

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?

    
Andrew Reid 05.04.2012, 20:17
quelle

6 Antworten

12

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."

    
Mike Clark 05.04.2012 21:37
quelle
7

Unter Linux:

%Vor%

In diesem Fall wird die Variable PATH nach Bedarf aktualisiert, und die ausführbare Datei wird in new $PATH gesucht. Dies funktionierte für mich unter Linux.

    
Sandeep 22.05.2012 16:55
quelle
3

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:

  1. 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.

  2. 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:

  1. Sie erstellen eine Umgebung mit der korrekten PATH .
  2. Sie starten einen Shell-Prozess.
  3. Sie übergeben den Befehl als Argument für die Shell ( "sh", "-c", "cmd args" oder "cmd.exe", "/c", "cmd args" )
  4. Die Shell wird bemerken, dass sie einen Befehl ausführen muss
  5. Es wird in seine Umgebung (die Sie in Schritt 1 konfiguriert haben) schauen, die modifizierte 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.

    
Aaron Digulla 03.12.2015 08:34
quelle
0

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.

    
Sarel Botha 05.04.2012 21:18
quelle
0

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.

    
David 30.11.2012 01:53
quelle
0

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.

    
John Smith 24.10.2013 07:47
quelle