通过java实现scp

通过java实现scp,java,scp,bouncycastle,jsse,jsch,Java,Scp,Bouncycastle,Jsse,Jsch,通过Java编程语言执行scp传输的最佳方法是什么?似乎我可以通过JSSE、JSch或bouncy castle java库来执行此操作。这些解决方案似乎都没有一个简单的答案。列出了几种Java替代方案,似乎符合您的要求。看一看 这是Ants的SCP任务的源代码。“execute”方法中的代码是它的螺母和螺栓所在的位置。这会让你对所需要的东西有一个大致的了解。我相信它使用JSch 或者,您也可以直接从java代码中执行此Ant任务。我最终使用了-它非常简单,而且似乎扩展得非常好(我每隔几分钟就抓

通过Java编程语言执行scp传输的最佳方法是什么?似乎我可以通过JSSE、JSch或bouncy castle java库来执行此操作。这些解决方案似乎都没有一个简单的答案。

列出了几种Java替代方案,似乎符合您的要求。

看一看

这是Ants的SCP任务的源代码。“execute”方法中的代码是它的螺母和螺栓所在的位置。这会让你对所需要的东西有一个大致的了解。我相信它使用JSch


或者,您也可以直接从java代码中执行此Ant任务。

我最终使用了-它非常简单,而且似乎扩展得非常好(我每隔几分钟就抓取几千个文件)。

我使用了这个SFTP API,它有一个名为Zehon的SCP,非常好,很容易与许多示例代码一起使用。这里是网站插件:sshj是唯一明智的选择!请参阅以下示例开始:,。

我使用一些实用方法包装了Jsch,使其更友好,并调用了它

Jscp 可从以下网址获得:

SCP实用程序对文件夹进行焦油处理,将其压缩,并将其压缩到某个位置,然后将其解压缩

用法:

// create secure context
SecureContext context = new SecureContext("userName", "localhost");

// set optional security configurations.
context.setTrustAllHosts(true);
context.setPrivateKeyFile(new File("private/key"));

// Console requires JDK 1.7
// System.out.println("enter password:");
// context.setPassword(System.console().readPassword());

Jscp.exec(context, 
           "src/dir",
           "destination/path",
           // regex ignore list 
           Arrays.asList("logs/log[0-9]*.txt",
           "backups") 
           );

还包括有用的类——Scp和Exec,以及TarAndGzip,它们的工作方式几乎相同。

我编写了一个Scp服务器,它比其他服务器简单得多。我使用apachemina项目(apachesshd)来开发它。您可以在这里查看: 您还可以从
/jar
目录下载jar文件。
如何使用?看看:

JSch是一个很好的库。对你的问题有一个很简单的答案

JSch jsch=new JSch();
  Session session=jsch.getSession(user, host, 22);
  session.setPassword("password");


  Properties config = new Properties();
  config.put("StrictHostKeyChecking","no");
  session.setConfig(config);
  session.connect();

  boolean ptimestamp = true;

  // exec 'scp -t rfile' remotely
  String command="scp " + (ptimestamp ? "-p" :"") +" -t "+rfile;
  Channel channel=session.openChannel("exec");
  ((ChannelExec)channel).setCommand(command);

  // get I/O streams for remote scp
  OutputStream out=channel.getOutputStream();
  InputStream in=channel.getInputStream();

  channel.connect();

  if(checkAck(in)!=0){
    System.exit(0);
  }

  File _lfile = new File(lfile);

  if(ptimestamp){
    command="T "+(_lfile.lastModified()/1000)+" 0";
    // The access time should be sent here,
    // but it is not accessible with JavaAPI ;-<
    command+=(" "+(_lfile.lastModified()/1000)+" 0\n");
    out.write(command.getBytes()); out.flush();
    if(checkAck(in)!=0){
      System.exit(0);
    }
  }
JSch-JSch=new-JSch();
Session Session=jsch.getSession(用户,主机,22);
session.setPassword(“密码”);
属性配置=新属性();
配置放置(“检查”、“否”);
session.setConfig(config);
session.connect();
布尔ptimestamp=true;
//远程执行“scp-t文件”
String command=“scp”+(ptimestamp?”-p:“)+”-t“+rfile;
Channel=session.openChannel(“exec”);
((ChannelExec)channel).setCommand(command);
//获取远程scp的I/O流
OutputStream out=channel.getOutputStream();
InputStream in=channel.getInputStream();
channel.connect();
如果(检查确认(in)!=0){
系统出口(0);
}
文件_lfile=新文件(lfile);
如果(ptimestamp){
command=“T”+(\u lfile.lastModified()/1000)+“0”;
//访问时间应该发送到这里,
//但是JavaAPI无法访问它-<
命令+=(“”+(_lfile.lastModified()/1000)+“0\n”);
out.write(command.getBytes());out.flush();
如果(检查确认(in)!=0){
系统出口(0);
}
}
您可以在以下位置找到完整的代码:


我看过很多这样的解决方案,但不喜欢其中的很多。主要是因为必须识别已知主机这一恼人的步骤。与scp命令相比,JSCH的级别低得离谱

我发现了一个不需要这个的库,但它被捆绑起来并用作命令行工具

我浏览了源代码,发现了如何在没有命令行的情况下使用它。下面是一个上载示例:

    uk.co.marcoratto.scp.SCP scp = new uk.co.marcoratto.scp.SCP(new uk.co.marcoratto.scp.listeners.SCPListenerPrintStream());
    scp.setUsername("root");
    scp.setPassword("blah");
    scp.setTrust(true);
    scp.setFromUri(file.getAbsolutePath());
    scp.setToUri("root@host:/path/on/remote");
    scp.execute();

最大的缺点是它不是maven回购协议(我可以找到)。但是,它的易用性对我来说是值得的。

jsCH对我来说非常有用。下面是一个连接到sftp服务器并将文件下载到指定目录的方法示例。建议不要禁用密钥检查。尽管设置起来有点困难,但出于安全原因,指定已知主机应该是标准

jsch.setKnownHosts(“C:\Users\test\known_hosts”)推荐

JSch.setConfig(“StrictHostKeyChecking”、“no”)-不建议使用

import com.jcraft.jsch.*;
 public void downloadFtp(String userName, String password, String host, int port, String path) {


        Session session = null;
        Channel channel = null;
        try {
            JSch ssh = new JSch();
            JSch.setConfig("StrictHostKeyChecking", "no");
            session = ssh.getSession(userName, host, port);
            session.setPassword(password);
            session.connect();
            channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp sftp = (ChannelSftp) channel;
            sftp.get(path, "specify path to where you want the files to be output");
        } catch (JSchException e) {
            System.out.println(userName);
            e.printStackTrace();


        } catch (SftpException e) {
            System.out.println(userName);
            e.printStackTrace();
        } finally {
            if (channel != null) {
                channel.disconnect();
            }
            if (session != null) {
                session.disconnect();
            }
        }

    }

和这里的一些人一样,我最终在JSch库周围编写了一个包装器

它被称为way secshell,托管在GitHub上:

//scp myfile.txt localhost:/tmp
File File=新文件(“myfile.txt”);
Scp res=WaySSH.Scp()
.file(文件)
.toHost(“本地主机”)
.at(“/tmp”)
.send();

这是一个高级解决方案,无需再创新。又快又脏

1)首先,转到并下载最新的ApacheAnt二进制文件。(现在是apache-ant-1.9.4-bin.zip)

