Простой запуск команды Unix с Java.
Runtime.getRuntime().exec(myCommand);
Но можно ли запустить оболочку Unix script из кода Java? Если да, было бы хорошей практикой запускать оболочку script из кода Java?
Простой запуск команды Unix с Java.
Runtime.getRuntime().exec(myCommand);
Но можно ли запустить оболочку Unix script из кода Java? Если да, было бы хорошей практикой запускать оболочку script из кода Java?
Вы действительно должны посмотреть 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();
Я бы сказал, что не в духе Java запускать оболочку script из Java. Java должна быть кросс-платформой, а запуск оболочки script ограничит ее использование только UNIX.
С учетом сказанного, безусловно, можно запустить оболочку script из Java. Вы бы использовали тот же самый синтаксис, который вы указали (я сам не пробовал, но попробуйте выполнить оболочку script напрямую, и если это не сработает, выполните сам оболочку, передав script в качестве параметр командной строки).
Я думаю, что вы ответили на свой вопрос с помощью
Runtime.getRuntime().exec(myShellScript);
Что касается хорошей практики... что вы пытаетесь сделать с оболочкой script, которую вы не можете сделать с Java?
Вы также можете использовать библиотеку exec Apache Commons.
Пример:
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.
Да, это возможно. Это сработало для меня.
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());
}
}
Для меня все должно быть простым. Для запуска script просто нужно выполнить
new ProcessBuilder("pathToYourShellScript").start();
Вот мой пример. Надеюсь, что это имеет смысл.
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;
}
Чтобы избежать жесткого кодирования абсолютного пути, вы можете использовать следующий метод, который найдет и выполнит ваш script, если он находится в корневом каталоге.
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!");
}
}
Возможно, просто выполните его как любую другую программу. Просто убедитесь, что ваш script имеет правильный #! (she-bang) в качестве первой строки script и убедитесь, что в файле есть разрешения на выполнение.
Например, если это bash script положить #!/bin/bash в верхней части script, также chmod + x.
Также, если это хорошая практика, нет, это не так, особенно для Java, но если это сэкономит вам много времени на перенос большого script, и вам не придется платить за это дополнительно;) save ваше время, выполните script и поместите перенос на Java в свой многолетний список задач.
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();
}
Библиотека 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:
Да, это возможно, и вы ответили на это! Что касается хороших практик, я думаю, что лучше запускать команды из файлов, а не непосредственно из вашего кода. Поэтому вы должны заставить Java выполнить список команд (или одну команду) в существующих файлах .bat,.sh,.ksh.... Ниже приведен пример выполнения списка команд в файле "MyFile.sh":
String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
Runtime.getRuntime().exec(cmd);
То же самое, что и Solaris 5.10, работает так: ./batchstart.sh
есть трюк, который я не знаю, если ваша ОС примет его вместо \\. batchstart.sh
. Эта двойная косая черта может помочь.
Я думаю,
System.getProperty("os.name");
Проверка операционной системы может управлять сценариями оболочки /bash, если они поддерживаются. если необходимо сделать переносимый код.