11

私は決定するための最も効率的な方法を検討しています:

  • ユーザー提供のコマンドラインの前にシェル実行可能ファイルを追加する必要がありますか
  • はいの場合、その実行可能ファイルは何ですか? (/bin/sh? /usr/bin/perl? /usr/bin/ksh? c:/../cmd.exe?)

Java からシェル スクリプトを開始するには、代わりにシェルを開始する必要があることが知られています。

ProcessBuilder pb = new ProcessBuilder("/bin/sh", "script.sh", "arg1", "arg2);

バイナリを開始するには、バイナリ自体を開始する必要があります。

ProcessBuilder pb = new ProcessBuilder("/path/binary", "arg1", "arg2);

シェルでバイナリを実行すると、次のエラーが発生します。

ProcessBuilder pb = new ProcessBuilder("/bin/sh", "/path/binary", "arg1", "arg2);
(sh: cannot execute binary file)

シェル バイナリなしでシェル スクリプトを実行すると、次のエラーが発生します。

ProcessBuilder pb = new ProcessBuilder("script.sh", "arg1", "arg2);
(error 2: file not found)

アプリケーションがバイナリかスクリプトかを認識できない状況に陥っています。

開始されたアプリケーションは、エンド ユーザーによって提供されるイベント ハンドラです。Unix で実行されるシェル スクリプトである可能性が最も高いです。ただし、Windows では *.cmd である場合もあれば、あいまいなプラットフォームで実行される Perl スクリプトである場合もあります。結局のところ、それは Java です。

私の最初の素朴な試みは、シェルでコマンドラインを開始し、それが機能するかどうかを確認することでした. そうでない場合は、バイナリとして実行してみてください。

これは見苦しく危険です。プラットフォームとシェルの未知の組み合わせでは、2 回目の実行でもスクリプトが実行され、2 回目の結果が予測不能になる可能性があります。

また、スクリプトを開始できなかったときから、スクリプト自体の問題が原因でスクリプトがいつ正常に開始され、失敗したのかわかりません。

私が今考えている最善のことは次のとおりです。

  • スクリプトを読み、印刷できないバイトを探します
  • 見つかった場合は、バイナリと見なします
  • そうでない場合は、/bin/sh (Windows の場合は cmd.exe) を追加します。

何か良い案があればアドバイスお願いします。

更新/部分的な解決

私と考えを共有してくれたすべての人に感謝します。

結局、私は自分自身とインターネットの残りの部分を混乱させました:)

次の場合、ユーザーが入力したコマンド ラインの前に、shall バイナリを追加する必要はありません。

  1. スクリプトはPATHにあります
  2. (Unix の場合) スクリプトは実行可能です
  3. (Unix の場合) スクリプトには #!/path/to/interpreter があります

コードをテストしているときに、これらの条件のいずれかが満たされませんでした。:-(

スクラッチスクリプトから慎重にテストを実行した後、実行されました。

ポイント 3 はユーザーのみが行うことができ、ユーザー マニュアルに記載する必要があります。

これらのスクリプトがターゲット システムに伝達される方法が原因で、スクリプトが実行可能でなく、PATH に含まれていない場合があります。

私が気にする唯一のパスは相対パスなので、相対パスの前に ./ を追加するだけで十分です。

Unix (およびその他のプラットフォーム) でスクリプトを実行可能にすることは、さらに困難です。WORAではありません。その前に /bin/sh を配置すると役立つ場合がありますが、覚えている限り、Solaris のすぐ下では、シェルは実行不可能なスクリプトを実行しません。

今週後半に別の更新を投稿します。

4

3 に答える 3

3

コマンドを実行するためだけにこれらのフープを飛び越えなければならないという危険信号である必要があります。1 つ目は、これが非常に複雑になっていること、2 つ目は、Java がプラットフォームに依存しないように設計されていることです。組み込みクラスを機能させるために OS 固有のハックを調査している場合は、一歩下がって想定を再検討する必要があります。

ProcessBuilder pb = new ProcessBuilder("script.sh", "arg1", "arg2);
(error 2: file not found)

エラー メッセージは、「シェル スクリプトを実行できません」などのエラーではなく、「ファイルが見つかりません」であることに注意してください。このエラーの原因として最も可能性が高いのは、スクリプトを実行していることではなく、スクリプトが見つからないことです。

./スクリプトが現在のディレクトリにある場合は、先頭に a を追加する必要があります。実行可能ファイルへの明示的なパスを指定しない場合、実行可能ファイルは$PATH環境変数のいずれかのディレクトリに存在する必要があります。.通常、現在のディレクトリはデフォルトでは含まれていません。$PATH

ProcessBuilder pb = new ProcessBuilder("./script.sh", "arg1", "arg2);

スクリプト名がユーザー指定の値である場合、ユーザーにこの要件を課します。ユーザーに を追加することもできますが./、UNIX プログラムは一般に、あまり役に立たないようにします。彼らが置くのを忘れたら、./それは彼らの問題です!

于 2012-01-09T05:29:35.423 に答える
2

考えられる解決策の 1 つは、プログラム内から実行中のスクリプト/バイナリをラップするスクリプトを生成することです。そうすれば、それが常にスクリプトであることがわかります。生成されたスクリプトは、単純に内部スクリプト/バイナリを実行し、エラー コードを返します (場合によっては、入出力をリダイレクトします)。終了したら、簡単に削除できます。Java では、一時ファイルを非常に簡単に作成できます。

于 2012-01-09T05:25:10.147 に答える
0

On

ProcessBuilder pb = new ProcessBuilder("/bin/sh", "/path/binary", "arg1", "arg2); (sh: cannot execute binary file)

ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", "/path/binary", "arg1", "arg2); (sh: cannot execute binary file)

One option is to accept the interpreter path as another argument (probably from a list of known values) from the users.

(This could have been a comment. I could not get the formatting right)

于 2012-01-09T05:46:01.540 に答える