Как запустить оболочку Unix script из кода Java? - программирование

Как запустить оболочку Unix script из кода Java?

Простой запуск команды Unix с Java.

Runtime.getRuntime().exec(myCommand);

Но можно ли запустить оболочку Unix script из кода Java? Если да, было бы хорошей практикой запускать оболочку script из кода Java?

4b9b3361

Ответ 1

Вы действительно должны посмотреть 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();

Ответ 2

Я бы сказал, что не в духе Java запускать оболочку script из Java. Java должна быть кросс-платформой, а запуск оболочки script ограничит ее использование только UNIX.

С учетом сказанного, безусловно, можно запустить оболочку script из Java. Вы бы использовали тот же самый синтаксис, который вы указали (я сам не пробовал, но попробуйте выполнить оболочку script напрямую, и если это не сработает, выполните сам оболочку, передав script в качестве параметр командной строки).

Ответ 3

Я думаю, что вы ответили на свой вопрос с помощью

Runtime.getRuntime().exec(myShellScript);

Что касается хорошей практики... что вы пытаетесь сделать с оболочкой script, которую вы не можете сделать с Java?

Ответ 4

Вы также можете использовать библиотеку 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.

Ответ 5

Да, это возможно. Это сработало для меня.

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());
        }
    }

Ответ 6

Для меня все должно быть простым. Для запуска script просто нужно выполнить

new ProcessBuilder("pathToYourShellScript").start();

Ответ 7

Вот мой пример. Надеюсь, что это имеет смысл.

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;
}

Ответ 8

Чтобы избежать жесткого кодирования абсолютного пути, вы можете использовать следующий метод, который найдет и выполнит ваш 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!");
    }
}

Ответ 9

Возможно, просто выполните его как любую другую программу. Просто убедитесь, что ваш script имеет правильный #! (she-bang) в качестве первой строки script и убедитесь, что в файле есть разрешения на выполнение.

Например, если это bash script положить #!/bin/bash в верхней части script, также chmod + x.

Также, если это хорошая практика, нет, это не так, особенно для Java, но если это сэкономит вам много времени на перенос большого script, и вам не придется платить за это дополнительно;) save ваше время, выполните script и поместите перенос на Java в свой многолетний список задач.

Ответ 10

  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();
  }  

Ответ 11

Библиотека 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:

  • Улучшенная обработка потоков
    • Чтение/запись в потоки
    • Перенаправление stderr в stdout
  • Улучшена обработка тайм-аутов
  • Улучшена проверка кодов выхода
  • Улучшенный API
    • Один вкладыш для довольно сложных вариантов использования
    • Один лайнер для вывода процесса в строку
    • Доступ к объекту Процесс
    • Поддержка асинхронных процессов (Будущее)
  • Улучшен ведение журнала с помощью API SLF4J
  • Поддержка нескольких процессов

Ответ 12

Да, это возможно, и вы ответили на это! Что касается хороших практик, я думаю, что лучше запускать команды из файлов, а не непосредственно из вашего кода. Поэтому вы должны заставить Java выполнить список команд (или одну команду) в существующих файлах .bat,.sh,.ksh.... Ниже приведен пример выполнения списка команд в файле "MyFile.sh":

    String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
    Runtime.getRuntime().exec(cmd);

Ответ 13

То же самое, что и Solaris 5.10, работает так: ./batchstart.sh есть трюк, который я не знаю, если ваша ОС примет его вместо \\. batchstart.sh. Эта двойная косая черта может помочь.

Ответ 14

Я думаю,

System.getProperty("os.name"); 

Проверка операционной системы может управлять сценариями оболочки /bash, если они поддерживаются. если необходимо сделать переносимый код.