【问题标题】:scp via javascp 通过 java
【发布时间】:2010-09-17 00:14:50
【问题描述】:

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

【问题讨论】:

  • 您能分解一下您在使用各种库时遇到的问题吗,为什么它们不适合您?

标签: java scp bouncycastle jsse jsch


【解决方案1】:

openssh project 列出了几个 Java 替代方案,Trilead SSH for Java 似乎符合您的要求。

【讨论】:

  • Trilead 似乎比 Jsch 成熟得多,但缺乏对 sftp 和 scp 的支持,这正是我所追求的。目前,sftp 只支持 get 和 put(我也需要 ls 和 rm),并且 scp 支持被列为体验。
【解决方案2】:

看看 here

这是 Ants 的 SCP 任务的源代码。 “执行”方法中的代码是它的具体细节。这应该让您对所需的内容有一个公平的了解。我相信它使用 JSch。

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

【讨论】:

    【解决方案3】:

    我最终使用了Jsch——它非常简单,而且似乎可以很好地扩展(我每隔几分钟就会抓取几千个文件)。

    【讨论】:

    • jsch 原来是更好的选择,但文档很糟糕。来自 Abarax 的关于查看 ants scp 任务的提示非常有帮助。目前还不清楚该项目是否仍然非常活跃。感谢您的提示。
    • @LloydMeinholz:我为这个库写了Javadocs
    • 保罗-干得好!他们看起来真的很有帮助。
    • 我发现这个页面信息量很大:jcraft.com/jsch/examples
    【解决方案4】:

    我使用这个 SFTP API,它有一个叫做 Zehon 的 SCP,它很棒,很容易使用,有很多示例代码。这里是网站http://www.zehon.com

    【讨论】:

      【解决方案5】:

      plug:sshj 是唯一明智的选择!请参阅以下示例以开始使用:downloadupload

      【讨论】:

      • 我选择了 sshj 而不是 Jsch,因为它的界面要简单得多。
      • 在 jsch 和 sshj 之间,我选择了 sshj,因为它更简单、更高级别的 API。将答案中的上传示例与 jsch 的等效示例进行比较:jcraft.com/jsch/examples/ScpTo.java.html。这可能就是为什么它被称为“唯一明智的选择”。
      • 真是浪费我的时间。示例不显示使用的参数。不存在不同的远程用户名文档。避免这个建议的人。
      【解决方案6】:

      我用一些实用方法包装了 Jsch,让它更友好一些,并称之为

      Jscp

      可在此处获取:https://github.com/willwarren/jscp

      SCP 实用程序 tar 一个文件夹,压缩它,然后将它 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,它们的工作方式几乎相同。

      【讨论】:

        【解决方案7】:

        我写了一个 scp 服务器,它比其他的要容易得多。我使用 Apache MINA 项目(Apache SSHD)来开发它。你可以看这里:https://github.com/boomz/JSCP 您也可以从/jar 目录下载jar 文件。 如何使用?看一看:https://github.com/boomz/JSCP/blob/master/src/Main.java

        【讨论】:

          【解决方案8】:

          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);
              }
            }
          

          你可以在

          找到完整的代码

          http://faisalbhagat.blogspot.com/2013/09/java-uploading-file-remotely-via-scp.html

          【讨论】:

            【解决方案9】:

            我查看了很多这样的解决方案,但其中很多都不喜欢。主要是因为必须识别已知主机的烦人步骤。相对于 scp 命令,这和 JSCH 处于可笑的低水平。

            我找到了一个不需要此功能的库,但它已捆绑并用作命令行工具。 https://code.google.com/p/scp-java-client/

            我查看了源代码并发现了如何在没有命令行的情况下使用它。以下是上传示例:

                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 repo 中(我可以找到)。但是,易用性对我来说是值得的。

            【讨论】:

              【解决方案10】:

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

              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();
                          }
                      }
              
                  }
              

              【讨论】:

                【解决方案11】:

                像这里的一些人一样,我最终为 JSch 库编写了一个包装器。

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

                https://github.com/objectos/way-secshell

                // scp myfile.txt localhost:/tmp
                File file = new File("myfile.txt");
                Scp res = WaySSH.scp()
                  .file(file)
                  .toHost("localhost")
                  .at("/tmp")
                  .send();
                

                【讨论】:

                  【解决方案12】:

                  这是高级解决方案,无需重新发明。又快又脏!

                  1) 首先,转到http://ant.apache.org/bindownload.cgi 并下载最新的Apache Ant 二进制文件。 (现在,apache-ant-1.9.4-bin.zip)。

                  2) 解压下载的文件,找到JAR ant-jsch.jar ("apache-ant-1.9.4/lib/ant-jsch.jar" )。 将此 JAR 添加到您的项目中。还有 ant-launcher.jar 和 ant.jar。

                  3) 转到Jcraft jsch SouceForge Project 并下载jar。如今,jsch-0.1.52.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();
                  

                  【讨论】:

                  • 我正在尝试这个,但如果有任何解决方案出现错误,请发表评论---> com.jcraft.jsch.JSchException: Session.connect: java.security.NoSuchAlgorithmException: 算法 DH 不可用
                  • 如果您需要一个快速的解决方案,这就像魔术一样,并且比直接使用 JSch 更简单,谢谢。
                  • 可以通过 org.apache.tools.ant.taskdefs.optional.ssh.Scp 从远程服务器读取?
                  【解决方案13】:

                  我需要递归复制文件夹,在尝试了不同的解决方案后,最终以 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();
                  }
                  

                  【讨论】:

                    【解决方案14】:

                    以下是使用JSch 上传文件的示例:

                    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;
                        }
                    }
                    

                    AppEntryPoint.java:

                    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();
                        }
                    }
                    

                    【讨论】:

                      【解决方案15】:

                      -:如果您使用 Maven 进行依赖管理,请稍微完善一下费尔南多的答案:-

                      pom.xml

                      <dependency>
                        <groupId>org.apache.ant</groupId>
                        <artifactId>ant-jsch</artifactId>
                        <version>${ant-jsch.version}</version>
                      </dependency>
                      

                      在您的项目中添加此依赖项。最新版本可以在here找到。

                      Java 代码

                      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();
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 2014-09-03
                        • 2018-12-09
                        • 2017-04-12
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-02-17
                        • 2011-02-19
                        • 1970-01-01
                        • 2011-11-17
                        相关资源
                        最近更新 更多