Skip to content

Archives

  • 2022 január
  • 2021 december
  • 2021 november
  • 2021 október
  • 2021 szeptember

Categories

  • Nincs kategória
Trend RepositoryArticles and guides
Articles

Shell-parancsok végrehajtása Javában

On október 23, 2021 by admin
  • Bevezetés
  • Runtime.exec()
  • Parancs végrehajtása stringből
  • Munkakönyvtár megadása
  • Környezeti változók használata
  • A .bat és .sh fájlok futtatása
  • ProcessBuilder
  • ProcessBuilder: Parancs végrehajtása karakterláncokból
  • ProcessBuilder: A munkakönyvtár megadása
  • ProcessBuilder: Környezeti változók
  • ProcessBuilder: .bat és .sh fájlok futtatása
  • Következtetés

Bevezetés

Ebben a cikkben megnézzük, hogyan használhatjuk a Runtime és ProcessBuilder osztályokat shell-parancsok és szkriptek futtatására Javával.

A számítógépeket sok minden automatizálására használjuk a napi munkánk során. A rendszergazdák állandóan sok parancsot futtatnak, amelyek közül néhány nagyon ismétlődő, és minimális változtatásokat igényel a futtatások között.

Ez a folyamat is megérett az automatizálásra. Nincs szükség arra, hogy mindent kézzel futtassunk. A Java segítségével egyetlen vagy több shell parancsot futtathatunk, shell szkripteket futtathatunk, a terminál/parancssorozatot futtathatjuk, munkakönyvtárakat állíthatunk be és környezeti változókat manipulálhatunk a core osztályokon keresztül.

Runtime.exec()

A Runtime osztály a Java-ban egy magas szintű osztály, amely minden egyes Java alkalmazásban jelen van. Ezen keresztül maga az alkalmazás kommunikál azzal a környezettel, amelyben van.

Az alkalmazásunkhoz tartozó futási időt a getRuntime() metóduson keresztül kivonva, a exec() metódus segítségével közvetlenül tudunk parancsokat végrehajtani vagy .bat/.sh fájlokat futtatni.

A exec() módszer néhány túlterhelt változatot kínál:

  • public Process exec(String command) – A command-ben szereplő parancsot hajtja végre egy külön folyamatban.
  • public Process exec(String command, String envp) – Végrehajtja a command-t, a környezeti változók tömbjével. Ezeket Strings tömbként adja meg, a name=value formátumot követve.
  • public Process exec(String command, String envp, File dir) – Végrehajtja a command parancsot, a megadott környezeti változókkal, a dir könyvtárból.
  • public Process exec(String cmdArray) – Végrehajtja a parancsot egy Strings tömb formájában.
  • public Process exec(String cmdArray, String envp) – Végrehajtja a parancsot a megadott környezeti változókkal.
  • public Process exec(String cmdarray, String envp, File dir) – Parancsot hajt végre a megadott környezeti változókkal a dir könyvtárból.

Érdemes megjegyezni, hogy ezek a folyamatok az értelmezőn kívül futnak, és rendszerfüggőek lesznek.

Azt is érdemes megjegyezni, hogy a String command és a String cmdArray között van különbség. Ugyanazt a dolgot érik el. Egy command amúgy is tömbre bomlik, így e kettő bármelyikének használata ugyanazt az eredményt fogja eredményezni.

Az már rajtad múlik, hogy a exec("dir /folder") vagy a exec(new String{"dir", "/folder"} az, amit használni szeretnél.

Írjunk fel néhány példát, hogy lássuk, miben különböznek ezek a túlterhelt módszerek egymástól.

Parancs végrehajtása stringből

Kezdjük a legegyszerűbb megközelítéssel a három közül:

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

A kód futtatásával végrehajtjuk az általunk megadott parancsot string formátumban. Azonban nem látunk semmit, amikor ezt futtatjuk.

Az érvényesítéshez, hogy ez helyesen futott-e, a process objektumot kell megszereznünk. Használjunk egy BufferedReader-et, hogy megnézzük, mi történik:

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); }}

Most, amikor ezt a metódust a exec() metódus után futtatjuk, valami olyasmit kell eredményeznie, mint:

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

Ne feledjük, hogy a folyamatinformációkat a Process példányokból kell majd kinyernünk, ahogy más példákon keresztül haladunk.

Munkakönyvtár megadása

Ha egy parancsot mondjuk egy bizonyos mappából szeretnénk futtatni, akkor valami olyasmit teszünk, mint:

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);

Itt a exec() metódust egy command, egy null az új környezeti változóknak és egy new File(), amit a munkakönyvtárunknak állítunk be.

Az cmd /c hozzáadása egy olyan parancs előtt, mint a dir, érdemes megjegyezni.

Mivel Windowson dolgozom, ez megnyitja a cmd és a /c végrehajtja a következő parancsot. Ebben az esetben ez a dir.

Az okot, hogy ez miért nem volt kötelező a ping példánál, de ennél a példánál kötelező, egy SO felhasználó szépen megválaszolta.

Az előző kódrészlet futtatása a következőt eredményezi:

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

Nézzük meg, hogy az előző parancsot egyetlen karakterlánc helyett több különálló részben is megadhatjuk:

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

A kódrészlet futtatása szintén a következőt eredményezi:

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

