web-dev-qa-db-ja.com

JSchで簡単なSSH接続

私はこの簡単な例から何かを作ろうとしています:

SSH、Androidでリモートコマンドを実行

私はAndroid電話からSSHを使用してLinuxサーバーに接続できるかどうかを確認したいのですが、機能しません...

これが私のメインコードです:

package com.example.ssh;

import Java.util.Properties;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import Android.os.Bundle;
import Android.app.Activity;

 public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    try
    {
        JSch jsch = new JSch();
          Session session = jsch.getSession("root","192.168.0.26", 22);
          session.setPassword("xxxxx");

          // Avoid asking for key confirmation
          Properties prop = new Properties();
          prop.put("StrictHostKeyChecking", "no");
          session.setConfig(prop);

          session.connect();

    }
    catch (Exception e)
    {
      System.out.println(e.getMessage());
    }
}
}

私は何を間違えましたか?エラーメッセージがなく、LinuxにSSH接続が表示されません。ライブラリjschとjzlibを追加しました。 PuTTYセッションに接続しても問題ありません。

EDIT1:実際、問題の解決方法がわからなくても機能しない理由を説明するエラーを見つけました。エラーは:

Android.os.NetworkOnMainThreadException

つまり、アプリがメインスレッドでネットワーク操作を実行できないことを意味しているようです...

15
Pozinux

そのコードを別のスレッドで実行する必要があるので、UIスレッドをハングアップさせないことが、その例外の意味です。 UIスレッドがネットワーク呼び出しを実行している場合、UIを再描画できないため、アプリがネットワーク呼び出しの終了を待機している間、UIが応答しないフリーズされたUIがユーザーに表示されます。 Androidは、このようなユーザーエクスペリエンスの悪さを避けたいので、この例外をスローして、このようなことを行うのを防ぎます。

OnCreate()メソッドは、SSH接続を実行するために別のスレッド(生のスレッドではなくAsyncTaskを使用することをお勧めします)を呼び出す必要があります。その後、結果をUIスレッドにポストバックし、UIスレッドからアプリケーションのUIを安全に更新できます。

http://developer.Android.com/reference/Android/os/AsyncTask.html

17
chubbsondubs

chubbsondubsのソリューションは完璧です。この問題のために作成したコードを、簡単な解決策を求めている人たちにも共有したいと思います。

public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new AsyncTask<Integer, Void, Void>(){
       @Override
       protected Void doInBackground(Integer... params) {
           try {
                 executeRemoteCommand("root", "myPW","192.168.0.26", 22);
           } catch (Exception e) {
                 e.printStackTrace();
           }
           return null;
       }
    }.execute(1);
}

public static String executeRemoteCommand(String username,String password,String hostname,int port)
        throws Exception {
    JSch jsch = new JSch();
    Session session = jsch.getSession(username, hostname, port);
    session.setPassword(password);

    // Avoid asking for key confirmation
    Properties prop = new Properties();
    prop.put("StrictHostKeyChecking", "no");
    session.setConfig(prop);

    session.connect();

    // SSH Channel
    ChannelExec channelssh = (ChannelExec)
            session.openChannel("exec");
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    channelssh.setOutputStream(baos);

    // Execute command
    channelssh.setCommand("lsusb > /home/pi/test.txt");
    channelssh.connect();
    channelssh.disconnect();

    return baos.toString();
}
16
Frange

A Kotlin ソリューション:

import Android.os.AsyncTask
import Android.os.Bundle
import Android.support.v7.app.AppCompatActivity
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import Java.io.ByteArrayOutputStream
import Java.util.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        SshTask().execute()
    }

    class SshTask : AsyncTask<Void, Void, String>() {
        override fun doInBackground(vararg p0: Void?): String {
            val output = executeRemoteCommand("demo", "password", "test.rebex.net")
            print(output)
            return output
        }
    }
}

fun executeRemoteCommand(username: String,
                         password: String,
                         hostname: String,
                         port: Int = 22): String {
    val jsch = JSch()
    val session = jsch.getSession(username, hostname, port)
    session.setPassword(password)

    // Avoid asking for key confirmation.
    val properties = Properties()
    properties.put("StrictHostKeyChecking", "no")
    session.setConfig(properties)

    session.connect()

    // Create SSH Channel.
    val sshChannel = session.openChannel("exec") as ChannelExec
    val outputStream = ByteArrayOutputStream()
    sshChannel.outputStream = outputStream

    // Execute command.
    sshChannel.setCommand("ls")
    sshChannel.connect()

    // Sleep needed in order to wait long enough to get result back.
    Thread.sleep(1_000)
    sshChannel.disconnect()

    session.disconnect()

    return outputStream.toString()
}

build.gradle 追加:

dependencies {
    ...
    compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
}
2
phoenix