Ganymed SSH2 模拟类似FileZilla远程传输文件(基于SCP协议)

Ganymed SSH2 模拟类似FileZilla远程传输文件(基于SCP协议)

为了传输文件或者目录,我们使用 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]。

时间: 2024-11-17 14:56:05

Ganymed SSH2 模拟类似FileZilla远程传输文件(基于SCP协议)的相关文章

expect 远程传输文件

+++++++++++++++++++++++++++++++++++++ 标题:expect 远程传输文件 时间:2020年3月3日 +++++++++++++++++++++++++++++++++++++ #/usr/bin/env expect set  ip  192.168.100.100 set  user  root set  password  centos set  timeout  5 spawn scp -r /etc/hosts ${user}@${ip}:/tmp e

远程传输文件命令:scp

1.概述 scp(secure copy)是一个基于 SSH 协议在网络之间进行安全传输的命令,其格式为"scp [参数] 本地文件 远程帐户@远程 IP 地址:远程目录". 与第 2 章讲解的 cp 命令不同,cp 命令只能在本地硬盘中进行文件复制,而 scp 不 仅能够通过网络传送数据,而且所有的数据都将进行加密处理.例如,如果想把一些文件通过网络从一台主机传递到其他主机,这两台主机又恰巧是 Linux 系统,这时使用 scp 命令就可以轻松完成文件的传递了.scp 命令中可用的参

shell---scp远程传输文件不需要手动输入密码

1.通过sshpass让ssh记住密码实现ssh自动登陆 (1)安装sshpass sudo apt-get install sshpass 或者 下载sshpass-1.05.tar.gz shell>tar xvf sshpass-1.05.tar.gz shell>cd sshpass-1.05 shell>make && make install (2)测试 shell>/usr/local/bin/sshpass -p 密码 ssh [email prot

Ganymed SSH2 模拟putty远程交互式执行命令工具

接着上篇http://blog.csdn.net/doctor_who2004/article/details/47322105的介绍: 我们模拟下putty这类交互式的执行远程命令: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.nio.charset.StandardChar

花生棒配合树莓派使用SFTP远程传输文件

废话不多说,树莓派部署在内网,那么没有公网IP地址,要怎么样通过外网得以进行FTP文件传输呢?今天就告诉大家用花生壳家的花生棒端口映射结合树莓派来解决这一问题的方法. 花生壳官网:http://hsk.oray.com/ 具体的操作方法如下: 1.连通花生棒 2.登录花生棒 通过访问 http://www.oray.cn 进行花生棒端口映射的配置通过SN码登录:SN码在花生棒背面,初始化密码为:admin也可以通过帐号登录.如图: 3.配置花生棒 花生棒端口映射配置 点击内网映射-添加映射应用名

scp远程传输文件和ssh远程连接

ssh使用方法 如果从一台linux服务器通过ssh远程登录到另一台Linux机器, 这种情况通常会在多台服务器的时候用到. 如用root帐号连接一个IP为192.168.1.102的机器,输入:“ ssh 192.168.1.102 -l root ” 如果该服务器的ssh端口不是默认的22端口,是自定义的一个如1234,则可在命令后面加参数-p,  如:“ ssh 192.168.1.102 -l root -p 1234 ” scp使用方法 1.获取远程服务器上的文件 scp -P 222

第十一章练习 压缩和远程传输文件

<<<第十二单元练习>>> 在server主机中把/etc目录打包压缩到/mnt中,名字为etc.tar.gz tar  zcvf  /mnt/etc.tar.gz  /etc 2.复制server主机中的etc.tar.gz到desktop主机的/mnt中 scp /mnt/etc.tar.gz [email protected]:/root/Desktop 3.同步server主机中的/etc中的所有文件到desktop主机中/mnt中,包含链接文件 rsync -

命令远程传输文件

可以简单用scp 命令来实现 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff; min-height: 13.0px } span.s1

linux系统批量传输文件(SCP)

(1)首先,把要传输的主机ip保存到文件内 vi   ip 10.161.4.x 10.161.4.x 10.161.4.x (2)编写脚本 #!/usr/bin/ksh username=tomcat      #这里是连接远程主机的用户名,本例中连接的远程主机用户名都一样 #echo $username password='xxxxx'     #这里是密码 #echo $password homedir=">" ip_form='[email protected]'  #这