Salta al contenuto

Archivi

  • Gennaio 2022
  • Dicembre 2021
  • Novembre 2021
  • Ottobre 2021
  • Settembre 2021

Categorie

  • Nessuna categoria
Trend RepositoryArticles and guides
Articles

Esecuzione di comandi Shell in Java

Il Ottobre 23, 2021 da admin
  • Introduzione
  • Runtime.exec()
  • Eseguire un comando da una stringa
  • Specificare la directory di lavoro
  • Usare le variabili d’ambiente
  • Esecuzione di file .bat e .sh
  • ProcessBuilder
  • ProcessBuilder: Executing Command from Strings
  • ProcessBuilder: Specify the Working Directory
  • ProcessBuilder: Variabili d’ambiente
  • ProcessBuilder: Esecuzione di file .bat e .sh
  • Conclusione

Introduzione

In questo articolo, daremo un’occhiata a come possiamo sfruttare le classi Runtime e ProcessBuilder per eseguire comandi e script shell con Java.

Utilizziamo i computer per automatizzare molte cose nel nostro lavoro quotidiano. Gli amministratori di sistema eseguono molti comandi tutto il tempo, alcuni dei quali sono molto ripetitivi e richiedono cambiamenti minimi tra un’esecuzione e l’altra.

Anche questo processo è maturo per l’automazione. Non c’è bisogno di eseguire tutto manualmente. Usando Java, possiamo eseguire comandi di shell singoli o multipli, eseguire script di shell, eseguire il terminale / prompt dei comandi, impostare le directory di lavoro e manipolare le variabili di ambiente attraverso le classi del nucleo.

Runtime.exec()

La classe Runtime in Java è una classe di alto livello, presente in ogni singola applicazione Java. Attraverso di essa, l’applicazione stessa comunica con l’ambiente in cui si trova.

Estraendo il runtime associato alla nostra applicazione tramite il metodo getRuntime(), possiamo utilizzare il metodo exec() per eseguire direttamente i comandi o eseguire i file .bat/.sh.

Il metodo exec() offre alcune varianti sovraccaricate:

  • public Process exec(String command) – Esegue il comando contenuto in command in un processo separato.
  • public Process exec(String command, String envp) – Esegue il command, con un array di variabili ambientali. Sono fornite come un array di stringhe, seguendo il formato name=value.
  • public Process exec(String command, String envp, File dir) – Esegue il command, con le variabili d’ambiente specificate, dall’interno della directory dir.
  • public Process exec(String cmdArray) – Esegue un comando nella forma di un array di stringhe.
  • public Process exec(String cmdArray, String envp) – Esegue un comando con le variabili d’ambiente specificate.
  • public Process exec(String cmdarray, String envp, File dir) – Esegue un comando, con le variabili d’ambiente specificate, dall’interno della directory dir.

E’ da notare che questi processi sono eseguiti esternamente all’interprete e dipendono dal sistema.

C’è anche da notare la differenza tra String command e String cmdArray. Essi ottengono la stessa cosa. Un command è comunque suddiviso in un array, quindi usare uno qualsiasi di questi due dovrebbe dare gli stessi risultati.

Sta a voi decidere se exec("dir /folder") o exec(new String{"dir", "/folder"} è quello che vorreste usare.

Scriviamo qualche esempio per vedere come questi metodi sovraccaricati differiscono tra loro.

Eseguire un comando da una stringa

Partiamo con l’approccio più semplice di questi tre:

Process process = Runtime.getRuntime().exec("ping www.stackabuse.com");

Eseguendo questo codice verrà eseguito il comando che abbiamo fornito in formato String. Tuttavia, non vediamo nulla quando lo eseguiamo.

Per validare se questo viene eseguito correttamente, vogliamo prendere in mano l’oggetto process. Usiamo un BufferedReader per dare un’occhiata a cosa sta succedendo:

public static void printResults(Process process) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = reader.readLine()) != null) { System.out.println(line); }}

Ora, quando eseguiamo questo metodo dopo il metodo exec(), dovrebbe produrre qualcosa di simile a:

Pinging www.stackabuse.com with 32 bytes of data:Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Ping statistics for 104.18.57.23: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),Approximate round trip times in milli-seconds: Minimum = 21ms, Maximum = 21ms, Average = 21ms

Tenete a mente che dovremo estrarre le informazioni di processo dalle istanze Process quando passeremo ad altri esempi.

Specificare la directory di lavoro

