scp über Java


81

Was ist die beste Methode, um eine scp-Übertragung über die Programmiersprache Java durchzuführen? Es scheint, dass ich dies möglicherweise über JSSE, JSch oder die Java-Bibliotheken der Hüpfburg durchführen kann. Keine dieser Lösungen scheint eine einfache Antwort zu haben.


2
Können Sie die Probleme, die Sie mit den verschiedenen Bibliotheken haben, aufschlüsseln, warum sie bei Ihnen nicht funktionieren?
Tim Howland

Antworten:


59

Am Ende habe ich Jsch verwendet - es war ziemlich einfach und schien ziemlich gut zu skalieren (ich habe alle paar Minuten ein paar tausend Dateien abgerufen ).


1
jsch erwies sich als die bessere Alternative, aber die Dokumentation ist schrecklich. Der Tipp von Abarax, sich die Ameisen-SCP-Aufgabe anzusehen, war sehr hilfreich. Es ist wirklich nicht klar, ob das Projekt noch sehr aktiv ist. Danke für den Tipp.
Lloyd Meinholz

30
@LloydMeinholz: Ich habe Javadocs für diese Bibliothek geschrieben.
Paŭlo Ebermann

Paulo - tolle Arbeit! Sie sehen sehr hilfreich aus.
Tim Howland


23

plug: sshj ist die einzig vernünftige Wahl! Sehen Sie sich diese Beispiele an, um loszulegen: Herunterladen , Hochladen .


4
Ich ging mit sshj über Jsch, da es eine viel einfachere Oberfläche hatte.
Chris

1
Verwenden Sie die Haupt- Github-Site oder laden Sie die ZIP
CrazyPyro

Zwischen jsch und sshj habe ich mich wegen der einfacheren API auf höherer Ebene für sshj entschieden. Vergleichen Sie das Upload-Beispiel aus der Antwort mit dem entsprechenden Beispiel für jsch: jcraft.com/jsch/examples/ScpTo.java.html . Dies könnte der Grund sein, warum es "die einzig vernünftige Wahl" genannt wurde.
Bogdan Calmac

1
Was für eine Zeitverschwendung. Beispiele zeigen keine verwendeten Argumente. Eine abweichende Dokumentation zum Remote-Benutzernamen ist nicht vorhanden. Vermeiden Sie diesen Vorschlag Menschen.
Kieveli

17

Schauen Sie hier

Dies ist der Quellcode für die SCP-Aufgabe von Ants. Der Code in der "execute" -Methode befindet sich dort, wo sich die Schrauben und Muttern befinden. Dies sollte Ihnen eine gute Vorstellung davon geben, was erforderlich ist. Es verwendet JSch, glaube ich.

Alternativ können Sie diese Ant-Aufgabe auch direkt über Ihren Java-Code ausführen.


7

Ich habe Jsch mit einigen Dienstprogrammmethoden umwickelt, um es ein bisschen freundlicher zu machen, und es aufgerufen

Jscp

Verfügbar hier: https://github.com/willwarren/jscp

SCP-Dienstprogramm zum Tarieren eines Ordners, zum Komprimieren und Scannen irgendwo, dann zum Entpacken.

Verwendung:

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

Enthält auch nützliche Klassen - Scp und Exec sowie ein TarAndGzip, die auf die gleiche Weise funktionieren.


5

Dies ist eine Lösung auf hoher Ebene , die nicht neu erfunden werden muss. Schnell und dreckig!

1) Gehen Sie zunächst zu http://ant.apache.org/bindownload.cgi und laden Sie die neueste Apache Ant-Binärdatei herunter. (heutzutage apache-ant-1.9.4-bin.zip).

2) Extrahieren Sie die heruntergeladene Datei und suchen Sie die JAR ant-jsch.jar ("apache-ant-1.9.4 / lib / ant-jsch.jar"). Fügen Sie diese JAR in Ihr Projekt ein . Auch ant-launcher.jar und ant.jar.

3) Gehen Sie zu Jcraft jsch SouceForge Project und laden Sie das Glas herunter. Heutzutage jsch-0.1.52.jar . Auch Fügen Sie diese JAR in Ihrem Projekt .

Jetzt können Sie die Ant Classes Scp zum Kopieren von Dateien über das Netzwerk oder SSHExec für Befehle in SSH-Servern einfach in Java-Code verwenden .

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

Ich versuche dies, habe aber eine Fehlermeldung erhalten, wenn eine Lösung vorliegt. Bitte kommentieren Sie ---> com.jcraft.jsch.JSchException: Session.connect: java.security.NoSuchAlgorithmException: Algorithmus DH nicht verfügbar
Karan

1
Wenn Sie eine schnelle Lösung benötigen, funktioniert dies wie Magie und ist viel einfacher als die direkte Verwendung von JSch, danke.
Haim Raman

Kann mit org.apache.tools.ant.taskdefs.optional.ssh.Scp von einem Remote-Server gelesen werden?
Minisha


2

Ich verwende diese SFTP-API mit SCP namens Zehon. Sie ist großartig und mit viel Beispielcode einfach zu verwenden. Hier ist die Website http://www.zehon.com


2

Ich habe mir viele dieser Lösungen angesehen und viele davon nicht gemocht. Meistens, weil es ärgerlich ist, Ihre bekannten Hosts identifizieren zu müssen. Das und JSCH sind im Vergleich zum Befehl scp auf einem lächerlich niedrigen Niveau.

Ich habe eine Bibliothek gefunden, die dies nicht benötigt, die jedoch gebündelt und als Befehlszeilenprogramm verwendet wird. https://code.google.com/p/scp-java-client/

Ich habe den Quellcode durchgesehen und herausgefunden, wie man ihn ohne die Befehlszeile verwendet. Hier ist ein Beispiel für das Hochladen:

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

Der größte Nachteil ist, dass es nicht in einem Maven Repo ist (das ich finden konnte). Aber die Benutzerfreundlichkeit lohnt sich für mich.


1

jsCH hat bei mir super funktioniert. Unten finden Sie ein Beispiel für eine Methode, mit der eine Verbindung zum SFTP-Server hergestellt und Dateien in das angegebene Verzeichnis heruntergeladen werden. Es wird empfohlen, StrictHostKeyChecking nicht zu deaktivieren. Obwohl die Einrichtung etwas schwieriger ist, sollte aus Sicherheitsgründen die Angabe der bekannten Hosts die Norm sein.

jsch.setKnownHosts ("C: \ Benutzer \ Test \ bekannte_Hosts"); empfohlen

JSch.setConfig ("StrictHostKeyChecking", "no"); - nicht empfohlen

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

Wie einige hier habe ich am Ende einen Wrapper um die JSch-Bibliothek geschrieben.

Es heißt way-secshell und wird auf GitHub gehostet:

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 ist eine schöne Bibliothek zum Arbeiten. Es hat eine ziemlich einfache Antwort auf Ihre Frage.

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

Den vollständigen Code finden Sie unter

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


1

Hier ist ein Beispiel zum Hochladen einer Datei mit 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

Ich muss den Ordner rekursiv kopieren, nachdem ich verschiedene Lösungen ausprobiert habe, um schließlich von ProcessBuilder + Expect / Spawn zu erhalten

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

-: Fernandos Antwort ein wenig verfeinern, wenn Sie Maven für das Abhängigkeitsmanagement verwenden: -

pom.xml :

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

Fügen Sie diese Abhängigkeit in Ihr Projekt ein. Die neueste Version finden Sie hier .

Java-Code :

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();
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.