scp qua java


81

Phương pháp tốt nhất để thực hiện chuyển scp qua ngôn ngữ lập trình Java là gì? Có vẻ như tôi có thể thực hiện điều này thông qua JSSE, JSch hoặc các thư viện java lâu đài bouncy. Không có giải pháp nào trong số này dường như có câu trả lời dễ dàng.


2
bạn có thể chia nhỏ các vấn đề mà bạn gặp phải với các thư viện khác nhau, tại sao chúng không phù hợp với bạn?
Tim Howland

Câu trả lời:


59

Tôi đã kết thúc bằng cách sử dụng Jsch - nó khá đơn giản và dường như mở rộng quy mô khá tốt (tôi đang lấy một vài nghìn tệp mỗi vài phút).


1
jsch hóa ra là giải pháp thay thế tốt hơn, nhưng tài liệu thì quá tệ. Mẹo từ Abarax để xem xét nhiệm vụ truy quét kiến ​​rất hữu ích. Thực sự không rõ liệu dự án có còn hoạt động hay không. Cảm ơn vì tiền hỗ trợ.
Lloyd Meinholz 19/10/08

30
@LloydMeinholz: Tôi đã viết Javadocs cho thư viện này.
Paŭlo Ebermann

Paulo- công việc tuyệt vời! Chúng trông thực sự hữu ích.
Tim Howland

4
Tôi đang tìm kiếm trang này là rất nhiều thông tin: jcraft.com/jsch/examples
Daniel Kaplan

23

plug: sshj là sự lựa chọn lành mạnh duy nhất! Xem các ví dụ sau để bắt đầu: tải xuống , tải lên .


4
Tôi đã sử dụng sshj thay vì Jsch vì nó có giao diện đơn giản hơn nhiều.
Chris

1
Sử dụng chính trang web github hoặc tải về bưu điện
CrazyPyro

Giữa jsch và sshj, tôi đã chọn sshj vì API cấp cao hơn, đơn giản hơn. So sánh ví dụ tải lên từ câu trả lời với ví dụ tương đương cho jsch: jcraft.com/jsch/examples/ScpTo.java.html . Đây có thể là lý do tại sao nó được gọi là "sự lựa chọn lành mạnh duy nhất".
Bogdan Calmac

1
Thật là một sự lãng phí thời gian của tôi. Các ví dụ không hiển thị các đối số được sử dụng. Tài liệu tên người dùng từ xa khác nhau không tồn tại. Tránh gợi ý này mọi người.
Kieveli

17

Hãy xem ở đây

Đó là mã nguồn cho nhiệm vụ SCP của Người Kiến. Mã trong phương thức "thực thi" là nơi chứa các đai ốc và bu lông của nó. Điều này sẽ cung cấp cho bạn một ý tưởng hợp lý về những gì được yêu cầu. Nó sử dụng JSch mà tôi tin tưởng.

Ngoài ra, bạn cũng có thể thực hiện trực tiếp tác vụ Ant này từ mã java của mình.


7

Tôi đã bọc Jsch bằng một số phương thức tiện ích để làm cho nó thân thiện hơn một chút và gọi nó là

Jscp

Có sẵn tại đây: https://github.com/willwarren/jscp

SCP tiện ích để tar một thư mục, nén nó và quét nó vào đâu đó, sau đó giải nén nó.

Sử dụng:

// 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") 
           );

Cũng bao gồm các lớp hữu ích - Scp và Exec, và TarAndGzip, hoạt động theo cách khá giống nhau.


5

Đây là giải pháp cấp cao , không cần phải phát minh lại. Nhanh chóng và hèn hạ!

1) Đầu tiên, hãy truy cập http://ant.apache.org/bindownload.cgi và tải xuống tệp nhị phân Apache Ant mới nhất. (ngày nay, apache-ant-1.9.4-bin.zip).

2) Giải nén tệp đã tải xuống và tìm JAR ant-jsch.jar ("apache-ant-1.9.4 / lib / ant-jsch.jar"). Thêm JAR này vào dự án của bạn . Ngoài ra ant-launcher.jar và ant.jar.

3) Đi tới Dự án Jcraft jsch SouceForge và tải xuống bình. Ngày nay, jsch-0.1.52.jar . Cũng Thêm JAR này trong dự án của bạn .