2)提取下载的文件并找到JARantjsch.JAR(“apache-ant-1.9.4/lib/antjsch.JAR”)将此JAR添加到项目中。还有ant-launcher.jar和ant.jar

3)转到并下载jar。如今。另外,将这个JAR添加到您的项目中

现在,您可以轻松地将Ant类Scp用于通过网络复制文件,或SSHExec用于SSH服务器中的命令,并将其用于java代码中

4)代码示例Scp:

// This make scp copy of 
// one local file to remote dir

org.apache.tools.ant.taskdefs.optional.ssh.Scp scp = new Scp();
int portSSH = 22;
String srvrSSH = "ssh.your.domain";
String userSSH = "anyuser"; 
String pswdSSH = new String ( jPasswordField1.getPassword() );
String localFile = "C:\\localfile.txt";
String remoteDir = "/uploads/";

scp.setPort( portSSH );
scp.setLocalFile( localFile );
scp.setTodir( userSSH + ":" + pswdSSH + "@" + srvrSSH + ":" + remoteDir );
scp.setProject( new Project() );
scp.setTrust( true );
scp.execute();

我需要递归地复制文件夹,在尝试不同的解决方案后,最终由ProcessBuilder+expect/spawn完成

scpFile("192.168.1.1", "root","password","/tmp/1","/tmp");

