【问题标题】:How to use Java exec如何使用 Java 执行程序
【发布时间】:2012-09-07 22:38:20
【问题描述】:

我对 java 还很陌生,现在我想使用 java 通过 windows 命令运行 SSH。

这是我创建的代码,

Process pr1 = Runtime.getRuntime().exec("cmd /k" + "ssh root@host" + "&&" + "passwd" );
Process pr = Runtime.getRuntime().exec("ls");
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;

while((line=input.readLine()) != null)
    System.out.println(line);

我总是得到错误:

java.io.IOException:无法运行程序“ls”:CreateProcess 错误=2, 系统找不到指定的文件

有人可以帮我吗?

【问题讨论】:

  • 您似乎正试图在 Windows 机器上执行 ls...如果这是您所期望的,它不会在远程机器上执行。
  • 相反,您应该找到一种方法将 ls\n 写入 ssh ProcessOutputStream,但我不确定具体如何执行此操作。免费提示答案。不过,您最好为 Java 找到一个 SSH 库。
  • this question。这可能是比手动执行更好的方法。

标签: java exec


【解决方案1】:

不要打扰 Runtime.exec,使用Apache Commons Exec。要将其应用于您的问题,它看起来像这样:

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
CommandLine pr1 = CommandLine.parse("cmd /k" + "ssh root@host" + "&&" + "passwd");
CommandLine pr = CommandLine.parse("ls");
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(streamHandler);

int exitValue = executor.execute(pr1);
exitValue = executor.execute(pr);

【讨论】:

  • 根据 DefaultExecutor JavaDoc,PumpStreamHandler 已经默认使用,所以你可以跳过 setStreamHandler() 的那一步;
【解决方案2】:

除了使用JSch(或任何其他Java SSH 实现)之外,通过环境变量传递路径可能不起作用,因为大多数SSH 守护程序只接受来自另一端的一小部分变量(主要与本地化有关或终端类型)。

由于 ssh 的参数(或“命令”,如果将 JSch 与 ChannelExec 一起使用)传递给远程 shell 以执行,您可以尝试在此命令中定义路径(如果您的默认 shell 兼容POSIX sh):

PATH=path_needed_toRun_myProg /absPathToMyProg/myProg

因此,您的 Runtime.exec 数组如下所示:

String[] cmd = {"/usr/bin/ssh", "someRemoteMachine",
                "PATH=path_needed_toRun_myProg /absPathToMyProg/myProg"};

如果使用 Runtime.exec 不是硬性规定,那么试试 Apache 的 Exec 库...

查看此链接:

http://commons.apache.org/exec/

【讨论】:

    【解决方案3】:

    实际上答案可能很简单:问题是您正在执行 SSH 命令,然后执行一个单独的命令 ls 发送到 Windows 控制台(而不是通过 SSH)所以,正如您所知 Windows 没有ls 命令。

    您必须将其发送到 SSH 命令的 exec 返回的 Process,您可以通过存储结果进程、检索其 OutputStream 并在那里写入逗号来实现。当然,您必须使用它的InputStream 来获取结果。第二个exec() 根本不应该存在。

    【讨论】:

    • 你切换了流。您将命令写入OutputStream 并从InputStream 读取结果:3
    【解决方案4】:

    你想写入进程的标准输入。

    pr.getOutputStream().write("ls\n".getBytes());
    

    【讨论】:

    • 既然他在 Windows 上,而另一个盒子是某种 UNIX 风格,应该使用什么字符编码将 ls\n 转换为字节?
    • 好问题。我怀疑只有一个正确答案。鉴于所讨论的字符是 7 位 ASCII,许多编码将产生相同的字节。
    【解决方案5】:

    请使用https://github.com/zeroturnaround/zt-exec。 Apache Commons Exec 有很多缺点,你需要相当多的代码才能让它正确。一切都在这里解释:https://zeroturnaround.com/rebellabs/why-we-created-yaplj-yet-another-process-library-for-java/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 2014-11-29
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      • 1970-01-01
      相关资源
      最近更新 更多