java - 使用 Runtime.exec 处理 i/o 流

标签 java process stream

我正在尝试在 Java 中运行 scp 命令。这是我的代码,

try {
    Process p = Runtime.getRuntime().exec("scp -P" + PORT + " " + FILEPATH + " " + USERNAME + "@" + HOST + ":somefolder/");
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
    String line;
    while ((line=br.readLine()) != null) {
        System.out.println("LINE: " + line);
        if (line.contains(USERNAME+"@"+HOST+"'s password:")) {
            bw.write(PASSWORD);
            bw.newLine();
        }
    }
    System.out.println("end of while.");
} catch (IOException e) {
    e.printStackTrace();
}

如您所见,我不想盲目地将密码打印到 p.getOutputStream(),几乎所有类似的问题都建议这样做。我想阅读提示并采取相应行动。例如,scp 可能会提示“The authenticity of host 'SOME HOST' can't be established...”,提示是/否。或者我现在无法想象的其他东西。

我的代码的问题是它从不读取一行,尽管 scp 提示输入密码,这在 cli 上可以看到。有什么建议吗?

编辑: 正如 Andrew Thompson 所建议的,我更改了代码以使用 ProcessBuilder 和 String[] 构造函数。完整代码如下:

package scptest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class STest {

    // args => filepath, username, host, port, password
    public static void main(String[] args) {
        try {
            ProcessBuilder pb = new ProcessBuilder("scp", "-P", args[3],
                    args[0], args[1] + "@" + args[2] + ":folder/");
            Process p = pb.start();
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    p.getInputStream()));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    p.getOutputStream()));
            String line;
            bw.write(args[4]);
            bw.newLine();
            bw.flush();
            System.out.println("RETURN: " + p.waitFor());
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

}

如你所见,我放弃了检查scp的提示,直接将密码发送到Process的输入流。这也行不通!我的意思是,当我在命令行中执行 jar 文件时,我看到提示“用户名@主机的密码:”,它等待密码。当我在没有输入密码的情况下按回车键时,它只是重新询问密码而没有任何错误消息,这意味着没有字符串被提供给 Process 的输入流,即我的 BufferedWriter 似乎什么也没做。

我正在使用 jdk 1.7.0_45 在 w8 机器上编译我的程序,我在 Ubuntu Server x64 上使用 jre 1.7.0_51 运行该程序。

最佳答案

我发现配置 rsa 文件和在 scp 命令中使用 -i 选项更容易。

只需使用 -i HOST 机器的私钥所在的位置。您还需要将运行命令的机器的公钥添加到主机机器中的授权 key 文件中。

这样他就不会提示您输入密码了。此外,如果您使用 -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 选项,您几乎不必担心任何事情(这并不总是一件好事!)

关于java - 使用 Runtime.exec 处理 i/o 流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21159231/

相关文章:

java - 获取惰性 OneToOne 实体会获取同一对象内的所有其他 OneToOne 实体

vb.net - 从正在运行的进程中提取文件名和路径

android - Android中所有正在运行的进程列表

unit-testing - 用mockito模拟的方法(带有可选参数)在单元测试中返回null。 Dart flutter

node.js - Express (node.js) 似乎正在用 application/json 替换我的内容类型

clojure - 在 Clojure 的 Ring Web 应用程序中生成并传输 zip 文件

java - 应用程序关闭时警报管理器不会启动

java - 我在使用 JPA 从 mssql 的关系表中获取数据时遇到问题

java - Android 错误 : Attempt to invoke virtual. .. setOnClickListener(android.view.View$OnClickListener)' 空对象引用

java - ProcessBuilder 向命令行添加额外的引号