Java实践 — SSH远程执行Shell脚本
1. SSH简介
2. 实现原理
3. 示例代码及分析
- SSHCommandExecutor.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Vector; import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session; /**
* This class provide interface to execute command on remote Linux.
*/ public class SSHCommandExecutor {
private String ipAddress; private String username; private String password; public static final int DEFAULT_SSH_PORT = 22; private Vector<String> stdout; public SSHCommandExecutor(final String ipAddress, final String username, final String password) {
this.ipAddress = ipAddress;
this.username = username;
this.password = password;
stdout = new Vector<String>();
} public int execute(final String command) {
int returnCode = 0;
JSch jsch = new JSch();
MyUserInfo userInfo = new MyUserInfo(); try {
// Create and connect session.
Session session = jsch.getSession(username, ipAddress, DEFAULT_SSH_PORT);
session.setPassword(password);
session.setUserInfo(userInfo);
session.connect(); // Create and connect channel.
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command); channel.setInputStream(null);
BufferedReader input = new BufferedReader(new InputStreamReader(channel
.getInputStream())); channel.connect();
System.out.println("The remote command is: " + command); // Get the output of remote command.
String line;
while ((line = input.readLine()) != null) {
stdout.add(line);
}
input.close(); // Get the return code only after the channel is closed.
if (channel.isClosed()) {
returnCode = channel.getExitStatus();
} // Disconnect the channel and session.
channel.disconnect();
session.disconnect();
} catch (JSchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return returnCode;
} public Vector<String> getStandardOutput() {
return stdout;
} public static void main(final String [] args) {
SSHCommandExecutor sshExecutor = new SSHCommandExecutor("xx.xx.xx.xx", "username", "password");
sshExecutor.execute("uname -s -r -v"); Vector<String> stdout = sshExecutor.getStandardOutput();
for (String str : stdout) {
System.out.println(str);
}
}
}getSession()只是创建一个session,需要设置必要的认证信息之后,调用connect()才能建立连接。
调用openChannel(String type) 可以在session上打开指定类型的channel。该channel只是被初始化,使用前需要先调用connect()进行连接。Channel的类型可以为如下类型:- shell - ChannelShell
- exec - ChannelExec
- direct-tcpip - ChannelDirectTCPIP
- sftp - ChannelSftp
- subsystem - ChannelSubsystem
其中,ChannelShell和ChannelExec比较类似,都可以作为执行Shell脚本的Channel类型。它们有一个比较重要的区别:ChannelShell可以看作是执行一个交互式的Shell,而ChannelExec是执行一个Shell脚本。 - MyUserInfo:
import com.jcraft.jsch.UserInfo; /**
* This class provide interface to feedback information to the user.
*/
public class MyUserInfo implements UserInfo {
private String password; private String passphrase; @Override
public String getPassphrase() {
System.out.println("MyUserInfo.getPassphrase()");
return null;
} @Override
public String getPassword() {
System.out.println("MyUserInfo.getPassword()");
return null;
} @Override
public boolean promptPassphrase(final String arg0) {
System.out.println("MyUserInfo.promptPassphrase()");
System.out.println(arg0);
return false;
} @Override
public boolean promptPassword(final String arg0) {
System.out.println("MyUserInfo.promptPassword()");
System.out.println(arg0);
return false;
} @Override
public boolean promptYesNo(final String arg0) {
System.out.println("MyUserInfo.promptYesNo()");
System.out.println(arg0);
if (arg0.contains("The authenticity of host")) {
return true;
}
return false;
} @Override
public void showMessage(final String arg0) {
System.out.println("MyUserInfo.showMessage()");
}
}MyUserInfo实现了接口UserInfo,主要是为获得运行执行的用户信息提供接口。大部分实现方法中,没有做实质性的工作,只是输出一下trace信息,帮助判断哪个方法被执行过。4. 执行结果分析
1. 如果不设置UserInfo,会抛出JSchException异常,提示找不到host:
2. 如果MyUserInfo实现了接口UserInfo,但是只是@Override一些函数,会出现如下错误:
虽然可以找到host,但是会拒绝访问host。发现所有@Override函数中,get方法返回的都是null,prompt方法返回的都是false。3. 为了判断这些Override的methods中,那些是有用的,在每个method中加入trace信息。发现只有promptYesNo(final String)会被调用到,输出如下图所示:
4. promptYesNo(final String)是向用户提出一个yes或者no的问题,来决定是否允许连接远程主机。这才是决定连接是否成功的一个关键函数。如果返回值为true,则允许连接;如果返回值为false,则拒绝连接。最后正确连接后的输出入下图所示:
Reference
来自:http://blog.csdn.net/jmyue/article/details/14003783
Java实践 — SSH远程执行Shell脚本的更多相关文章
- Java实践 — SSH远程执行Shell脚本(转)
原文地址:http://www.open-open.com/lib/view/open1384351384024.html 1. SSH简介 SSH是Secure Shell的缩写,一 ...
- Java SSH远程执行Shell脚本实现(转)
前言 此程序需要ganymed-ssh2-build210.jar包(下载地址:http://www.ganymed.ethz.ch/ssh2/) 为了调试方便,可以将\ganymed-ssh2-bu ...
- JAVA远程执行Shell脚本类
1.java远程执行shell脚本类 package com.test.common.utility; import java.io.IOException; import java.io.Input ...
- [linux] ssh远程执行本地脚本
1.ssh密钥登录 略 2.免确认机器指纹,ssh -o StrictHostKeyChecking=no [root@XM-v125 ~]# ssh wykai@192.168.0.110 The ...
- Python ssh 远程执行shell命令
工具 python paramiko 远程执行命令 import paramiko ssh = paramiko.SSHClient() key = paramiko.AutoAddPolicy() ...
- Java SSH远程执行Shell命令、shell脚本实现(Ganymed SSH)
jar包下载地址: http://www.ganymed.ethz.ch/ssh2/ 此源码的好处就是没有依赖很多其他的包,拷贝过来干干净净.具体代码实现可以看下文,或参考官方文档,在下载的压缩包里g ...
- 远程执行shell脚本的小技巧
很多时候需要批量跑脚本执行任务,但又不想分发再执行,而是直接一条命令下去就跑脚本,该怎么玩比较嗨? 例如以下脚本: #!/bin/bash echo "$@" echo " ...
- 远程执行shell脚本
ssh -p2016 apache@10.10.18.130 '/bin/sh /data/www/vhosts/WOStest3_ENV/update_env.sh' 需要设置shell远程免密码登 ...
- SaltStack远程执行shell脚本
编辑文件fansik.sh 脚本内容: #!/bin/bash # Author: fansik # data: 2017年 09月 26日 星期二 :: CST touch /tmp/fansik. ...
随机推荐
- Asp.Net时间方法大全
DateTime dt = DateTime.Now; //当前时间 DateTime startWeek = dt.AddDays(- Convert.ToInt32(dt.DayOfWeek.To ...
- hive查询遇到java.io.EOFException: Unexpected end of input stream错误
hive查询遇到java.io.EOFException: Unexpected end of input stream错误 原因基本上有两个: 空文件 不完整的文件 解决办法: 删除对应文件- 参考 ...
- Centos7 ss搭建
1.安装pip Pip 是 Python 的包管理工具,下载ss十分方便,但是centos是没有pip的,我们需要安装一个. yum install python-setuptools & e ...
- My To Do List (Task Manager)
My To Do List (Task Manager) With everything that business owners deal with throughout their day, th ...
- go语言可变参数的坑
0x00 前提 对可变参数不了解的同学,可以先看这篇文章可变参数终极指南 0x01 第一个坑 不能通过空接口类型向可变参数传递一个普通的切片 ,需要将普通切片转换为空接口切片 0x02 第二个坑 可变 ...
- java基础篇---枚举详解
在JDK1.5之前,JAVA可以有两种方式定义新类型:类和接口,对于大部分面向对象编程,有这两种似乎就足够了,但是在一些特殊情况就不合适.例如:想要定义一个Color类,它只能有Red,Green,B ...
- GridView“GridView1”激发了未处理的事件“RowDeleting”
GridView“GridView1”激发了未处理的事件“RowDeleting”. 原因:1.模板列或者buttoncommand里的commandname=“Delete”,“Update”等关键 ...
- Chrome 插件编写日记
Chrome 插件,你可以理解为打开了一个网页,但是里面只有前端语言,JavaScript, HTML + css 但是有一点区别的是,它是有一个名字为 manifest.json 的配置文件的,里面 ...
- 宇宙最强spacemacs
这个标题背后的潜台词其实是:逼格是什么炼成的? 此处省略一万字. Emacs就不多说了,神之编辑器,但其快捷键实在是....Evil.好啦,现在来了Spacemacs,结合Vim与Emacs二者的优点 ...
- MapReduce教程(一)基于MapReduce框架开发<转>
1 MapReduce编程 1.1 MapReduce简介 MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算,用于解决海量数据的计算问题. MapReduce分成了两个部分: ...