public void scpFile(String host, String username, String password, String src, String dest) throws Exception {

    String[] scpCmd = new String[]{"expect", "-c", String.format("spawn scp -r %s %s@%s:%s\n", src, username, host, dest)  +
            "expect \"?assword:\"\n" +
            String.format("send \"%s\\r\"\n", password) +
            "expect eof"};

    ProcessBuilder pb = new ProcessBuilder(scpCmd);
    System.out.println("Run shell command: " + Arrays.toString(scpCmd));
    Process process = pb.start();
    int errCode = process.waitFor();
    System.out.println("Echo command executed, any errors? " + (errCode == 0 ? "No" : "Yes"));
    System.out.println("Echo Output:\n" + output(process.getInputStream()));
    if(errCode != 0) throw new Exception();
}

以下是使用以下方法上载文件的示例:

ScpUploader.java

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.io.ByteArrayInputStream;
import java.util.Properties;

public final class ScpUploader
{
    public static ScpUploader newInstance()
    {
        return new ScpUploader();
    }

    private volatile Session session;
    private volatile ChannelSftp channel;

    private ScpUploader(){}

    public synchronized void connect(String host, int port, String username, String password) throws JSchException
    {
        JSch jsch = new JSch();

        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");

        session = jsch.getSession(username, host, port);
        session.setPassword(password);
        session.setConfig(config);
        session.setInputStream(System.in);
        session.connect();

        channel = (ChannelSftp) session.openChannel("sftp");
        channel.connect();
    }

    public synchronized void uploadFile(String directoryPath, String fileName, byte[] fileBytes, boolean overwrite) throws SftpException
    {
        if(session == null || channel == null)
        {
            System.err.println("No open session!");
            return;
        }

        // a workaround to check if the directory exists. Otherwise, create it
        channel.cd("/");
        String[] directories = directoryPath.split("/");
        for(String directory : directories)
        {
            if(directory.length() > 0)
            {
                try
                {
                    channel.cd(directory);
                }
                catch(SftpException e)
                {
                    // swallowed exception

                    System.out.println("The directory (" + directory + ") seems to be not exist. We will try to create it.");

                    try
                    {
                        channel.mkdir(directory);
                        channel.cd(directory);
                        System.out.println("The directory (" + directory + ") is created successfully!");
                    }
                    catch(SftpException e1)
                    {
                        System.err.println("The directory (" + directory + ") is failed to be created!");
                        e1.printStackTrace();
                        return;
                    }

                }
            }
        }

        channel.put(new ByteArrayInputStream(fileBytes), directoryPath + "/" + fileName, overwrite ? ChannelSftp.OVERWRITE : ChannelSftp.RESUME);
    }

    public synchronized void disconnect()
    {
        if(session == null || channel == null)
        {
            System.err.println("No open session!");
            return;
        }

        channel.exit();
        channel.disconnect();
        session.disconnect();

        channel = null;
        session = null;
    }
}
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public final class AppEntryPoint
{
    private static final String HOST = "192.168.1.1";
    private static final int PORT = 22;
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";

    public static void main(String[] args) throws IOException
    {
        ScpUploader scpUploader = ScpUploader.newInstance();

        try
        {
            scpUploader.connect(HOST, PORT, USERNAME, PASSWORD);
        }
        catch(JSchException e)
        {
            System.err.println("Failed to connect the server!");
            e.printStackTrace();
            return;
        }

        System.out.println("Successfully connected to the server!");

        byte[] fileBytes = Files.readAllBytes(Paths.get("C:/file.zip"));

        try
        {
            scpUploader.uploadFile("/test/files", "file.zip", fileBytes, true); // if overwrite == false, it won't throw exception if the file exists
            System.out.println("Successfully uploaded the file!");
        }
        catch(SftpException e)
        {
            System.err.println("Failed to upload the file!");
            e.printStackTrace();
        }

        scpUploader.disconnect();
    }
}
AppEntryPoint.java

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.io.ByteArrayInputStream;
import java.util.Properties;

