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

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

Runtime.getRuntime().exec(myCommand);

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

4b9b3361

Вы действительно должны посмотреть 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();
152
ответ дан 08 февр. '09 в 23:18
источник

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

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

23
ответ дан 08 февр. '09 в 8:41
источник

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

Runtime.getRuntime().exec(myShellScript);

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

22
ответ дан 08 февр. '09 в 8:39
источник

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

16
ответ дан 15 февр. '14 в 7:15
источник

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

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());
        }
    }
8
ответ дан 04 марта '13 в 17:25
источник

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

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

new ProcessBuilder("pathToYourShellScript").start();
2
ответ дан 10 июля '12 в 12:47
источник

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

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;
}
2
ответ дан 27 июля '16 в 9:09
источник

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

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

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

1
ответ дан 08 февр. '09 в 10:49
источник
  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();
  }  
1
ответ дан 19 мая '16 в 17:57
источник

Библиотека 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
  • Поддержка нескольких процессов
1
ответ дан 30 июля '16 в 17:34
источник

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

    String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"};
    Runtime.getRuntime().exec(cmd);
1
ответ дан 14 окт. '16 в 19:25
источник

Я думаю,

System.getProperty("os.name"); 

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

0
ответ дан 10 июня '13 в 12:39
источник

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

0
ответ дан 10 окт. '09 в 3:59
источник