Skip to content

Archives

  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月

Categories

  • カテゴリーなし
Trend RepositoryArticles and guides
Articles

Java でシェル コマンドを実行する

On 10月 23, 2021 by admin
  • はじめに
  • Runtime.exec()
  • String からコマンドを実行する
  • 作業ディレクトリの指定
  • 環境変数の使用
  • Running .bat and .sh Files
  • ProcessBuilder
  • ProcessBuilder: Strings からコマンドを実行する
  • ProcessBuilder: 作業ディレクトリを指定する
  • ProcessBuilder: 環境変数
  • ProcessBuilder: .bat および .sh ファイルを実行する

はじめに

今回は、Runtime と ProcessBuilder クラスを活用して、Java でシェル コマンドとスクリプトを実行する方法を紹介します。

私たちは日々の仕事で多くのものを自動化するためにコンピュータを使っています。 システム管理者は常に多くのコマンドを実行しますが、その中には非常に反復的で、実行の合間に最小限の変更しか必要としないものもあります。 すべてを手動で実行する必要はありません。 Java を使用して、単一または複数のシェル コマンドの実行、シェル スクリプトの実行、ターミナル/コマンド プロンプトの実行、作業ディレクトリの設定、コア クラスによる環境変数の操作などが可能です。

Runtime.exec()

The Runtime クラス in Java は高レベル クラスで、すべての Java アプリケーションで存在するものです。

getRuntime() メソッドを介してアプリケーションに関連付けられたランタイムを抽出することにより、exec() メソッドを使用して直接コマンドを実行したり、.bat/.sh ファイルを実行することができます。

exec() メソッドにはいくつかのオーバーロードされたバリエーションがあります:

  • public Process exec(String command) – command に含まれるコマンドを別のプロセスで実行します。
  • public Process exec(String command, String envp) – command を、環境変数の配列と一緒に実行します。
  • public Process exec(String command, String envp, File dir) – dir ディレクトリの中から指定された環境変数とともに command を実行する.
  • public Process exec(String cmdArray) – 文字列の配列の形式でコマンドを実行する.
  • public Process exec(String cmdarray, String envp, File dir) – dir ディレクトリ内から環境変数を指定してコマンドを実行する。

これらの処理はインタープリタから外部で実行されるため、システムに依存することは特筆すべきだろう。 これらは同じことを実現します。 command はいずれにせよ配列に分解されるので、この2つのどれを使っても同じ結果になるはずです。

exec("dir /folder")とexec(new String{"dir", "/folder"}のどちらを使うかはあなた次第です。

これらのオーバーロードされたメソッドが互いにどう違うか、いくつかの例を書いて見ましょう。

String からコマンドを実行する

これらの 3 つのうち、最も単純な方法から始めましょう:

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

このコードを実行すると、String 形式で提供されたコマンドが実行されます。 しかし、これを実行しても何も表示されません。

これが正しく実行されたかどうかを検証するために、process オブジェクトを取得したいと思うでしょう。

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

ここで、exec()メソッドの後にこのメソッドを実行すると、次のような結果が得られるはずです:

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

他の例でも、Processインスタンスからプロセス情報を抽出する必要があることを覚えておいてください。

作業ディレクトリの指定

例えば、あるフォルダからコマンドを実行したい場合、次のようにします:

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

ここでは、exec()メソッドにcommand、新しい環境変数用のnull、作業ディレクトリとして設定するnew File()を用意しています。

注目すべきは、dirなどのコマンドの前にcmd /cが追加されている点です。

Windowsで作業しているので、これでcmdが開き、/cがその後のコマンドを実行します。 この場合、dirです。

なぜ、pingの例では必須ではなかったのに、この例では必須なのかは、SOユーザーがうまく答えてくれていますね。

Running the previous piece of code will result in:

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

Let’s look at how we could supply the previous command in several individual parts, instead of a single String:

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

Running this piece of code will also result in.ここで、このコードを実行すると、結果はどうなるか見てみましょう。

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

結局のところ、単一の文字列または文字列配列を使用するアプローチにかかわらず、入力したコマンドは常に配列に分解された後、基本ロジックで処理されます。

環境変数の使用

環境変数をどのように使用するか見ていきましょう。 ここでは、echo を使用して var1 の値を出力しています。

このコードを実行すると、次の結果が得られます:

value1

Running .bat and .sh Files

時には、すべてをファイルにオフロードして、プログラム的に追加する代わりにそのファイルを実行する方がずっと簡単なことがあります。

echo Hello World

次に、前と同じ方法で作成します。

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

これでコマンドプロンプトが開き、設定した作業ディレクトリで .bat ファイルが実行されます。

このコードを実行すると、確かに次の結果が得られます:

オーバーロードされた exec() 署名のすべてが完了したので、ProcessBuilder クラスとそれを使用してコマンドを実行する方法について見ていきましょう。

ProcessBuilder

ProcessBuilder は、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 for the Runtime クラス

が exec() メソッドの入力を受けてコマンドを実行する方法を見て、同様にそれを使用する方法についても良いアイデアを得られました。

これは String cmdarray を受け取り、実行するにはそれで十分です。 あるいは、String envp や File dir などのオプションの引数を与えることもできます。

これらのオプションを調べてみましょう。

ProcessBuilder: Strings からコマンドを実行する

cmd /c dir のような単一の String を提供できる代わりに、この場合、それを分割する必要があります。 たとえば、以前のように C:/Users ディレクトリにあるファイルをリストアップしたい場合、次のようにします:

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

実際に Process を実行するには、start() コマンドを実行して返された値を Process インスタンスに割り当てます。

このコードを実行すると:

 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

しかしこの方法は以前のものよりも優れているとは言えません。 ProcessBuilder クラスで便利なのは、カスタマイズが可能なことです。 コマンドだけでなく、プログラム的に設定することができます。

ProcessBuilder: 作業ディレクトリを指定する

コマンドで作業ディレクトリを指定する代わりに、プログラム的に設定します。

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

ここで、作業ディレクトリを以前と同じに設定しましたが、その定義をコマンド自体から移動しました。 このコードを実行すると、前回の例と同じ結果が得られます。

ProcessBuilder: 環境変数

ProcessBuilder のメソッドを使用すると、Map の形式で環境変数のリストを取得することが簡単にできます。

現在利用可能な環境変数を取得し、後で使用するためにいくつか追加してみましょう:

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

ここでは、返された環境変数を Map に詰め、forEach() を実行してコンソールに値を出力しています。

このコードを実行すると、あなたのマシンにある環境変数のリストが得られます:

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

では、そのリストに環境変数を追加して使ってみましょう:

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

このコードを実行すると:

value1

もちろん、プログラムの実行が終了したら、この変数はリストに残りません:

ProcessBuilder: .bat および .sh ファイルを実行する

ファイルを実行したい場合は、再度、ProcessBuilder インスタンスに必要な情報を提供します。 そのためにRuntimeクラスとProcessBuilderクラスを使用しました。

Java を使用すると、単一または複数のシェルコマンドの実行、シェルスクリプトの実行、ターミナル/コマンドプロンプトの実行、作業ディレクトリの設定、コアクラスによる環境変数の操作などを行うことができます。

コメントを残す コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

アーカイブ

  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • 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 | Theme by ThemeinProgress | Proudly powered by WordPress