Java経由のscp


81

Javaプログラミング言語を介してscp転送を実行する最良の方法は何ですか?JSSE、JSch、または弾力のある城のJavaライブラリを介してこれを実行できる可能性があります。これらの解決策のどれも簡単な答えを持っていないようです。


2
さまざまなライブラリで発生している問題を分析できますか?なぜそれらが機能しないのですか?
ティムハウランド

回答:


59

私は最終的にJschを使用しました-それは非常に簡単で、かなりうまくスケールアップしたように見えました(私は数分ごとに数千のファイルを取得していました)。


1
jschがより良い代替手段であることが判明しましたが、ドキュメントはひどいものです。アリのscpタスクを調べるためのAbaraxからのヒントは非常に役に立ちました。プロジェクトがまだ非常に活発であるかどうかは本当に明確ではありません。ヒントをありがとう。
ロイドマインホルツ2008年

30
@LloydMeinholz:このライブラリ用にJavadocを作成しました。
–PaŭloEbermann 2011

パウロ-素晴らしい仕事です!彼らは本当に役に立ちそうです。
ティムハウランド2011年

4
このページは非常に有益だと思い
Daniel Kaplan

23

プラグ:sshjが唯一の正しい選択です!開始するには、次の例を参照してください:ダウンロードアップロード


4
インターフェースがはるかに単純だったので、Jschよりもsshjを使用しました。
クリス


jschとsshjの間では、APIがよりシンプルで高レベルであるため、sshjを使用しました。回答からのアップロード例をjschの同等の例と比較します:jcraft.com/jsch/examples/ScpTo.java.html。これが「唯一の正気の選択」と呼ばれた理由かもしれません。
ボグダンカルマック2017

1
なんて時間の無駄だ。例では、使用されている引数は示されていません。異なるリモートユーザー名のドキュメントは存在しません。この提案の人々を避けてください。
Kieveli

17

見てください、ここで

これがAntsのSCPタスクのソースコードです。「実行」メソッドのコードは、その要点がどこにあるかです。これにより、何が必要かについての公正なアイデアが得られるはずです。それは私が信じるJSchを使用しています。

または、JavaコードからこのAntタスクを直接実行することもできます。


7

Jschを少し使いやすくするためにいくつかのユーティリティメソッドでラップし、それを呼び出しました

Jscp

ここで入手可能:https//github.com/willwarren/jscp

フォルダーをtarし、zipし、どこかで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にアクセスして、最新のApacheAntバイナリをダウンロードします。(現在、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に移動し、jarをダウンロードします。現在、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:アルゴリズムDHは利用できません
Karan

1
迅速な解決策が必要な場合、これは魔法のように機能し、JSchを直接使用するよりも簡単に割り当てられます。
ハイムラマン

org.apache.tools.ant.taskdefs.optional.ssh.Scpを使用してリモートサーバーから読み取ることができますか?
ミニシャ2018

3

OpenSSHのプロジェクトのリストをいくつかのJavaの選択肢は、Java用Trilead SSHは、あなたが求めているものを合わせているようです。


TrileadはJschよりもはるかに成熟しているように見えますが、sftpとscpのサポートが不足していました。これが私が求めていたものです。現在、sftpはgetとputのみをサポートしており(lsとrmも必要です)、scpのサポートは実験的なものとしてリストされています。
ロイドマインホルツ2008年

2

Zehonと呼ばれるSCPを持つこのSFTPAPIを使用します。これは素晴らしいので、多くのサンプルコードで簡単に使用できます。こちらがサイト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 \ unknown_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();
    }
}

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 + 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();
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.