Bây giờ, bạn có thể dễ dàng sử dụng vào mã java Ant Classes Scp để sao chép tệp qua mạng hoặc SSHExec cho các lệnh trong máy chủ SSH.

4) Ví dụ về mã 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();

tôi đang cố gắng này, nhưng đã nhận lỗi nếu bất kỳ giải pháp sau đó xin vui lòng comment ---> com.jcraft.jsch.JSchException: Session.connect: java.security.NoSuchAlgorithmException: Không có thuật toán DH
Karan

1
Nếu bạn cần một giải pháp nhanh chóng, điều này hoạt động như một phép thuật và phân bổ đơn giản hơn thì hãy sử dụng trực tiếp JSch, cảm ơn.
Haim Raman

Có thể đọc từ máy chủ từ xa với org.apache.tools.ant.taskdefs.optional.ssh.Scp không?
Minisha 27/09/18

3

Các dự án openssh danh sách nhiều lựa chọn thay thế Java, Trilead SSH cho Java vẻ phù hợp với những gì bạn đang xin.


Trilead có vẻ trưởng thành hơn nhiều so với Jsch, nhưng lại thiếu đi sự hỗ trợ của sftp và scp, đó là điều mà tôi đã theo đuổi. Hiện tại, sftp chỉ hỗ trợ nhận và đặt (tôi cũng cần ls và rm) và hỗ trợ scp được liệt kê là thử nghiệm.
Lloyd Meinholz 19/10/08

2

Tôi sử dụng API SFTP này có SCP gọi là Zehon, nó rất tuyệt, rất dễ sử dụng với rất nhiều mã mẫu. Đây là trang web http://www.zehon.com


2

Tôi đã xem xét rất nhiều giải pháp và không thích nhiều giải pháp trong số đó. Chủ yếu là vì bước khó chịu khi phải xác định các máy chủ đã biết của bạn. Điều đó và JSCH ở mức thấp đáng kinh ngạc so với lệnh scp.

Tôi đã tìm thấy một thư viện không yêu cầu điều này nhưng nó được đóng gói và sử dụng như một công cụ dòng lệnh. https://code.google.com/p/scp-java-client/

Tôi đã xem qua mã nguồn và phát hiện ra cách sử dụng nó mà không cần dòng lệnh. Đây là một ví dụ về tải lên:

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

Nhược điểm lớn nhất là nó không có trong repo maven (mà tôi có thể tìm thấy). Nhưng, sự dễ sử dụng là giá trị nó đối với tôi.


1

jsCH đã làm việc tuyệt vời cho tôi. Dưới đây là ví dụ về một phương pháp sẽ kết nối với máy chủ sftp và tải tệp xuống thư mục được chỉ định. Bạn nên tránh vô hiệu hóa tính năng Kiểm tra nghiêm ngặt. Mặc dù khó thiết lập hơn một chút, vì lý do bảo mật, việc chỉ định các máy chủ đã biết nên là tiêu chuẩn.

jsch.setKnownHosts ("C: \ Users \ test \ known_hosts"); đề nghị

JSch.setConfig ("Kiểm tra nghiêm ngặt", "không"); - không được khuyến khích

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

    }

1

Giống như một số ở đây, tôi đã viết một trình bao bọc xung quanh thư viện JSch.

Nó được gọi là way-secshell và nó được lưu trữ trên 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();

1

JSch là một thư viện tốt để làm việc cùng. Nó có một câu trả lời khá dễ dàng cho câu hỏi của bạn.

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

Bạn có thể tìm thấy mã hoàn chỉnh tại

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


1

Đây là một ví dụ để tải lên một tệp bằng 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();
    }
}


0

Tôi cần sao chép thư mục một cách đệ quy, sau khi thử các giải pháp khác nhau, cuối cùng kết thúc bằng ProcessBuilder + mong đợi / 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();
}

0

-: Tinh chỉnh câu trả lời của Fernando một chút, nếu bạn sử dụng Maven để quản lý sự phụ thuộc: -

pom.xml :

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

Thêm phụ thuộc này vào dự án của bạn. Phiên bản mới nhất có thể được tìm thấy ở đây .

Mã 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();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.