{"id":42,"date":"2023-11-27T15:26:00","date_gmt":"2023-11-27T14:26:00","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=42"},"modified":"2024-01-08T09:14:06","modified_gmt":"2024-01-08T08:14:06","slug":"externe-prozesse-in-java-starten-und-steuern","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=42","title":{"rendered":"Externe Prozesse in Java starten und steuern"},"content":{"rendered":"\n<p>Die Integration externer Programme in Java-Anwendungen ist eine h\u00e4ufige Notwendigkeit, sei es f\u00fcr die Automatisierung von Aufgaben, die Interaktion mit Systemressourcen oder die Kommunikation mit anderen Anwendungen. Die <code>ProcessBuilder<\/code>-Klasse in Java bietet eine flexible M\u00f6glichkeit, externe Prozesse zu starten und mit ihnen zu interagieren. In diesem Artikel werden wir den Umgang mit <code>ProcessBuilder<\/code> sowie verwandten Konzepten wie Umgebungsvariablen, Kommandozeilenparametern, stdin\/stdout und m\u00f6glichen Herausforderungen beim Lesen von Prozessausgaben besprechen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Prozesse starten mit ProcessBuilder<\/h2>\n\n\n\n<p>Die <code>ProcessBuilder<\/code>-Klasse in Java erm\u00f6glicht es, externe Prozesse zu starten und mit ihnen zu interagieren. Um einen einfachen Prozess zu starten, k\u00f6nnen Sie <code>ProcessBuilder<\/code> wie folgt verwenden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.io.IOException;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ExternalProcessExample<\/span> <\/span>{\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) {\n        <span class=\"hljs-keyword\">try<\/span> {\n            ProcessBuilder processBuilder = <span class=\"hljs-keyword\">new<\/span> ProcessBuilder(<span class=\"hljs-string\">\"command\"<\/span>, <span class=\"hljs-string\">\"arg1\"<\/span>, <span class=\"hljs-string\">\"arg2\"<\/span>);\n            Process process = processBuilder.start();\n\n            <span class=\"hljs-comment\">\/\/ Warten, bis der Prozess beendet ist<\/span>\n            int exitCode = process.waitFor();\n\n            System.out.println(<span class=\"hljs-string\">\"Prozess beendet mit Exit-Code: \"<\/span> + exitCode);\n        } <span class=\"hljs-keyword\">catch<\/span> (IOException | InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird ein externer Prozess mit einem Befehl (&#8222;command&#8220;) und optionalen Argumenten (&#8222;arg1&#8220;, &#8222;arg2&#8220;) gestartet. Der <code>waitFor<\/code>-Aufruf blockiert, bis der gestartete Prozess beendet ist, und gibt den Exit-Code des Prozesses zur\u00fcck.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Umgebungsvariablen und Kommandozeilenparameter setzen<\/h2>\n\n\n\n<p>Oftmals ist es erforderlich, Umgebungsvariablen oder Kommandozeilenparameter f\u00fcr den gestarteten Prozess festzulegen. Dies kann \u00fcber die <code>environment()<\/code>-Methode von <code>ProcessBuilder<\/code> erfolgen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.io.IOException;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ProcessWithEnvironment<\/span> <\/span>{\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) {\n        <span class=\"hljs-keyword\">try<\/span> {\n            ProcessBuilder processBuilder = <span class=\"hljs-keyword\">new<\/span> ProcessBuilder(<span class=\"hljs-string\">\"command\"<\/span>, <span class=\"hljs-string\">\"arg1\"<\/span>, <span class=\"hljs-string\">\"arg2\"<\/span>);\n\n            <span class=\"hljs-comment\">\/\/ Umgebungsvariablen setzen<\/span>\n            processBuilder.environment().put(<span class=\"hljs-string\">\"KEY\"<\/span>, <span class=\"hljs-string\">\"VALUE\"<\/span>);\n\n            Process process = processBuilder.start();\n\n            int exitCode = process.waitFor();\n\n            System.out.println(<span class=\"hljs-string\">\"Prozess beendet mit Exit-Code: \"<\/span> + exitCode);\n        } <span class=\"hljs-keyword\">catch<\/span> (IOException | InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">3. stdin und stdout steuern<\/h2>\n\n\n\n<p>Die <code>ProcessBuilder<\/code>-Klasse erm\u00f6glicht auch die Steuerung von stdin und das Abfangen von stdout des gestarteten Prozesses. Dazu k\u00f6nnen Sie <code>getOutputStream()<\/code> f\u00fcr die Eingabe und <code>getInputStream()<\/code> f\u00fcr die Ausgabe verwenden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.io.*;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ProcessWithInputOutput<\/span> <\/span>{\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) {\n        <span class=\"hljs-keyword\">try<\/span> {\n            ProcessBuilder processBuilder = <span class=\"hljs-keyword\">new<\/span> ProcessBuilder(<span class=\"hljs-string\">\"command\"<\/span>);\n\n            <span class=\"hljs-comment\">\/\/ stdin des Prozesses abrufen<\/span>\n            OutputStream stdin = processBuilder.start().getOutputStream();\n\n            <span class=\"hljs-comment\">\/\/ Daten in stdin schreiben<\/span>\n            BufferedWriter writer = <span class=\"hljs-keyword\">new<\/span> BufferedWriter(<span class=\"hljs-keyword\">new<\/span> OutputStreamWriter(stdin));\n            writer.write(<span class=\"hljs-string\">\"Input-Daten\"<\/span>);\n            writer.close();\n\n            <span class=\"hljs-comment\">\/\/ stdout des Prozesses abrufen<\/span>\n            InputStream stdout = processBuilder.start().getInputStream();\n\n            <span class=\"hljs-comment\">\/\/ Daten von stdout lesen<\/span>\n            BufferedReader reader = <span class=\"hljs-keyword\">new<\/span> BufferedReader(<span class=\"hljs-keyword\">new<\/span> InputStreamReader(stdout));\n            <span class=\"hljs-built_in\">String<\/span> output = reader.readLine();\n\n            System.out.println(<span class=\"hljs-string\">\"Prozessausgabe: \"<\/span> + output);\n        } <span class=\"hljs-keyword\">catch<\/span> (IOException e) {\n            e.printStackTrace();\n        }\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">4. Verwendung der StreamGobbler-Hilfsklasse<\/h2>\n\n\n\n<p>Um stdout und stderr des gestarteten Prozesses effizienter zu verarbeiten, ist es ratsam, eine Hilfsklasse wie <code>StreamGobbler<\/code> zu verwenden. Diese Klasse liest die Ausgaben des Prozesses in einem separaten Thread und verhindert, dass die Puffer des Betriebssystems \u00fcberlaufen.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> java.io.BufferedReader;\n<span class=\"hljs-keyword\">import<\/span> java.io.IOException;\n<span class=\"hljs-keyword\">import<\/span> java.io.InputStream;\n<span class=\"hljs-keyword\">import<\/span> java.io.InputStreamReader;\n\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">StreamGobbler<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Thread<\/span> <\/span>{\n    private InputStream inputStream;\n    private Consumer&lt;<span class=\"hljs-built_in\">String<\/span>&gt; consumer;\n\n    public StreamGobbler(InputStream inputStream, Consumer&lt;<span class=\"hljs-built_in\">String<\/span>&gt; consumer) {\n        <span class=\"hljs-keyword\">this<\/span>.inputStream = inputStream;\n        <span class=\"hljs-keyword\">this<\/span>.consumer = consumer;\n    }\n\n    @Override\n    public <span class=\"hljs-keyword\">void<\/span> run() {\n        <span class=\"hljs-keyword\">try<\/span> (BufferedReader reader = <span class=\"hljs-keyword\">new<\/span> BufferedReader(<span class=\"hljs-keyword\">new<\/span> InputStreamReader(inputStream))) {\n            reader.lines().forEach(consumer);\n        } <span class=\"hljs-keyword\">catch<\/span> (IOException e) {\n            e.printStackTrace();\n        }\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Die <code>StreamGobbler<\/code>-Klasse erfasst den InputStream des Prozesses und leitet die Ausgaben an den angegebenen Consumer weiter. Dadurch k\u00f6nnen Sie die Ausgaben des Prozesses nach Bedarf verarbeiten, z.B. sie in einer Datei speichern oder analysieren.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Warnung vor Blockaden bei stdout<\/h2>\n\n\n\n<p>Beim Lesen von stdout ist es wichtig, die Ausgaben des Prozesses kontinuierlich zu verarbeiten, um zu verhindern, dass die Puffer des Betriebssystems \u00fcberlaufen und der Prozess blockiert. Dies kann erreicht werden, indem Sie den <code>StreamGobbler<\/code> oder einen \u00e4hnlichen Mechanismus verwenden, um die Ausgaben parallel zum Hauptprogramm zu verarbeiten &#8211; oder komplett zu ignorieren (denn die Hauptsache ist, dass der Stream ausgelesen wird)!<\/p>\n\n\n\n<p>Insgesamt bietet die <code>ProcessBuilder<\/code>-Klasse in Java eine leistungsstarke M\u00f6glichkeit, mit externen Prozessen zu interagieren. Mit den oben genannten Konzepten k\u00f6nnen Sie nicht nur Prozesse starten, sondern auch Umgebungsvariablen setzen, Kommandozeilenparameter \u00fcbergeben und die stdin\/stdout-Streams effizient steuern. Die Verwendung von Hilfsklassen wie <code>StreamGobbler<\/code> erleichtert zudem die Handhabung von Prozessausgaben und minimiert das Risiko von Blockaden durch volle Puffer.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die Integration externer Programme in Java-Anwendungen ist eine h\u00e4ufige Notwendigkeit, sei es f\u00fcr die Automatisierung von Aufgaben, die Interaktion mit Systemressourcen oder die Kommunikation mit anderen Anwendungen. Die ProcessBuilder-Klasse in Java bietet eine flexible M\u00f6glichkeit, externe Prozesse zu starten und mit ihnen zu interagieren. In diesem Artikel werden wir den Umgang mit ProcessBuilder sowie verwandten [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-plain_java"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=42"}],"version-history":[{"count":3,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/42\/revisions"}],"predecessor-version":[{"id":47,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/42\/revisions\/47"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}