从Java运行Unix命令非常简单。
Runtime.getRuntime().exec(myCommand);
但是可以从Java代码运行Unix shell脚本吗?如果是,从Java代码中运行shell脚本是一个好习惯吗?
答案 0 :(得分:171)
你应该看看Process Builder。它真的是为这种东西而建的。
ProcessBuilder pb = new ProcessBuilder("myshellScript.sh", "myArg1", "myArg2");
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");
pb.directory(new File("myDir"));
Process p = pb.start();
答案 1 :(得分:23)
我会说,从Java 的精神来看,不是从Java运行shell脚本。 Java应该是跨平台的,运行shell脚本会将其用途仅限于UNIX。
说到这一点,绝对可以从Java中运行shell脚本。您使用的是与您列出的完全相同的语法(我自己没有尝试过,但是尝试直接执行shell脚本,如果不起作用,请执行shell本身,将脚本作为命令行参数传递)
答案 2 :(得分:21)
我认为您已经用
回答了自己的问题Runtime.getRuntime().exec(myShellScript);
至于它是否是一种好的做法......你试图用你不能用Java做的shell脚本做什么?
答案 3 :(得分:20)
您也可以使用Apache Commons exec library。
示例:
package testShellScript;
import java.io.IOException;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
public class TestScript {
int iExitValue;
String sCommandString;
public void runScript(String command){
sCommandString = command;
CommandLine oCmdLine = CommandLine.parse(sCommandString);
DefaultExecutor oDefaultExecutor = new DefaultExecutor();
oDefaultExecutor.setExitValue(0);
try {
iExitValue = oDefaultExecutor.execute(oCmdLine);
} catch (ExecuteException e) {
System.err.println("Execution failed.");
e.printStackTrace();
} catch (IOException e) {
System.err.println("permission denied.");
e.printStackTrace();
}
}
public static void main(String args[]){
TestScript testScript = new TestScript();
testScript.runScript("sh /root/Desktop/testScript.sh");
}
}
为了进一步参考,还给出了一个例子Apache Doc。
答案 4 :(得分:11)
是的,可以这样做。这对我有用。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.omg.CORBA.portable.InputStream;
public static void readBashScript() {
try {
Process proc = Runtime.getRuntime().exec("/home/destino/workspace/JavaProject/listing.sh /"); //Whatever you want to execute
BufferedReader read = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
try {
proc.waitFor();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
while (read.ready()) {
System.out.println(read.readLine());
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
答案 5 :(得分:4)
这是我的例子。希望它有意义。
public static void excuteCommand(String filePath) throws IOException{
File file = new File(filePath);
if(!file.isFile()){
throw new IllegalArgumentException("The file " + filePath + " does not exist");
}
if(this.isLinux()){
Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null);
}else if(this.isWindows()){
Runtime.getRuntime().exec("cmd /c start " + filePath);
}
}
public static boolean isLinux(){
String os = System.getProperty("os.name");
return os.toLowerCase().indexOf("linux") >= 0;
}
public static boolean isWindows(){
String os = System.getProperty("os.name");
return os.toLowerCase().indexOf("windows") >= 0;
}
答案 6 :(得分:3)
ZT Process Executor库是Apache Commons Exec的替代品。它具有运行命令,捕获输出,设置超时等功能。
我还没有使用它,但它看起来相当充分。
文档中的示例:执行命令,将stderr泵入记录器,将输出返回为UTF8字符串。
String output = new ProcessExecutor().command("java", "-version")
.redirectError(Slf4jStream.of(getClass()).asInfo())
.readOutput(true).execute()
.outputUTF8();
其文档列出了Commons Exec的以下优点:
答案 7 :(得分:3)
是的,这是可能的,你已经回答了!关于良好实践,我认为最好从文件中启动命令,而不是直接从代码中启动命令。因此,您必须使Java在现有的.bat,.sh,.ksh ...文件中执行命令列表(或一个命令)。 以下是在文件&#34; MyFile.sh&#34;中执行命令列表的示例:
String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
Runtime.getRuntime().exec(cmd);
答案 8 :(得分:3)
为了避免对绝对路径进行硬编码,您可以使用以下方法找到并执行您的脚本(如果它位于根目录中)。
public static void runScript() throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder("./nameOfScript.sh");
//Sets the source and destination for subprocess standard I/O to be the same as those of the current Java process.
processBuilder.inheritIO();
Process process = processBuilder.start();
int exitValue = process.waitFor();
if (exitValue != 0) {
// check for errors
new BufferedInputStream(process.getErrorStream());
throw new RuntimeException("execution of script failed!");
}
}
答案 9 :(得分:2)
至于我,一切都必须简单。 对于运行脚本,只需要执行
new ProcessBuilder("pathToYourShellScript").start();
答案 10 :(得分:2)
这是一个如何从Java运行Unix bash或Windows bat / cmd脚本的示例。可以在脚本上传递参数,并从脚本接收输出。该方法接受任意数量的参数。
public static void runScript(String path, String... args) {
try {
String[] cmd = new String[args.length + 1];
cmd[0] = path;
int count = 0;
for (String s : args) {
cmd[++count] = args[count - 1];
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
process.waitFor();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
while (bufferedReader.ready()) {
System.out.println("Received from script: " + bufferedReader.readLine());
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
System.exit(1);
}
}
在Unix / Linux上运行时,路径必须类似于Unix(以'/'作为分隔符),而在Windows上运行时,请使用'\'。 Hier是一个bash脚本(test.sh)的示例,该脚本接收任意数量的参数并将每个参数加倍:
#!/bin/bash
counter=0
while [ $# -gt 0 ]
do
echo argument $((counter +=1)): $1
echo doubling argument $((counter)): $(($1+$1))
shift
done
致电
runScript("path_to_script/test.sh", "1", "2")
在Unix / Linux上,输出为:
Received from script: argument 1: 1
Received from script: doubling argument 1: 2
Received from script: argument 2: 2
Received from script: doubling argument 2: 4
Hier是一个简单的cmd Windows脚本test.cmd,它计算输入参数的数量:
@echo off
set a=0
for %%x in (%*) do Set /A a+=1
echo %a% arguments received
在Windows上调用脚本时
runScript("path_to_script\\test.cmd", "1", "2", "3")
输出为
Received from script: 3 arguments received
答案 11 :(得分:1)
有可能,只需执行任何其他程序。只需确保您的脚本具有正确的#! (she-bang)行作为脚本的第一行,并确保文件具有执行权限。
例如,如果它是一个bash脚本,将#!/ bin / bash放在脚本的顶部,也是chmod + x。
另外,如果这是一个好的做法,不是没有,特别是对于Java,但是如果它节省了大量时间移植大型脚本,并且你没有得到额外的报酬;)节省你的时间,执行脚本,并在您的长期待办事项列表中将Java移植到Java。
答案 12 :(得分:1)
String scriptName = PATH+"/myScript.sh";
String commands[] = new String[]{scriptName,"myArg1", "myArg2"};
Runtime rt = Runtime.getRuntime();
Process process = null;
try{
process = rt.exec(commands);
process.waitFor();
}catch(Exception e){
e.printStackTrace();
}
答案 13 :(得分:1)
这是一个迟到的答案。但是,我想到了为了让未来的开发人员从Spring-Boot应用程序中执行shell脚本而付出的努力。
我在Spring-Boot工作,我无法找到要从我的Java应用程序执行的文件而且它正在抛出FileNotFoundFoundException
。我必须将文件保留在resources
目录中,并且必须在启动应用程序时将文件设置为pom.xml
,如下所示。
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
<include>**/*.sh</include>
</includes>
</resource>
</resources>
error code = 13, Permission Denied
。然后我必须通过运行此命令 - chmod u+x myShellScript.sh
最后,我可以使用以下代码片段执行该文件。
public void runScript() {
ProcessBuilder pb = new ProcessBuilder("src/main/resources/myFile.sh");
try {
Process p;
p = pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
希望解决某人的问题。
答案 14 :(得分:0)
就像它所使用的Solaris 5.10一样./batchstart.sh
有一个技巧我不知道你的操作系统是否接受它使用\\. batchstart.sh
。这个双斜线可能有所帮助。
答案 15 :(得分:0)
我想用
System.getProperty("os.name");
如果支持操作系统,则可以管理shell / bash scrips。 如果需要使代码可移植。
答案 16 :(得分:0)
供Linux使用
public static void runShell(String directory, String command, String[] args, Map<String, String> environment)
{
try
{
if(directory.trim().equals(""))
directory = "/";
String[] cmd = new String[args.length + 1];
cmd[0] = command;
int count = 1;
for(String s : args)
{
cmd[count] = s;
count++;
}
ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String, String> env = pb.environment();
for(String s : environment.keySet())
env.put(s, environment.get(s));
pb.directory(new File(directory));
Process process = pb.start();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter outputReader = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
int exitValue = process.waitFor();
if(exitValue != 0) // has errors
{
while(errReader.ready())
{
LogClass.log("ErrShell: " + errReader.readLine(), LogClass.LogMode.LogAll);
}
}
else
{
while(inputReader.ready())
{
LogClass.log("Shell Result : " + inputReader.readLine(), LogClass.LogMode.LogAll);
}
}
}
catch(Exception e)
{
LogClass.log("Err: RunShell, " + e.toString(), LogClass.LogMode.LogAll);
}
}
public static void runShell(String path, String command, String[] args)
{
try
{
String[] cmd = new String[args.length + 1];
if(!path.trim().isEmpty())
cmd[0] = path + "/" + command;
else
cmd[0] = command;
int count = 1;
for(String s : args)
{
cmd[count] = s;
count++;
}
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter outputReader = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
int exitValue = process.waitFor();
if(exitValue != 0) // has errors
{
while(errReader.ready())
{
LogClass.log("ErrShell: " + errReader.readLine(), LogClass.LogMode.LogAll);
}
}
else
{
while(inputReader.ready())
{
LogClass.log("Shell Result: " + inputReader.readLine(), LogClass.LogMode.LogAll);
}
}
}
catch(Exception e)
{
LogClass.log("Err: RunShell, " + e.toString(), LogClass.LogMode.LogAll);
}
}
以及用途;
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"});
OR
ShellAssistance.runShell("", "pg_dump", new String[]{"-U", "aliAdmin", "-f", "/home/Backup.sql", "StoresAssistanceDB"}, new Hashmap<>());