자바를 통한 scp


81

Java 프로그래밍 언어를 통해 scp 전송을 수행하는 가장 좋은 방법은 무엇입니까? JSSE, JSch 또는 탄력성 자바 라이브러리를 통해이 작업을 수행 할 수있을 것 같습니다. 이 솔루션들 중 어느 것도 쉬운 답이없는 것 같습니다.


2
다양한 라이브러리에서 발생하는 문제를 분석 할 수 있습니까? 왜 그들이 당신을 위해 작동하지 않습니까?
Tim Howland

답변:


59

결국 Jsch 를 사용 하게되었습니다. 매우 간단하고 확장이 잘되는 것 같았습니다 (몇 분마다 수천 개의 파일 을 가져 왔습니다 ).


1
jsch가 더 나은 대안으로 판명되었지만 문서는 끔찍합니다. 개미 scp 작업을 살펴 ​​보는 Abarax의 팁은 매우 도움이되었습니다. 프로젝트가 여전히 활발한 지 확실하지 않습니다. 팁 고마워.
Lloyd Meinholz

30
@LloydMeinholz : 이 라이브러리에 대한 Javadocs 를 작성했습니다 .
Paŭlo Ebermann 2011

파울로-훌륭합니다! 정말 도움이됩니다.
Tim Howland 2011

4
이 페이지가 매우 유익하다고 생각합니다 : jcraft.com/jsch/examples
Daniel Kaplan

23

플러그 : sshj는 유일한 건전한 선택입니다! 시작하려면 다음 예제를 참조하십시오. 다운로드 , 업로드 .


4
훨씬 간단한 인터페이스를 가지고 있었기 때문에 Jsch보다 sshj를 사용했습니다.
Chris


jsch와 sshj 사이에서 더 간단하고 높은 수준의 API 때문에 sshj를 사용했습니다. 답변의 업로드 예제를 jsch에 해당하는 예제 인 jcraft.com/jsch/examples/ScpTo.java.html 과 비교하십시오 . 이것이 "유일한 건전한 선택"이라고 불리는 이유 일 수 있습니다.
Bogdan Calmac

1
내 시간 낭비입니다. 예제는 사용 된 인수를 표시하지 않습니다. 다른 원격 사용자 이름 문서가 존재하지 않습니다. 이 제안 사람들을 피하십시오.
Kieveli

17

여기

이것이 Ants의 SCP 작업의 소스 코드입니다. "execute"메소드의 코드는 그것의 너트와 볼트가있는 곳입니다. 이것은 당신에게 무엇이 필요한지에 대한 공정한 아이디어를 줄 것입니다. 그것은 내가 믿는 JSch를 사용합니다.

또는 Java 코드에서이 Ant 태스크를 직접 실행할 수도 있습니다.


7

Jsch를 좀 더 친숙하게 만들기 위해 몇 가지 유틸리티 메서드로 래핑하고 호출했습니다.

JSCP

여기에서 사용 가능 : https://github.com/willwarren/jscp

폴더를 tar로 압축하고 어딘가에 scp 한 다음 압축을 푸는 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 프로젝트로 이동 하여 항아리를 다운로드하십시오. 요즘은 jsch-0.1.52.jar 입니다. 또한 이 JAR을 프로젝트에 추가하십시오 .

이제 네트워크를 통한 파일 복사 용 Ant Classes Scp 또는 SSH 서버의 명령 용 SSHExec 을 Java 코드로 쉽게 사용할 수 있습니다 .

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 : Algorithm DH not available
Karan

1
빠른 솔루션이 필요한 경우 마술처럼 작동하며 JSch를 직접 사용하는 것보다 더 간단합니다.
Haim Raman

org.apache.tools.ant.taskdefs.optional.ssh.Scp를 사용하여 원격 서버에서 읽을 수 있습니까?
Minisha


2

저는 Zehon이라는 SCP가있는이 SFTP API를 사용합니다. 아주 훌륭하고 많은 샘플 코드와 함께 사용하기 쉽습니다. 다음은 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 repo에 없다는 것입니다. 그러나 사용 편의성은 그만한 가치가 있습니다.


1

jsCH는 나를 위해 잘 작동했습니다. 다음은 sftp 서버에 연결하고 지정된 디렉토리에 파일을 다운로드하는 방법의 예입니다. StrictHostKeyChecking을 비활성화하지 않는 것이 좋습니다. 설정하기가 조금 더 어렵지만 보안상의 이유로 알려진 호스트를 지정하는 것이 일반적이어야합니다.

jsch.setKnownHosts ( "C : \ Users \ test \ known_hosts"); 추천

JSch.setConfig ( "StrictHostKeyChecking", "no"); -권장하지 않음

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


0

다른 솔루션을 시도한 후 마지막으로 ProcessBuilder + expect / 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

-: 의존성 관리를 위해 Maven을 사용한다면 Fernando의 대답을 조금 수정하십시오 :-

pom.xml :

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

프로젝트에이 종속성을 추가하십시오. 최신 버전은 여기 에서 찾을 수 있습니다 .

자바 코드 :

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();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.