- PR -

Runtime#exec() で起動したping でDNS エラー

1
投稿者投稿内容
だい
会議室デビュー日: 2004/11/19
投稿数: 10
投稿日時: 2008-09-17 13:22
独学でjavaを勉強していますが、どうしても自力解決できないので質問させてください。

環境:
windowsXP SP2
SDK 1.5
tomcat 5.5

下記のコードは、サーブレット上でRuntime#exec() を使って別プロセスでping コマンドをlocalhost に対して行っているというものです。

下記のコードを実行するとエラー出力として次のメッセージが出力されてしまいます。

Ping request could not find host localhost. Please check the name and try again.

普通にMS-DOS コマンドプロンプト上では問題なくping がlocalhost に届くのですが、サーブレット上から行うと上記エラーとなります。

java 特有のDNSに関わる問題とは想像できるのですが、何をどのように修正すればよいか検討つきません。有識者の方のご助言お願いします。


String[] execl = { "c:\WINDOWS\system32\cmd.exe", "\c", "ping localhost" };
String[] envcl = { "PATH=" + System.getProperty("java.library.path") };

try {
// コマンドを実行する
proc = Runtime.getRuntime().exec(execl, envcl);

// コマンドの終了を待つ
int exitValue = proc.waitFor();
System.out.println("実行結果コード = " + exitValue);
} catch( Exception e ) {
e.printStackTrace();
} finally {
InputStream inStream = proc.getInputStream();
InputStream errStream = proc.getErrorStream();
OutputStream outStream = proc.getOutputStream();

// 標準出力を得る
BufferedReader inReader = new BufferedReader(new InputStreamReader(
inStream));
while( (line = inReader.readLine()) != null ) {
System.out.println(line);
}

// エラー出力を得る
BufferedReader errReader = new BufferedReader(new InputStreamReader(
errStream));
while( (line = errReader.readLine()) != null ) {
System.out.println(line);
}

inStream.close();
errStream.close();
outStream.close();

proc.destroy();
}

yutavigour
会議室デビュー日: 2008/05/30
投稿数: 7
投稿日時: 2008-09-17 14:25
String[] execl = { "c:\\WINDOWS\\system32\\cmd.exe", "\\c", "ping localhost" };
String[] envcl = { "PATH=" + System.getProperty("java.library.path") };
Runtime.getRuntime().exec(execl, envcl);

上記を以下にすると実行されると思います。(同環境で動作まで確認)
String[] execl = {"ping", "localhost"};
Runtime.getRuntime().exec(execl);

当該プロセスはTomcatのサブプロセスとして動作するはずなので、
Tomcatが正常に動作しているならコマンドキックの仕方がまずいか、
ネットワーク設定がまずいかでしょう。
後者ならhostsやfirewallの設定を見直すことになると思います。

余談ですが、ストリーム出力位置は、標準入力・出力・エラーのデータが
欠落するかもしれないのでプロセスの終了を待つ前にハンドリングした方がいいかもです。
また、デストロイは不要かと。
だい
会議室デビュー日: 2004/11/19
投稿数: 10
投稿日時: 2008-09-17 15:13
yutavigourさま、お返事ありがとうございます。

私のほうでもyutavigourさまから教えていただいた記述に変更して実行したらうまくいきました。

結局変更前と変更後では下記2点が異なるものと思います。

1. Runtime#exec() に環境変数を渡すこと
2. ping コマンドの実行の仕方(cmd経由かでないか)

1. についてはサブプロセスでは環境変数が一切セットされていないのでRuntime#exec()にて必要な環境変数を渡したのですが、この認識で間違いはないのでしょうか?

2. については「当該プロセスはTomcatのサブプロセスとして動作するはず」と回答されていますが、逆に、cmd.exe 経由でしか動作しないexe? とはたとえばecho など、組み込みコマンド? が該当するという認識でいいのでしょうか?

最後に、結局今回の一見DNSがおかしいようなエラーは上記1に原因があるように思いますが、原因の詳細がいまいちつかめません。理由を教えていただければ幸いです。


yutavigour
会議室デビュー日: 2008/05/30
投稿数: 7
投稿日時: 2008-09-18 23:52
どもです。

1. に関しては、pingなどのOS上パスの通っているコマンドでは不要です。
独自のEXEを実装してOS上パスを通したくない場合以外必要ないと思います。

2. に関しては、cmd.exeをキックしてそれからping.exeを起動したいなら
OutputStreamを使ってpingを実行するように実装する必要がある気がします。
(試していません)
そもそもその必要性が見えませんが、たとえばFTPなどの対話型のEXEを
起動したい場合は、OutputStreamを使用して制御できそうな気がします。
(これも試していません。)

また、DNSエラーぽい件については、再現できないので不明ですが、
Runtime#execの第一引数にはコマンドと引数を配列にして渡しましょう
という仕様なのでダイさんが設定されていた配列の3番目の"ping localhost"
の指定の仕方がおかしくて出ていたのかと思われます。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-09-19 08:28
引用:

だいさんの書き込み (2008-09-17 13:22) より:
String[] execl = { "c:WINDOWSsystem32cmd.exe", "c", "ping localhost" };
String[] envcl = { "PATH=" + System.getProperty("java.library.path") };


横から口を出すだけになりますが、会議室のシステムのバックスラッシュ(円記号)の処理が変なのでそれと紛らわしいですが、バックスラッシュが1個しかないのは会議室のシステムのためかもしれませんが、"/c" ではなく "\c" になっているのは変ですよね。
1

スキルアップ/キャリアアップ(JOB@IT)