public final class ScpUploader
{
    public static ScpUploader newInstance()
    {
        return new ScpUploader();
    }

    private volatile Session session;
    private volatile ChannelSftp channel;

    private ScpUploader(){}

    public synchronized void connect(String host, int port, String username, String password) throws JSchException
    {
        JSch jsch = new JSch();

        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");

        session = jsch.getSession(username, host, port);
        session.setPassword(password);
        session.setConfig(config);
        session.setInputStream(System.in);
        session.connect();

        channel = (ChannelSftp) session.openChannel("sftp");
        channel.connect();
    }

    public synchronized void uploadFile(String directoryPath, String fileName, byte[] fileBytes, boolean overwrite) throws SftpException
    {
        if(session == null || channel == null)
        {
            System.err.println("No open session!");
            return;
        }

        // a workaround to check if the directory exists. Otherwise, create it
        channel.cd("/");
        String[] directories = directoryPath.split("/");
        for(String directory : directories)
        {
            if(directory.length() > 0)
            {
                try
                {
                    channel.cd(directory);
                }
                catch(SftpException e)
                {
                    // swallowed exception

                    System.out.println("The directory (" + directory + ") seems to be not exist. We will try to create it.");

                    try
                    {
                        channel.mkdir(directory);
                        channel.cd(directory);
                        System.out.println("The directory (" + directory + ") is created successfully!");
                    }
                    catch(SftpException e1)
                    {
                        System.err.println("The directory (" + directory + ") is failed to be created!");
                        e1.printStackTrace();
                        return;
                    }

                }
            }
        }

        channel.put(new ByteArrayInputStream(fileBytes), directoryPath + "/" + fileName, overwrite ? ChannelSftp.OVERWRITE : ChannelSftp.RESUME);
    }

    public synchronized void disconnect()
    {
        if(session == null || channel == null)
        {
            System.err.println("No open session!");
            return;
        }

        channel.exit();
        channel.disconnect();
        session.disconnect();

        channel = null;
        session = null;
    }
}
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public final class AppEntryPoint
{
    private static final String HOST = "192.168.1.1";
    private static final int PORT = 22;
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";

    public static void main(String[] args) throws IOException
    {
        ScpUploader scpUploader = ScpUploader.newInstance();

        try
        {
            scpUploader.connect(HOST, PORT, USERNAME, PASSWORD);
        }
        catch(JSchException e)
        {
            System.err.println("Failed to connect the server!");
            e.printStackTrace();
            return;
        }

        System.out.println("Successfully connected to the server!");

        byte[] fileBytes = Files.readAllBytes(Paths.get("C:/file.zip"));

        try
        {
            scpUploader.uploadFile("/test/files", "file.zip", fileBytes, true); // if overwrite == false, it won't throw exception if the file exists
            System.out.println("Successfully uploaded the file!");
        }
        catch(SftpException e)
        {
            System.err.println("Failed to upload the file!");
            e.printStackTrace();
        }

        scpUploader.disconnect();
    }
}
-:如果您使用Maven进行依赖关系管理,请稍微细化Fernando的答案:-

pom.xml

<dependency>
  <groupId>org.apache.ant</groupId>
  <artifactId>ant-jsch</artifactId>
  <version>${ant-jsch.version}</version>
</dependency>
public void scpUpload(String source, String destination) {
    Scp scp = new Scp();
    scp.setPort(port);
    scp.setLocalFile(source);
    scp.setTodir(username + ":" + password + "@" + host + ":" + destination);
    scp.setProject(new Project());
    scp.setTrust(true);
    scp.execute();
}

你能分析一下各种库的问题吗?为什么它们不适合你?jsch被证明是更好的选择,但是文档很糟糕。Abarax关于蚂蚁scp任务的提示非常有用。现在还不清楚这个项目是否仍然很活跃。谢谢你的提示。@LloydMeinholz:我是为这个图书馆写的。保罗-干得好!他们看起来真的很有帮助。我发现这个页面信息非常丰富:Trilead看起来比Jsch成熟得多,但缺少sftp和scp支持,这正是我想要的。目前,sftp只支持get和put(我也需要ls和rm),scp支持被列为经验支持