Se volete eseguire un comando da, diciamo, una certa cartella, dovremmo fare qualcosa del tipo:

Process process = Runtime.getRuntime() .exec("cmd /c dir", null, new File("C:\Users\")); //.exec("sh -c ls", null, new File("Pathname")); for non-Windows usersprintResults(process);

Qui, abbiamo fornito il metodo exec() con un command, un null per le nuove variabili d’ambiente e un new File() che è impostato come nostra directory di lavoro.

Degno di nota è l’aggiunta di cmd /c prima di un comando come dir.

Siccome sto lavorando su Windows, questo apre il cmd e /c esegue il comando successivo. In questo caso, è dir.

Il motivo per cui questo non era obbligatorio per l’esempio ping, ma è obbligatorio per questo esempio è stato ben risposto da un utente SO.

Eseguendo il pezzo di codice precedente si otterrà:

Volume in drive C has no label. Volume Serial Number is XXXX-XXXX Directory of C:\Users08/29/2019 05:01 PM <DIR> .08/29/2019 05:01 PM <DIR> ..08/18/2016 09:11 PM <DIR> Default.migrated08/29/2019 05:01 PM <DIR> Public05/15/2020 11:08 AM <DIR> User 0 File(s) 0 bytes 5 Dir(s) 212,555,214,848 bytes free

Diamo un’occhiata a come potremmo fornire il comando precedente in diverse parti individuali, invece di una singola stringa:

Process process = Runtime.getRuntime().exec( new String{"cmd", "/c", "dir"}, null, new File("C:\Users\")); printResults(process);

Eseguendo questo pezzo di codice si otterrà anche:

Volume in drive C has no label. Volume Serial Number is XXXX-XXXX Directory of C:\Users08/29/2019 05:01 PM <DIR> .08/29/2019 05:01 PM <DIR> ..08/18/2016 09:11 PM <DIR> Default.migrated08/29/2019 05:01 PM <DIR> Public05/15/2020 11:08 AM <DIR> User 0 File(s) 0 bytes 5 Dir(s) 212,542,808,064 bytes free

In definitiva, indipendentemente dall’approccio – usando una singola stringa o un array di stringhe, il comando inserito sarà sempre suddiviso in un array prima di essere elaborato dalla logica sottostante.

Qualunque sia l’approccio che vorresti usare, si riduce solo a quello che trovi più leggibile.

Usare le variabili d’ambiente

Diamo un’occhiata a come possiamo usare le variabili d’ambiente:

Process process = Runtime.getRuntime().exec( "cmd /c echo %var1%", new String{"var1=value1"}); printResults(process);

Possiamo fornire tutte le variabili d’ambiente che vogliamo nell’array di stringhe. Qui, abbiamo appena stampato il valore di var1 usando echo.

Eseguendo questo codice otterremo:

value1

Esecuzione di file .bat e .sh

A volte, è molto più facile scaricare tutto in un file ed eseguire quel file invece di aggiungere tutto programmaticamente.

A seconda del tuo sistema operativo, dovresti usare file .bat o .sh. Creiamone uno con il contenuto:

echo Hello World

Poi, usiamo lo stesso approccio di prima:

Process process = Runtime.getRuntime().exec( "cmd /c start file.bat", null, new File("C:\Users\User\Desktop\"));

Questo aprirà il prompt dei comandi ed eseguirà il file .bat nella directory di lavoro che abbiamo impostato.

Eseguendo questo codice si ottiene sicuramente:

Con tutte le firme exec() sovraccaricate di cui ci siamo occupati, diamo un’occhiata alla classe ProcessBuilder e a come possiamo eseguire comandi con essa.

ProcessBuilder

ProcessBuilder è il meccanismo sottostante che esegue i comandi quando usiamo il metodo Runtime.getRuntime().exec():

/** * Executes the specified command and arguments in a separate process with * the specified environment and working directory. *...*/public Process exec(String cmdarray, String envp, File dir) throws IOException { return new ProcessBuilder(cmdarray) .environment(envp) .directory(dir) .start();}

JavaDocs per la classe Runtime

Dando uno sguardo a come il ProcessBuilder prende il nostro input dal metodo exec() ed esegue il comando, ci dà una buona idea di come usarlo.

Accetta un String cmdarray, e questo è sufficiente per farlo funzionare. In alternativa, possiamo fornirgli argomenti opzionali come il String envp e il File dir.

Esaminiamo queste opzioni.

ProcessBuilder: Executing Command from Strings

Invece di poter fornire una singola stringa, come cmd /c dir, dovremo spezzarla in questo caso. Per esempio, se volessimo elencare i file nella directory C:/Users come prima, faremmo:

ProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command("cmd", "/c", "dir C:\Users");Process process = processBuilder.start();printResults(process);

Per eseguire effettivamente un Process, eseguiamo il comando start() e assegniamo il valore restituito a un’istanza Process.

Eseguendo questo codice si ottiene:

 Volume in drive C has no label. Volume Serial Number is XXXX-XXXX Directory of C:\Users08/29/2019 05:01 PM <DIR> .08/29/2019 05:01 PM <DIR> ..08/18/2016 09:11 PM <DIR> Default.migrated08/29/2019 05:01 PM <DIR> Public05/15/2020 11:08 AM <DIR> User 0 File(s) 0 bytes 5 Dir(s) 212,517,294,080 bytes free

Tuttavia, questo approccio non è migliore di quello precedente. Ciò che è utile con la classe ProcessBuilder è che è personalizzabile. Possiamo impostare le cose programmaticamente, non solo tramite comandi.

ProcessBuilder: Specify the Working Directory

Invece di fornire la directory di lavoro tramite il comando, impostiamola programmaticamente:

processBuilder.command("cmd", "/c", "dir").directory(new File("C:\Users\"));

Qui abbiamo impostato la directory di lavoro come prima, ma abbiamo spostato questa definizione fuori dal comando stesso. L’esecuzione di questo codice fornirà lo stesso risultato dell’ultimo esempio.

ProcessBuilder: Variabili d’ambiente

Utilizzando i metodi di ProcessBuilder, è facile recuperare una lista di variabili d’ambiente sotto forma di Map. È anche facile impostare le variabili d’ambiente in modo che il vostro programma possa usarle.

Prendiamo le variabili d’ambiente attualmente disponibili e poi aggiungiamone alcune per un uso successivo:

ProcessBuilder processBuilder = new ProcessBuilder();Map<String, String> environmentVariables = processBuilder.environment();environmentVariables.forEach((key, value) -> System.out.println(key + value));

Qui abbiamo impacchettato le variabili d’ambiente restituite in un Map ed eseguito un forEach() su di esso per stampare i valori sulla nostra console.

Eseguendo questo codice otterremo una lista delle variabili d’ambiente che avete sulla vostra macchina:

DriverDataC:\Windows\System32\Drivers\DriverDataHerokuPathE:\HerokuProgramDataC:\ProgramData...

Ora, aggiungiamo una variabile d’ambiente a quella lista e usiamola:

environmentVariables.put("var1", "value1");processBuilder.command("cmd", "/c", "echo", "%var1%");Process process = processBuilder.start();printResults(process);

Eseguendo questo codice otterremo:

value1

Naturalmente, una volta che il programma ha finito di funzionare, questa variabile non rimarrà nella lista.

ProcessBuilder: Esecuzione di file .bat e .sh

Se volete eseguire un file, di nuovo, dobbiamo solo fornire all’istanza ProcessBuilder le informazioni richieste:

processBuilder .command("cmd", "/c", "start", "file.bat") .directory(new File("C:\Users\User\Desktop"));Process process = processBuilder.start();

Eseguendo questo codice il prompt dei comandi si apre ed esegue il file .bat:

Conclusione

In questo articolo, abbiamo esplorato esempi di esecuzione di comandi shell in Java. Abbiamo usato le classi Runtime e ProcessBuilder per farlo.

Utilizzando Java, possiamo eseguire comandi di shell singoli o multipli, eseguire script di shell, eseguire il terminale/prompt di comando, impostare le directory di lavoro e manipolare le variabili di ambiente attraverso le classi del nucleo.

Lascia un commento Annulla risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Archivi

  • Gennaio 2022
  • Dicembre 2021
  • Novembre 2021
  • Ottobre 2021
  • Settembre 2021

Meta

  • Accedi
  • Feed dei contenuti
  • Feed dei commenti
  • WordPress.org
  • DeutschDeutsch
  • NederlandsNederlands
  • SvenskaSvenska
  • DanskDansk
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • RomânăRomână
  • PolskiPolski
  • ČeštinaČeština
  • MagyarMagyar
  • SuomiSuomi
  • 日本語日本語

Copyright Trend Repository 2022 | Tema da ThemeinProgress | Offerto orgogliosamente da WordPress