【问题标题】:Process.= Runtime.getRuntime().exec() not working for meProcess.= Runtime.getRuntime().exec() 不适合我
【发布时间】:2013-03-28 14:54:48
【问题描述】:

当我从 java 执行 linux 命令时,它不起作用任何人都可以帮助我解决这个问题。

process3 = Runtime.getRuntime().exec(new String[] {"ls",
                    "-1s", 
                     "--block-size=1",
                      TStamp+"/received/i*.*",
                      "$dir|",
                      "awk",
"'{print $2\"\\t\"$1}'",
                           ">>",
                  "./"+TStamp+"/qa/manifest_QAG.txt"});
InputStream in1 = process3.getInputStream();              
BufferedReader br1=new BufferedReader(new InputStreamReader(in1));
String line1 =null;
while((line1=br1.readLine())!=null)
{
System.out.println(line1);
} 

Edit1:我试图列出文件并在 manifest_QAG.txt 中生成清单

实际命令在 linux 下工作:

ls -1s --block-size=1 20130328094916142/received/is*.* $dir| awk '{print $2"\t"$1}'

Edit2:我没有得到任何异常,甚至没有创建文件 manifest_QAG.txt

编辑 3:

【问题讨论】:

  • 究竟是什么不起作用?
  • 我正在尝试列出文件并在 manifest_QAG.txt 中生成清单
  • 但是怎么了?输出是什么?有输出吗?也许例外?
  • 我什至没有得到异常,也没有创建文件 manifest_QAG.txt
  • 你不能在一个String 中写入所有以数组形式写入的命令吗?我猜你放在 String 数组中的命令语法有一些错误

标签: java linux inputstream runtime.exec


【解决方案1】:

您没有收到异常,因为 ls 命令不是 Java 并且不与异常通信,而是与 STDERR 上的错误消息和退出代码进行通信。

其实你必须明白当你输入一个命令时shell做了什么,以及这个命令做了什么。因此,像这样的 shell 命令行

ls -1s --block-size=1 20130328094916142/received/is*.* $dir| awk '{print $2"\t"$1}'

由 shell 以这种方式处理:

  • shell:将20130328094916142/received/is*.* 扩展为文件名列表
  • shell:将$dir 部分扩展为文件名列表
  • shell:使用参数执行ls 命令
    • ls
    • -1s
    • --block-size=1
    • 每个扩展文件名作为单独的参数
  • shell: 使用参数执行awk 命令
    • {print ...}
  • shell:将ls的输出连接到awk的输入
  • ls:评估参数
  • awk:读取每一行,用给定的脚本处理并输出结果。

你看:环境变量和通配符的扩展是由shell完成的,而不是ls

回到 Java: execute 确实 NOT 像 shell 一样处理参数。那取决于你。因此,您的调用与 shell 等效,大致如下:

ls '-1s' '--block-size=1' '20130328094916142/received/is*.*' '$dir' '|' 'awk' '{print $2"\t"$1}'

所有内容都被引用,甚至是管道,因此 shell 不会扩展任何内容。

到目前为止的问题。有什么解决办法?

  • 您可以模拟 shell 并在 Java 中进行扩展。玩得开心。 (即这不是真正的解决方案)。
  • 您可以从 Java 调用 shell 而不是 ls

后面是这样的:

shell 通常有一个-c 选项,您可以在其中给它一个命令字符串,然后以与实际键入的命令行相同的方式对其进行评估。

所以你这样调用命令

String[] args = {
    "/bin/sh",
    "-c",
    "ls -1s --block-size=1 20130328094916142/received/is*.* $dir| awk '{print $2\"\t\"$1}'"
};
Process process3 = Runtime.getRuntime().exec(args);

虽然awk 命令的正确引用可能需要更多的工作。

【讨论】:

    【解决方案2】:

    管道 (|) 不是 ls 的参数,而是 shell 的一个功能。如果你想在 Runtime#exec 中使用这样的管道,你必须启动一个 shell,并将你希望 shell 解析和执行的命令字符串作为参数传递。

    除非我遗漏了什么,否则使用 Java 代码列出目录和编写清单可能会更容易,而不是调用外部工具来进行琐碎的文件和字符串操作。

    【讨论】:

    • 是的,我们可以使用 java 来做这件事非常简单,但我用 Runtime.getRuntime().exec(); 来练习复杂性;
    • 我可以知道如何传递另一个shell吗?
    【解决方案3】:

    我觉得这里有错别字

    /received/i*.* is different from one that is in linux command /received/is*.*
    

    希望对你有帮助

    【讨论】:

    • 这不是问题 is*.* 是 i*.* 的交集
    猜你喜欢
    • 1970-01-01
    • 2020-12-02
    • 1970-01-01
    • 2011-01-09
    • 2015-08-28
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多