简单的SSH连接与JSch

我正在试图从这个简单的例子中做出一些事情:

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。 我没有问题与腻子会议连接。

编辑1:其实,我发现一个错误,解释为什么它不起作用,即使我不知道如何解决问题。 错误是:

android.os.NetworkOnMainThreadException

所以这似乎意味着应用程序不能执行其主线程上的网络操作…

你必须在另一个线程中执行这个代码,所以你不要挂上UI线程就是这个exception的意思。 如果UI线程正在执行网络调用,则无法重新绘制UI,以便用户在网络调用等待完成时看到不响应的冻结UI。 Android想要避免这样的不好的用户体验,所以通过抛出这个exception来阻止你做这样的事情。

你的onCreate()方法应该调用另一个线程(我建议在原线程上使用AsyncTask)来执行SSH连接。 然后,当它完成后,可以将结果发回UI线程,并安全地从UI线程更新应用程序的UI。

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

chubbsondubs的解决方案是完美的。 我只是想分享我为这个问题所做的代码,以供想要快速解决方案的人使用:

 public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new AsyncTask(){ @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(); } 

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() { 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' }