scp через java


81

Який найкращий спосіб виконувати передачу scp за допомогою мови програмування Java? Здається, я зможу виконати це за допомогою JSSE, JSch або жвавих замкових Java-бібліотек. Здається, жодне з цих рішень не має простої відповіді.


2
чи можете ви розбити проблеми, що виникають у вас із різними бібліотеками, чому вони не працюють у вас?
Тім Хауленд,

Відповіді:


59

У підсумку я використав Jsch - це було досить просто і, здавалося, досить добре масштабувалось (я захоплював кілька тисяч файлів кожні кілька хвилин).


1
jsch виявився кращою альтернативою, але документація жахлива. Порада від Abarax, щоб подивитися на завдання мурахи scp, була дуже корисною. Насправді незрозуміло, чи проект все ще є дуже активним. Дякую за підказку.
Ллойд Майнхольц,

30
@LloydMeinholz: Я написав Javadocs для цієї бібліотеки.
Paŭlo Ebermann

Пауло - чудова робота! Вони виглядають по-справжньому корисними.
Tim Howland

4
Я вважаю цю сторінку дуже інформативною: jcraft.com/jsch/examples
Даніель Каплан

23

plug: sshj - єдиний розумний вибір! Для початку перегляньте ці приклади: завантажте , завантажте .


4
Я перейшов з sshj до Jsch, оскільки він мав набагато простіший інтерфейс.
Кріс,

1
Використовуйте головний сайт github або завантажте ZIP
CrazyPyro

Між jsch і sshj я пішов на sshj через простіший API вищого рівня. Порівняйте приклад завантаження з відповіді з еквівалентним прикладом для jsch: jcraft.com/jsch/examples/ScpTo.java.html . Ось чому його називали "єдиним розумним вибором".
Богдан Калмак

1
Яка трата мого часу. У прикладах не відображаються використані аргументи. Відмінна документація щодо віддаленого імені користувача не існує. Уникайте цієї пропозиції люди.
Kieveli

17

Поглянь тут

Це вихідний код для завдання мурахи SCP. Код у методі "виконати" - це місце, де його гайки та болти. Це має дати вам чітке уявлення про те, що потрібно. Я використовую JSch, я вважаю.

Ви також можете безпосередньо виконати це завдання Ant з вашого коду Java.


7

Я обгорнув Jsch деякими корисними методами, щоб зробити його дещо зручнішим, і назвав його

Jscp

Доступно тут: https://github.com/willwarren/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, які працюють приблизно однаково.


5

Це рішення високого рівня , не потрібно винаходити. Швидко і брудно!

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 і завантажте банку. У наш час jsch-0.1.52.jar . Також додайте цей JAR у свій проект .

Тепер ви можете легко використовувати в Java-коді Ant Classes Scp для копіювання файлів через мережу або SSHExec для команд на серверах SSH.

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 недоступний
Каран

1
Якщо вам потрібне швидке рішення, це працює як магія і набагато простіше, ніж безпосередньо за допомогою JSch, дякую.
Хаїм Раман,

Чи можна читати з віддаленого сервера за допомогою org.apache.tools.ant.taskdefs.optional.ssh.Scp?
Мініша

3

У проекті openssh перелічено кілька альтернативних варіантів Java, Trilead SSH для Java, здається, відповідає тому, про що ви просите.


Trilead здається набагато зрілішим за Jsch, але бракував підтримки sftp та scp, саме цього я й шукав. В даний час sftp підтримує лише get and put (мені також потрібні ls і rm), а підтримка scp була перелічена як експериментальна.
Ллойд Майнхольц,

2

Я використовую цей SFTP API, який має SCP під назвою Zehon, він чудовий, настільки простий у використанні з великою кількістю зразків коду. Ось сайт http://www.zehon.com


2

Я розглянув багато цих рішень і багато з них мені не сподобались. Здебільшого тому, що дратує крок того, що потрібно ідентифікувати своїх відомих господарів. Це і JSCH знаходиться на смішно низькому рівні щодо команди scp.

Я знайшов бібліотеку, яка цього не вимагає, але вона в комплекті і використовується як інструмент командного рядка. 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-репо (яке я міг знайти). Але простота використання мені того варта.


1

jsCH чудово для мене спрацював. Нижче наведено приклад методу, який буде підключатися до сервера sftp і завантажувати файли до вказаного каталогу. Рекомендуємо триматися подалі від вимкнення StrictHostKeyChecking. Хоча трохи складніше налаштувати, з міркувань безпеки вказівка ​​відомих хостів має бути нормою.

jsch.setKnownHosts ("C: \ Users \ test \ known_hosts"); рекомендується

JSch.setConfig ("StrictHostKeyChecking", "ні"); - не рекомендовано

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

Як і деякі тут, я закінчив писати обгортку навколо бібліотеки 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();

1

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


1

Ось приклад завантаження файлу за допомогою 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();
    }
}

1

-: Трохи уточнивши відповідь Фернандо, якщо ви використовуєте Maven для управління залежностями: -

pom.xml :

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

Додайте цю залежність у свій проект. Останню версію можна знайти тут .

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


0

Мені потрібно скопіювати папку рекурсивно, після випробування різних рішень, нарешті, в кінцевому підсумку ProcessBuilder + очікування / поява

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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.