0

I have to run a shell script from Java in a Linux box for eg, Below is the script path and all parameters needed by the script.

"ksh /xyz/abc/data/code_base/RUN_SCRIPTS/dev/my_script.sh param1 param2 20200901 459 121"

Below is the code,

String script = "ksh /xyz/abc/data/code_base/RUN_SCRIPTS/dev/my_script.sh param1 param2 20200901 459 121";
ProcessBuilder processBuilder = new ProcessBuilder();                       
processBuilder.command(script);
processBuilder.redirectErrorStream(true);
//start() will be in try catch
process = processBuilder.start();

int exitVal = process.waitFor();

if(exitVal == 0){
   //code
}

Do i need to pass the script as a List by adding each as a separate String in the List ? "ksh" , "/xyz/abc/data/code_base/RUN_SCRIPTS/dev/my_script.sh" , "param1" "param2" "20200901" "459" "121"

On my Windows machine, i am opening a Notepad as below and it works fine,

ProcessBuilder processBuilder = new ProcessBuilder("Notepad.exe", "C:/Dev/Test.txt");
processBuilder.redirectErrorStream(true);
process = processBuilder.start();

Will the script get executed on the Linux box properly or any more changes are required in the code ??

VinodKhade
  • 147
  • 1
  • 2
  • 10
  • 2
    "Will the script get executed on the Linux box properly" does it work on your machine, for starters? – Federico klez Culloca Sep 04 '20 at 09:28
  • @FedericoklezCulloca - I am coding on Windows machine and opening a Notepad using below for testing purpose. ProcessBuilder processBuilder = new ProcessBuilder("Notepad.exe", "C:/Dev/Test.txt"); – VinodKhade Sep 04 '20 at 09:46
  • Does this answer your question? [How to run Unix shell script from Java code?](https://stackoverflow.com/questions/525212/how-to-run-unix-shell-script-from-java-code) – Milgo Sep 04 '20 at 09:50
  • @VinodKhade leaving aside the specific case, you should really test it on linux anyway. Don't guess compatibility. Also, don't expect `ksh` to be installed, it's not standard on any linux distro I can think of. – Federico klez Culloca Sep 04 '20 at 10:18
  • @FedericoklezCulloca - How do we handle for ksh ? Do we need to put all these in a list of String ? Like List will contain "ksh" , "/xyz/abc/data/code_base/RUN_SCRIPTS/dev/my_script.sh" , "param1" "param2" "20200901" "459" "121" – VinodKhade Sep 04 '20 at 14:13
  • `new ProcessBuilder("ksh", "-c", "/xyz/abc/data/code_base/RUN_SCRIPTS/dev/my_script.sh", "param1", "param2", etc...);` should do the trick, but, again, test it on an actual linux system (even wsl is fine). – Federico klez Culloca Sep 04 '20 at 15:02
  • @FedericoklezCulloca - Thank you so much...What is the use of "-c" ?. Also is there a reference link which i could refer to get more understanding of this. – VinodKhade Sep 04 '20 at 16:31
  • `-c` is for "command". It's a thing for ksh, not for `ProcessBuilder`. Here's the doc for [`ProcessBuilder`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ProcessBuilder.html#start()) and here's the manual page for [`ksh`](https://linux.die.net/man/1/ksh). – Federico klez Culloca Sep 04 '20 at 16:56

3 Answers3

1

You should be able to use Runtime.exec() or ProcessBuilder to invoke a shell to run a script, but the whole process is full of pitfalls.

I would suggest reading this article:

https://www.infoworld.com/article/2071275/when-runtime-exec---won-t.html

which explains many of these pitfalls, and how to avoid them. In particular, on Linux you'll almost certainly need to consume stdout and stderr from your shell invocation -- that's sometimes true even if the script doesn't produce any output. You'll also need to be careful how you handle spaces and special characters -- if there are any -- in the arguments to your script. The parser that Java uses for the command line blindly breaks a command line at whitespace.

Kevin Boone
  • 4,092
  • 1
  • 11
  • 15
0

Take a look at this Runtime.getRunTime().exec

Difettoso
  • 51
  • 1
  • 1
  • 10
0

You can also use my small library called jaxec:

import com.yegor256.Jaxec;
String stdout = new Jaxec("my_script.sh", "param1", "param2")
    .withHome("/home/me") // run it in this directory
    .withRedirect(false) // don't redirect STDERR to STDOUT
    .exec();

The instance of Jaxec class will not only execute your script, but also will send its output to Slf4j log, wait for its completion, redirect stderr to stdout, and make sure an exception is raised if the exit code is not equal to zero. Behind the scene, Jaxec uses Runtime.

yegor256
  • 102,010
  • 123
  • 446
  • 597