标签:ganymed ssh2 远程传输文件 ganymed ssh2 scp协议 ganymed ssh2 模拟类似fil
为了传输文件或者目录,我们使用 Ganymed SSH2中的SCPClient类,这个类实现了scp命令功能。
下面的代码包含了传输单个文件和传输目录的功能:
package com.doctor.ganymed_ssh2;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.SCPOutputStream;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
/**
* 1.确保所连接linux机器安装ssh,并且服务打开;
* 2.密码登陆,需配置文件:
* ssh配置文件: /ect/ssh/sshd_config
* 配置项:PasswordAuthentication yes
*
* 验证登陆成功否:ssh 127.0.0.1(/other)
*
* @see http://www.ganymed.ethz.ch/ssh2/FAQ.html
* http://www.programcreek.com/java-api-examples/index.php?api=ch.ethz.ssh2.StreamGobbler
* http://www.javawebdevelop.com/3240343/
* http://www.programcreek.com/java-api-examples/index.php?api=ch.ethz.ssh2.SCPClient
* @author doctor
*
* @time 2015年8月5日
*/
public final class SSHAgent {
private Logger log = LoggerFactory.getLogger(getClass());
private Connection connection;
public void initSession(String hostName, String userName, String passwd) throws IOException {
connection = new Connection(hostName);
connection.connect();
boolean authenticateWithPassword = connection.authenticateWithPassword(userName, passwd);
if (!authenticateWithPassword) {
throw new RuntimeException("Authentication failed. Please check hostName, userName and passwd");
}
}
/**
* Why can't I execute several commands in one single session?
*
* If you use Session.execCommand(), then you indeed can only execute only one command per session. This is not a restriction of the library, but rather an enforcement by the underlying SSH-2 protocol (a Session object models the underlying SSH-2 session).
*
* There are several solutions:
*
* Simple: Execute several commands in one batch, e.g., something like Session.execCommand("echo Hello && echo again").
* Simple: The intended way: simply open a new session for each command - once you have opened a connection, you can ask for as many sessions as you want, they are only a "virtual" construct.
* Advanced: Don't use Session.execCommand(), but rather aquire a shell with Session.startShell().
*
* @param command
* @return
* @throws IOException
*/
public String execCommand(String command) throws IOException {
Session session = connection.openSession();
session.execCommand(command, StandardCharsets.UTF_8.toString());
InputStream streamGobbler = new StreamGobbler(session.getStdout());
String result = IOUtils.toString(streamGobbler, StandardCharsets.UTF_8);
session.waitForCondition(ChannelCondition.EXIT_SIGNAL, Long.MAX_VALUE);
if (session.getExitStatus().intValue() == 0) {
log.info("execCommand: {} success ", command);
} else {
log.error("execCommand : {} fail", command);
}
IOUtils.closeQuietly(streamGobbler);
session.close();
return result;
}
/**
* 远程传输单个文件
*
* @param localFile
* @param remoteTargetDirectory
* @throws IOException
*/
public void transferFile(String localFile, String remoteTargetDirectory) throws IOException {
File file = new File(localFile);
if (file.isDirectory()) {
throw new RuntimeException(localFile + " is not a file");
}
String fileName = file.getName();
execCommand("cd " + remoteTargetDirectory + ";rm " + fileName + "; touch " + fileName);
SCPClient sCPClient = connection.createSCPClient();
SCPOutputStream scpOutputStream = sCPClient.put(fileName, file.length(), remoteTargetDirectory, "7777");
String content = IOUtils.toString(new FileInputStream(file));
scpOutputStream.write(content.getBytes(StandardCharsets.UTF_8));
scpOutputStream.flush();
scpOutputStream.close();
}
/**
* 传输整个目录
*
* @param localFile
* @param remoteTargetDirectory
* @throws IOException
*/
public void transferDirectory(String localDirectory, String remoteTargetDirectory) throws IOException {
File dir = new File(localDirectory);
if (!dir.isDirectory()) {
throw new RuntimeException(localDirectory + " is not directory");
}
String[] files = dir.list();
for (String file : files) {
if (file.startsWith(".")) {
continue;
}
String fullName = localDirectory + "/" + file;
if (new File(fullName).isDirectory()) {
String rdir = remoteTargetDirectory + "/" + file;
execCommand("mkdir -p " + remoteTargetDirectory + "/" + file);
transferDirectory(fullName, rdir);
} else {
transferFile(fullName, remoteTargetDirectory);
}
}
}
public void close() {
connection.close();
}
public static void main(String[] args) throws IOException {
SSHAgent sshAgent = new SSHAgent();
sshAgent.initSession("127.0.0.1", "root", "xxx");
String execCommand = sshAgent.execCommand("pwd ; date");
System.out.println("pwd ; date:" + execCommand);
String execCommand2 = sshAgent.execCommand("who ");
System.out.println("who :" + execCommand2);
sshAgent.transferFile("/home/xx/Documents/a", "/home/xx");
sshAgent.transferDirectory("/home/xx/Documents", "/home/xx/book");
// 执行bash脚本
System.out.println(sshAgent.execCommand("cd /home/xx/book; ./test.sh"));
;
sshAgent.close();
}
}
运行结果就不贴出来了。
传输目录的时候,只是递归遍历文件传输。单个文件的传输也可以优化的,单个文件毕竟有大、小容量的。
而且远程文件目录还要执行系统命令去创建。
目录创建我们使用了mkdir -p ,这样,即使父母录没有,系统也会为我们自动创建。
版权声明:本文为博主原创文章,未经博主允许不得转载[http://blog.csdn.net/doctor_who2004]。
Ganymed SSH2 模拟类似FileZilla远程传输文件(基于SCP协议)
标签:ganymed ssh2 远程传输文件 ganymed ssh2 scp协议 ganymed ssh2 模拟类似fil
原文地址:http://blog.csdn.net/doctor_who2004/article/details/47322801