Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scp via java

What is the best method of performing an scp transfer via the Java programming language? It seems I may be able to perform this via JSSE, JSch or the bouncy castle java libraries. None of these solutions seem to have an easy answer.

like image 368
Lloyd Meinholz Avatar asked Oct 14 '08 00:10

Lloyd Meinholz


People also ask

What is scp in Java?

Whenever we call new String() in Java, it will create an object in the heap memory and String literals will go into String Constant Pool (SCP). For objects, JVM used SCP which is for efficient memory management in Java.

Why is scp in Java?

SCP (Secure Copy) allows the files in the local file system or a remote file system to be copied to the local files system or a remote file system. This uses SSH for data transfer and provides the same authentication and same level of security as SSH.

Is scp and SFTP the same?

The main difference between SCP and SFTP is that SCP is a protocol that allows transferring files securely from a local host to a remote host while SFTP is a protocol that allows file accessing, transferring, and managing over a reliable data stream which is faster than SCP.

What is JSch Java?

JSch is the Java implementation of SSH2 that allows us to connect to an SSH server and use port forwarding, X11 forwarding, and file transfer. Also, it is licensed under the BSD style license and provides us with an easy way to establish an SSH connection with Java.


7 Answers

I ended up using Jsch- it was pretty straightforward, and seemed to scale up pretty well (I was grabbing a few thousand files every few minutes).

like image 160
Tim Howland Avatar answered Oct 02 '22 20:10

Tim Howland


plug: sshj is the only sane choice! See these examples to get started: download, upload.

like image 41
shikhar Avatar answered Oct 02 '22 21:10

shikhar


Take a look here

That is the source code for Ants' SCP task. The code in the "execute" method is where the nuts and bolts of it are. This should give you a fair idea of what is required. It uses JSch i believe.

Alternatively you could also directly execute this Ant task from your java code.

like image 21
abarax Avatar answered Oct 02 '22 19:10

abarax


I wrapped Jsch with some utility methods to make it a bit friendlier and called it

Jscp

Available here: https://github.com/willwarren/jscp

SCP utility to tar a folder, zip it, and scp it somewhere, then unzip it.

Usage:

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

Also includes useful classes - Scp and Exec, and a TarAndGzip, which work in pretty much the same way.

like image 35
Will Avatar answered Oct 02 '22 20:10

Will


This is high-level solution, no need to reinvent. Quick and dirty!

1) First, go to http://ant.apache.org/bindownload.cgi and download latest Apache Ant binary. (nowadays, apache-ant-1.9.4-bin.zip).

2) Extract the downloaded file and find the JAR ant-jsch.jar ("apache-ant-1.9.4/lib/ant-jsch.jar"). Add this JAR in your project. Also ant-launcher.jar and ant.jar.

3) Go to Jcraft jsch SouceForge Project and download the jar. Nowadays, jsch-0.1.52.jar. Also Add this JAR in your project.

Now, can you easyly use into java code the Ant Classes Scp for copy files over network or SSHExec for commands in SSH servers.

4) Code Example 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();
like image 26
Fernando Santos Avatar answered Oct 02 '22 21:10

Fernando Santos


The openssh project lists several Java alternatives, Trilead SSH for Java seems to fit what you're asking for.

like image 24
Kyle Burton Avatar answered Oct 02 '22 20:10

Kyle Burton


Here is an example to upload a file using 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();
    }
}
like image 33
Eng.Fouad Avatar answered Oct 02 '22 21:10

Eng.Fouad