13

JSch ライブラリを使用して、SSH プロトコル経由で複数のコマンドを実行しようとしていました。しかし、私は立ち往生しているようで、解決策が見つかりません。このsetCommand()メソッドは、セッションごとに 1 つのコマンドしか実行できません。しかし、Android プラットフォームの connectbot アプリのように、コマンドを順番に実行したいと考えています。これまでのところ、私のコードは次のとおりです。

package com.example.ssh;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Properties;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class ExampleSSH extends Activity {
    /** Called when the activity is first created. */
    EditText command;
    TextView result;
    Session session;
    ByteArrayOutputStream baos;
    ByteArrayInputStream bais;
    Channel channel;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        bais = new ByteArrayInputStream(new byte[1000]);
        command = (EditText) findViewById(R.id.editText1);
        result  = (TextView) findViewById(R.id.terminal);
    }

    public void onSSH(View v){
        String username = "xxxyyyzzz";
        String password = "aaabbbccc";
        String host     = "192.168.1.1"; // sample ip address
        if(command.getText().toString() != ""){
            JSch jsch = new JSch();
            try {
                session = jsch.getSession(username, host, 22);
                session.setPassword(password);

                Properties properties = new Properties();
                properties.put("StrictHostKeyChecking", "no");
                session.setConfig(properties);
                session.connect(30000);

                channel = session.openChannel("shell");
                channel.setInputStream(bais);
                channel.setOutputStream(baos);
                channel.connect();

            } catch (JSchException e) {
                // TODO Auto-generated catch block
                Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
        else{
            Toast.makeText(this, "Command cannot be empty !", Toast.LENGTH_LONG).show();
        }
    }

    public void onCommand(View v){
        try {
            bais.read(command.getText().toString().getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        baos = new ByteArrayOutputStream();
        channel.setOutputStream(baos);
        result.setText(baos.toString());

    }
}

コードはサーバーに接続されているようですが、出力がまったくないため、入力および出力配列バッファーに問題があると思います。サーバーとの間の入力と出力を適切に処理して、目的の出力を取得する方法を教えてください。

4

4 に答える 4

12

個々のコマンドの入力または出力を区別する必要がない場合は、Aaron からの回答 (\nまたはで区切られたすべてのコマンドを連続して与える;) で問題ありません。

それらを個別に処理する必要がある場合、または前のコマンドが終了する前に後のコマンドがわからない場合:同じセッション (つまり接続) で複数のexec-Channelsを次々に開くことができます (つまり、前のコマンドが閉じられた後)。 )。それぞれに独自のコマンドがあります。(ただし、それらは環境を共有しないためcd、最初のコマンドは後のコマンドには影響しません。)

コマンドごとに新しいオブジェクトを作成するのではなく、 Sessionオブジェクトを保持するように注意する必要があります。

もう 1 つのオプションは、シェル チャネルを使用して、個々のコマンドをリモート シェルに入力として (つまり、ストリームを介して) 渡すことです。ただし、あるコマンドへの入力と次のコマンドを混同しないように注意する必要があります (つまり、これは、コマンドが何を行っているかを知っている場合、またはコマンドへの入力と次のコマンドの両方を提供できる対話型のユーザーがいる場合にのみ機能します)。次のコマンドであり、どのコマンドがいつ使用されるかを知っています)。

于 2011-04-30T18:52:06.363 に答える
12

コマンドは文字列であり、リモート シェルが受け入れるものであれば何でもかまいません。試す

cmd1 ; cmd2 ; cmd3

いくつかのコマンドを順番に実行します。または

cmd1 && cmd2 && cmd3

失敗するまでコマンドを実行します。

これでもうまくいくかもしれません:

cmd1
cmd2
cmd3

またはJavaで:

channel.setCommand("cmd1\ncmd2\ncmd3");

補足: コードにパスワードとユーザー名を入れないでください。それらをプロパティ ファイルに入れ、システム プロパティを使用してプロパティ ファイルの名前を指定します。そうすれば、プロジェクトの外でもファイルを保持し、パスワード/ユーザー名が漏洩しないようにすることができます。

于 2011-04-29T12:12:00.827 に答える
4

ユーザー名、パスワード、ポート 22、および IP を保持する SCPInfo オブジェクトをセットアップします。

    List<String> commands = new ArrayList<String>();
    commands.add("touch test1.txt");
    commands.add("touch test2.txt");
    commands.add("touch test3.txt");
    runCommands(scpInfo, commands);

public static void runCommands(SCPInfo scpInfo, List<String> commands){
    try {
        JSch jsch = new JSch();
        Session session = jsch.getSession(scpInfo.getUsername(), scpInfo.getIP(), scpInfo.getPort());
        session.setPassword(scpInfo.getPassword());
        setUpHostKey(session);
        session.connect();

        Channel channel=session.openChannel("shell");//only shell  
        channel.setOutputStream(System.out); 
        PrintStream shellStream = new PrintStream(channel.getOutputStream());  // printStream for convenience 
        channel.connect(); 
        for(String command: commands) {
            shellStream.println(command); 
            shellStream.flush();
        }

        Thread.sleep(5000);

        channel.disconnect();
        session.disconnect();
    } catch (Exception e) { 
        System.err.println("ERROR: Connecting via shell to "+scpInfo.getIP());
        e.printStackTrace();
    }
}

private static void setUpHostKey(Session session) {
    // Note: There are two options to connect
    // 1: Set StrictHostKeyChecking to no
    //    Create a Properties Object
    //    Set StrictHostKeyChecking to no
    //    session.setConfig(config);
    // 2: Use the KnownHosts File
    //    Manually ssh into the appropriate machines via unix
    //    Go into the .ssh\known_hosts file and grab the entries for the hosts
    //    Add the entries to a known_hosts file
    //    jsch.setKnownHosts(khfile);
    java.util.Properties config = new java.util.Properties();
    config.put("StrictHostKeyChecking", "no");
    session.setConfig(config);
}
于 2012-03-25T20:45:52.290 に答える