Végeredményben a megközelítéstől függetlenül – egyetlen String vagy egy String tömb használata – a beírt parancsot mindig tömbre bontjuk, mielőtt a mögöttes logika feldolgozza.

Az, hogy melyiket szeretnénk használni, csak azon múlik, hogy melyiket találjuk olvashatóbbnak.

Környezeti változók használata

Nézzük meg, hogyan használhatjuk a környezeti változókat:

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

A String tömbön belül annyi környezeti változót adhatunk meg, amennyit csak szeretnénk. Itt éppen a var1 értékét nyomtattuk ki a echo használatával.

A kód futtatásával:

value1

A .bat és .sh fájlok futtatása

Néha sokkal egyszerűbb mindent egy fájlba pakolni és azt a fájlt futtatni ahelyett, hogy mindent programozottan adnánk hozzá.

Az operációs rendszertől függően a .bat vagy a .sh fájlokat használjuk. Hozzunk létre egyet a következő tartalommal:

echo Hello World

Ezután használjuk ugyanazt a megközelítést, mint korábban:

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

Ez megnyitja a parancssort, és futtatja a .bat fájlt az általunk beállított munkakönyvtárban.

Ez a kód futtatása elég biztosan azt eredményezi:

Mivel az összes túlterhelt exec() aláírásról gondoskodtunk, nézzük meg a ProcessBuilder osztályt és azt, hogyan tudunk parancsokat végrehajtani a segítségével.

ProcessBuilder

ProcessBuilder az a mögöttes mechanizmus, amely lefuttatja a parancsokat, amikor a Runtime.getRuntime().exec() metódust használjuk:

/** * 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 a Runtime osztályhoz

Megnézzük, hogyan veszi a ProcessBuilder a exec() metódusból származó bemenetünket és futtatja a parancsot, és ezzel egy jó ötletet kapunk arra, hogyan használjuk azt is.

Elvesz egy String cmdarray-at, és ez elég ahhoz, hogy futtassuk. Alternatívaként olyan opcionális argumentumokkal is elláthatjuk, mint a String envp és a File dir.

Vizsgáljuk meg ezeket a lehetőségeket.

ProcessBuilder: Parancs végrehajtása karakterláncokból

Ahelyett, hogy egyetlen karakterláncot tudnánk megadni, mint például a cmd /c dir, ebben az esetben fel kell bontanunk. Ha például a korábbiakhoz hasonlóan a C:/Users könyvtárban lévő fájlokat szeretnénk felsorolni, akkor:

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

Az Process tényleges végrehajtásához a start() parancsot futtatjuk, és a visszaadott értéket egy Process példányhoz rendeljük.

A kód futtatásával:

 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

Ez a megközelítés azonban semmivel sem jobb, mint az előző. Ami hasznos a ProcessBuilder osztályban, az az, hogy testre szabható. Programozottan is beállíthatunk dolgokat, nem csak parancsokon keresztül.

ProcessBuilder: A munkakönyvtár megadása

Ahelyett, hogy a parancson keresztül adnánk meg a munkakönyvtárat, állítsuk be programozottan:

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

Itt a munkakönyvtárat ugyanarra állítjuk be, mint korábban, de ezt a meghatározást kivettük magából a parancsból. Ezt a kódot futtatva ugyanazt az eredményt kapjuk, mint az előző példában.

ProcessBuilder: Környezeti változók

A ProcessBuilder módszereit használva könnyen lekérdezhetjük a környezeti változók listáját egy Map formájában. A környezeti változókat is könnyen beállíthatjuk, hogy a programunk használni tudja őket.

Kérjük le a jelenleg rendelkezésre álló környezeti változókat, majd adjunk hozzá néhányat későbbi használatra:

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

Itt a visszakapott környezeti változókat egy Map-be csomagoltuk, és egy forEach()-t futtattunk rajta, hogy kiírjuk az értékeket a konzolunkra.

Ezt a kódot futtatva megkapjuk a gépünkön lévő környezeti változók listáját:

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

Most, adjunk hozzá egy környezeti változót ehhez a listához, és használjuk fel:

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

Ezt a kódot futtatva megkapjuk:

value1

A program futásának befejezése után természetesen ez a változó nem marad a listában.

ProcessBuilder: .bat és .sh fájlok futtatása

Ha egy fájlt szeretnénk futtatni, ismét csak a ProcessBuilder példányt látjuk el a szükséges információkkal:

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

A kód futtatásának eredményeképpen megnyílik a parancssor és végrehajtja a .bat fájlt:

Következtetés

Ebben a cikkben a héjparancsok Java nyelven történő futtatásának példáit vizsgáltuk. Ehhez a Runtime és ProcessBuilder osztályokat használtuk.

A Java segítségével egyetlen vagy több shell parancsot futtathatunk, shell szkripteket futtathatunk, a terminál/parancssorozatot futtathatjuk, munkakönyvtárakat állíthatunk be és környezeti változókat manipulálhatunk a core osztályok segítségével.

Vélemény, hozzászólás? Kilépés a válaszból

Az e-mail-címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük

Archívum

  • 2022 január
  • 2021 december
  • 2021 november
  • 2021 október
  • 2021 szeptember

Meta

  • Bejelentkezés
  • Bejegyzések hírcsatorna
  • Hozzászólások hírcsatorna
  • WordPress Magyarország
  • 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 | Theme by ThemeinProgress | Proudly powered by WordPress