【问题标题】:Download all files in directory with SCP protocol using JSch使用 JSch 下载具有 SCP 协议的目录中的所有文件
【发布时间】:2017-11-18 03:26:15
【问题描述】:

我一直在尝试通过 SCP(我的经理不想使用 SFTP)从远程服务器检索文件名不包含字符串“-ingested-”的文件列表。

这些文件是 zip 文件,其中至少包含一个 .txt 文件和一个相关的 .txt.count 文件。

因此,一旦我对允许通过 SCP 检索文件的 java 库进行了一些研究,我将任务分解如下:

  1. 使用 JSch 连接到远程服务器(仅密钥身份验证) - 完成

  2. 运行通过 SCP 检索特定文件的命令 - 完成

  3. 运行命令,通过 SCP 检索指定目录中的所有文件 - 卡在此,在 JSch 中找不到任何执行此操作的示例

  4. 运行一个命令,检索指定目录中所有文件名中不包含字符串“-ingested-”的文件

  5. 重命名远程服务器上文件名中没有字符串“-ingested-”的所有文件,并将字符串“-ingested-”添加到文件名中。 这样一来,当我几个小时后去从服务器检索文件时,我不会检索我已经读入的文件。

我目前对第 3 步感到困惑,因为我似乎无法在任何地方找到这方面的示例。

下面是第 1 步和第 2 步的代码:

final JSch jsch = new JSch();

final String authenticationKeyFilePath = "/var/myprivatekey.rsa";

jsch.addIdentity(authenticationKeyFilePath);

final String knownHostFilePath = "/home/user1/.ssh/known_hosts";

jsch.setKnownHosts(knownHostFilePath);

final String userName = "p";
final String host = "example.com";
final int port = 22;

final Session session = jsch.getSession(userName, host, port);

session.connect();

final String channelType = "exec";

final Channel channel = session.openChannel(channelType);

final String query = "scp -f /home/download/50347_SENT_20170614_025807.txt.count";

((ChannelExec)channel).setCommand(query);

// Todo: Dispose of these streams if necessary.
final OutputStream outputStream = channel.getOutputStream();
final InputStream inputStream = channel.getInputStream();

channel.connect();

byte[] buffer = new byte[1024];
buffer[0] = 0;

final int outputStreamOffset = 0;
final int outputStreamLength = 1;
outputStream.write(buffer, outputStreamOffset, outputStreamLength);
outputStream.flush();

while (true) {
    final int c = checkAck(inputStream);

    if (c != 'C') break;

    // read '0644 '
    inputStream.read(buffer, 0, 5);

    long filesize = 0L;

    while (true) {
        if (inputStream.read(buffer, 0, 1) < 0) break;

        if (buffer[0] == ' ') break;
        filesize = filesize * 10L + (long)(buffer[0] - '0');
    }

    String file = null;

    for (int i = 0; ; i++) {
        inputStream.read(buffer, i, 1);

        if (buffer[i] == (byte)0x0a){
            file = new String(buffer, 0, i);
            break;
        }
    }

    // send '\0'
    buffer[0] = 0;
    outputStream.write(buffer, 0, 1);
    outputStream.flush();

    // read a content of lfile
    FileOutputStream fos = new FileOutputStream(file);
    int foo;

    while (true) {
        if (buffer.length < filesize) foo = buffer.length;
        else foo = (int)filesize;
        foo = inputStream.read(buffer, 0, foo);

        if (foo < 0){
            // error
            break;
        }

        fos.write(buffer, 0, foo);
        filesize -= foo;

        if (filesize == 0L) break;
    }

    final String textFromDownloadedFile = fos.toString();  

    fos.close();
    fos = null;

    if (checkAck(inputStream) != 0) System.exit(0);

    // send '\0'
    buffer[0] = 0;
    outputStream.write(buffer, outputStreamOffset, outputStreamLength);
    outputStream.flush();
}

session.disconnect();

System.exit(0);

因此,在理想情况下,我会将查询字符串更改为与第 4 步中我想要的匹配的内容,并将它们读入字符串列表或任何最有效的内容,然后我可以存储它们并进入第 5 步。 非常感谢任何帮助。

附言如果有一个更容易使用的具有公司友好许可证的 Java SCP 库,请告诉我!

【问题讨论】:

    标签: java scp jsch


    【解决方案1】:

    使用如下命令:

    scp -r -d -f /remote/path/*
    

    然后遍历服务器发送给您的文件。你的代码似乎已经做了什么。


    请注意,使用 SCP 协议执行第 4 步时恐怕会遇到麻烦。 “不包含” 条件很麻烦。

    使用 SFTP! SCP 是遗留的过时协议。

    当然,你可以执行ls shell 命令。解析结果以查找所有文件的列表。然后在本地过滤它们。


    一些相关问题:

    【讨论】:

    • 在代码中,我相信我是 ssh'd 到服务器上,所以在远程服务器上运行 scp。这就是为什么我认为在 scp 命令中我指的是没有用户名和主机的远程服务器上的目录。如果这是真的,而且我对 ssh\scp 知之甚少,这是合理的,那么我将如何引用运行代码的 machine\vm 上的目录?使用您发布的命令,我现在似乎获得了多个文件名。不确定我是否也获得了实际的文件数据(希望如此!),但我会调查一下。
    • 是的,没错。您在服务器上以服务器模式 (-f) 执行 scp。它会一一为您提供文件。您可以在 file 变量中获得各个文件名(包括相对路径)。 - “我将如何引用运行代码的机器\vm 上的目录” - 不知道你的意思。你想引用它做什么?你知道你传递给远程scp的路径,所以你知道文件来自哪里。
    • 我添加了相关问题的链接,这可能有助于您了解 SCP 的工作原理。
    猜你喜欢
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 2015-05-18
    • 2015-06-06
    相关资源
    最近更新 更多