2012-04-24 7 views
1

私はアンドロイドのアプリケーションにコマンドを送信し、このphpのファイルを持っている:どのようにして、すべての可能なUNIX(シェル)コマンドをプログラムで実行できますか?

enter image description here

を私がで作業しようとしている:

Runtime.getRuntime().exec(commandLine); 
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); 

が、コマンドは、PWDエコーといくつか他の人が働いていません。

は、私は次の例外を取得:

java.io.IOException: Error running exec(). Command: [pwd] Working Directory: null Environment: null 

私の知る限りは、任意のシェル環境がないので、これは理解して。

それから私は.SHファイルに私がしたいコマンドを書いて試してみましたが、その後、コマンドをこのように実行します。

Runtime rt = Runtime.getRuntime(); 
Process proc = rt.exec("sh /runCmds/shTest.sh"); 
InputStream is = proc.getInputStream(); 

をし、PWD、エコーやコマンドのほとんどの問題を解決しました。

しかし、後で私は実行している命令の状態を保持したいと思った。 たとえば、ディレクトリ(cd data)を変更してコマンドを実行したい場合は、mkdir Apoel

ここに私の問題に直面します。何をすべきか?

私は別のアイデアを思い付いた:シェルスクリプト(.SH)を作る

、ユーザーがコマンドを実行しようとするたびに、その中に新しいコマンドを追加(そして再び穴スクリプト(.SH)を実行)。しかし、私はそれを行うには非常に良い方法ではないと思います!

簡単な方法はありますか?私のアプリケーションで簡単に端末を開くことはできますか?

ここでは、ターミナルエミュレータで見つかったコードですが、複雑すぎます!

https://github.com/jackpal/Android-Terminal-Emulator

答えて

0

まず、いくつかの背景。任意のPosixシステムでは、シェルで、コマンドの2種類がある:

  1. 内部コマンド
  2. 外部コマンド(LS、CP、MVは、時々もエコー)(PWD、CDは、エコー)

すべてのディレクトリコンテキストコマンド(cd、pwdなど)はシェル内で実装されたコマンドで、変更を保持する必要がある場合はシェルを実行する必要があります(例:cd /data/local/tmp)。

一方、外部コマンドはスタンドアロンであり、独立して実行できますが、親プロセス(ほとんどの場合はシェル)からディレクトリコンテキストを取得します。

ここで問題を解決してください。はい、スクリプトを使用することをお勧めしますが、ファイル編集のオーバーヘッドが必要なため、実装するのは苦労します。ただし、シェルを使用してスクリプトを作成し、-cオプションを使用して実行することができます。夏には

/system/bin/sh -c 'cd /data/local/tmp; touch abc; cp abc def; cd /; rm /data/local/tmp/abc' 

:たとえば

String sPrefix="/system/bin/sh -c 'cd someplace;"; 
String sInputCmd=getCommand(); // this is simulating your command input 
String sPostfix="'"; 

Runtime rt = Runtime.getRuntime(); 
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix); // sh -c 'cd someplace; echo do something' 
InputStream is = proc.getInputStream(); 

はしかし、これは私たちに、ディレクトリのコンテキストを設定する機能を与えるものではありませんので、我々はそれをシミュレートする必要があります。ディレクトリコンテキストは、Runtime.exec(Stringコマンド、String [] envp、File dir)メソッドを使用して追加できます。これにより、コマンド間にディレクトリ のコンテキストを維持することができます。しかし、実際にはどうしたらいいのですか? 1つの解決方法は、コマンドにpwdを追加し、出力の最後の行を新しいディレクトリコンテキストとして取得することです。したがって、

String sPath = "/"; // start in root directory 
String sPrefix = "/system/bin/sh -c 'cd someplace;"; 
String sInputCmd; // this is simulating your command input 
String sPostfix = ";echo;pwd'"; 
Runtime rt = Runtime.getRuntime(); 
while(!(sInputCmd=getCommand()).equals("")) { 
    File dir= new File(sPath); 
    Process proc = rt.exec(sPrefix+sInputCmd+sPostfix, NULL, dir); 
    InputStream is = proc.getInputStream(); 
    // Do processing on input. 
    sPath= last_line_of_is ; 
} 

最後に、最後のオプションは、あなたに端末エミュレータの1つを統合することです。

[1] http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String,%20java.lang.String%5B%5D,%20java.io.File%29

+0

あなたは**/system/bin/sh ** -c 'ここのコマンド'を意味しますが、suは意味しません! 絶対パスを使用する方が良いです。 –

+0

アンドレアス、そうです、私はスーではなくシュウを意味しました。私は訂正をしました。 – Samveen

+0

良い!私は編集しようとしましたが、それは言う:少なくとも6空白以外の文字を編集する必要があります。 :p –

0

インタラクティブシェルが、それはstdoutとstderrに出力します生成しながら、それは標準入力から受け取り、新しいコマンドを待って、実行中のままです - それは変更されるなどの環境だが、結果として、セッションの期間保持されます。シェルがユーザにとって便利であるためには、stdin、stoud、stderrをコンソール、シリアル回線、またはxtermなどを介してユーザに接続する必要があります。

Androidの場合、作成したシェルプロセスのstdin、stdout、stderrに対応するパイプに追加し、それらを使用してJavaプログラムによって提供されるコマンドをプッシュし、プログラムが解釈/表示するための出力を受け入れます。

スクリプトを作成して実行するという考え方は、スクリプトが実行される前にすべてのコマンドが入力された場合にのみ機能します。

+0

**開かれたセッション**を維持するにはどうすればよいですか? あなたはこう言っています:_それらのコマンドが実行される前にコマンドが入力されています._例を使って説明できますか? あなたは次のような意味です: 'touch abc; cp abc def; cd /; '? –

+0

セッションを開いたままにするには、シェルの同じコピーをパイプで実行し、相互作用させます。スクリプトのアイデアを使用した場合は、スクリプトのすべてのコマンドを実行してから(そしてその出力を取得する)前に、すべてのコマンドをスクリプトに入れる必要がありますあなたはもはやインタラクティブではありません。おそらく、それらの端末エミュレータのソースを理解するためにもう一度試してみてください。 –

関連する問題