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.

Lloyd Meinholz
quelle
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 ).

Tim Howland
quelle
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
4
Ich finde
Daniel Kaplan
23

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

Shikhar
quelle
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.

Abarax
quelle
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.

Wille
quelle
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();
Fernando Santos
quelle
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
3

Das openssh-Projekt listet mehrere Java-Alternativen auf. Trilead SSH für Java scheint genau zu Ihren Anforderungen zu passen.

Kyle Burton
quelle
Trilead scheint viel reifer zu sein als Jsch, aber es fehlte an Unterstützung für SFTP und SCP, was ich suchte. Derzeit unterstützt sftp nur get and put (ich brauche auch ls und rm) und scp support wurde als experimentell aufgeführt.
Lloyd Meinholz
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


quelle
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.

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

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

quelle
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

faisalbhagat
quelle
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();
    }
}
Eng.Fouad
quelle
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();
}
Burt
quelle
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();
}
Saikat
quelle