【问题标题】:Shell command in Java with Runtime.getRuntime().exec();Java 中的 Shell 命令与 Runtime.getRuntime().exec();
【发布时间】:2021-09-14 05:46:48
【问题描述】:

这是通过 Java 执行 Shell 命令的简单好方法吗?

Runtime.getRuntime().exec( some command );

或者这是不好的做法?

【问题讨论】:

  • 它使你的代码依赖于平台,所以你应该避免执行shell命令。

标签: java shell


【解决方案1】:

视情况而定。

Unix shell 的最初目的和基本功能是让您运行程序,可选择地向它们传递参数。例如,命令ls 运行ls 程序,命令grep foo bar 运行带有参数foobargrep 程序。 如果你的命令只运行一个(固定的)程序,如果有任何参数,Runtime.exec 可以做到。有两种子情况:

  • 采用String 的重载使用任何空格将行解析为“单词”(程序名称和参数);这与标准 shell 完成的默认解析(不带引号)基本相同。

  • 如果您需要任何不同的解析,例如,如果您的命令将在 shell 中使用任何引用,您必须自己进行解析并将 results 传递给采用 String[] 的重载之一。

但请注意,当您从 interactive shell 运行程序时——使用终端或等效(有时称为控制台)进行输入和输出——程序的输入和输出默认为终端。 Runtime.exec 运行的程序的 I/O 始终是往返于 Java 进程的管道,并且当某些程序的输入和/或输出是管道或文件时,它们的行为会有所不同而不是终端。另外,您必须编写代码来发送(写入)任何所需的输入并接收(读取)任何输出。当然,shell 也可以并且有时也可以在没有终端的情况下运行。

但是,shell 可以并且通常用于做比基础更多的事情:

  • shell 可以通过变量(形式参数)替换(可能带有修改/编辑)、命令替换、进程替换、特殊符号(如 squiggle 和 bang)以及文件名扩展(也称为“globbing”)来执行内容与输入不同的命令(因此之所以调用它,是因为在 Unix 的早期版本中,它是由一个名为 glob 的单独程序完成的。 Runtime.exec 不这样做,尽管您可以编写 Java 代码以通过非常不同的方式生成相同的命令执行结果。

  • shell直接在shell中执行一些命令而不是通过运行程序,因为这些命令会影响shell进程本身, 比如cd umask ulimit exec source/. eval exit alias/unalias,或者像set shift unset export local readonly declare typeset let read readarray/mapfile这样的shell中的变量, 或jobs fg bg 之类的子进程,或[[ ]](( )) 之类的特殊解析(在某些shell 中)。这些被称为“内置”,Runtime.exec 不能这样做, 有两个部分例外:它可以运行具有不同工作目录和/或环境变量设置的程序,相当于以前执行过cdexport 或等效项。 Shell 还经常具有复制或修改“正常”程序的内置函数。这些通常包括test/[ echo printf kill timeRuntime.exec只能做程序版本,不能做内置版本。

  • shell 具有控制结构(复合命令),例如 if/then/else/elif/fiwhile/for/do/donetrap && || ( ) { }Runtime.exec 无法做到这些,尽管在某些情况下您可以使用 Java 逻辑来产生相同的结果。 shell 也可以有用户定义的函数和别名,可以用作命令; Runtime.exec 没有。

  • shell 可以重定向它运行的程序的 I/O,包括形成管道。 Runtime.exec 无法做到这些,但请参见下文。

从 1.5 开始,Java 也有 ProcessBuilder,它提供了相同的功能和更多功能,而且 API 更灵活,可以说更清晰,因此通常被推荐使用。 ProcessBuilder 确实支持为它运行的程序重定向 I/O,包括使用终端/控制台 if JVM 是在/从一个上运行的(并非总是如此),并且从 9 开始可以建立管道。它没有Runtime.exec(String) 的分词功能,但您可以使用string.split("[ \t]+") 或在大多数情况下只需" +" 轻松获得相同的结果。

注意 shell 本身就是一个程序,因此您可以使用 Runtime.execProcessBuilder 来运行 shell 并传递 it 一个命令,或者使用选项 -c 作为参数(在至少标准shell)或作为输入,毫不奇怪,这个shell命令可以做任何shell命令可以做的事情。 但这可能是一个可移植性问题,因为不同的系统可能有不同的 shell,尽管任何声称 Unix 认证或 POSIX 一致性的系统都必须有一个满足某些最低要求的 named sh 的 shell。 在不同系统上使用的实际 shell 可能是 bash dash ksh ash 中的任何一个,甚至更多。 OTOH 对于其他程序也是如此;一些通常在不同系统上显着不同的程序是 awk sed grep 以及与管理有关的任何东西,例如 netstat

一些现有的 Qs 显示在 Runtime.exec 中至少按原样不起作用的 shell 命令:
a command for sherlock.py is interpreted differently from linux command line and java process api
Execute shell script multiple commands in one line using Process Builder in Java (Unix)
Check in Java if a certain application is in focus Problem in executing command on AIX through Java
ProcessBuilder doesn't recognise embedded command
File not Found when executing a python scipt from java
Java system command to load sqlite3 db from file fails
Curl To Download Image In JAVA
Keytool command does not work when invoked with Java
use javap from within a java program on all the files
Using SSMTP and ProcessBuilder
@987654332 @
Whitespace in bash path with java
java.lang.Runtime exception "Cannot run program"
Why does Runtime.exec(String) work for some but not all commands?
How to save Top command output in a text or csv file in java?
Execute bash-command in Java won't give a return
Using Java's Runtime.getRuntime().exec I get error with some commands, success with others -- how can this be determined?
Java and exec command - pipe multiple commands
Java exec() does not return expected result of pipes' connected commandsHow to make pipes work with Runtime.exec()?
How to use Pipe Symbol through exec in Java
In Runtime.getRuntime().exec() getting error: /bin/bash: No such file or directory
Java exec linux command
How to use pipes in a java Runtime.exec
Java Runtime.getRuntime().exec and the vertical bar
Whenever I execute terminal command from code it gives "cannot run program" error=2 No such file or directory
Command line proccess read linux in java
Java Command line system call does not work properly

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    相关资源
    最近更新 更多