You should really look at Process Builder. It is really built for this kind of thing.

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();
Answer from Milhous on Stack Overflow
🌐
Baeldung
baeldung.com › home › java › core java › how to run a shell command in java
How to Run a Shell Command in Java | Baeldung
January 8, 2024 - Quick guide to how to two ways of running a shell command in Java, both on Windows as well as on UNIX.
🌐
Stack Abuse
stackabuse.com › executing-shell-commands-with-java
Executing Shell Commands with Java
May 18, 2020 - In this article, we've explored examples of running shell commands in Java. We've used the Runtime and ProcessBuilder classes to do this. Using Java, we can run single or multiple shell commands, execute shell scripts, run the terminal/command prompt, set working directories and manipulate environment variables through core classes.
🌐
Mkyong
mkyong.com › home › java › how to execute shell command from java
How to execute shell command from Java - Mkyong.com
January 3, 2019 - Founder of Mkyong.com, passionate Java and open-source technologies. If you enjoy my tutorials, consider making a donation to these charities. ... I used the same (similar) code for my ShellWrapper. When I use commands like echo it works fine, but when I use commands like cat it returns an empty String…. ... As a good practice, I wouldn’t catch Exception e. Just mention the two that need to be dealt with (IOException, InterruptedException) .
🌐
Redpill Linpro
redpill-linpro.com › techblog › 2024 › 02 › 21 › java-21-shell-scripts.html
Portable Java shell scripts with Java 21 – /techblog
February 21, 2024 - Finally, when the Java process has terminated, the exit code from the Java process ($?) is propagated as the exit code of the script so that users of the script can handle errors in a predictable way. It also prevents the program loader from attempting to execute the rest of the file: ///usr/bin/env java --source 21 --enable-preview "$0" "$@"; exit $? As long as you have Java 11 or higher, you can still make Java shell scripts, you just need to declare a class and make the main method static:
🌐
ExtraVM
thishosting.rocks › how-to-execute-a-shell-command-using-java
How To Execute a Shell Command Using Java
May 19, 2021 - Runtime.exec() is a simple high-level class, not customizable at the moment but available in every Java application. It gives the possibility for the application to communicate within its environment. The exec() method is for executing commands directly or running .bat/.sh files. try { // -- Linux -- // Run a shell command // Process process = Runtime.getRuntime().exec("ls /home/mkyong/"); // Run a shell script // Process process = Runtime.getRuntime().exec("path/to/hello.sh"); // -- Windows -- // Run a command //Process process = Runtime.getRuntime().exec("cmd /c dir C:\\Users\\mkyong"); //Ru
Find elsewhere
🌐
Unix.com
unix.com › shell programming and scripting
Compiling and Executing a Java File With a Shell Script - Shell Programming and Scripting - Unix Linux Community
March 28, 2017 - I’m trying to use a shell script to compile and execute a java file. The java classes are using sockets, so there is a client.java file and a server.java file, each with their own shell script. I also want to handle the …
🌐
Princeton CS
introcs.cs.princeton.edu › java › 15inout › linux-cmd.html
Java and the Linux Command Line
You will use the javac command to convert your Java program into a form more amenable for execution on a computer. From the shell, navigate to the directory containing your .java files, say ~wayne/introcs/hello, by typing the cd command below.
🌐
Medium
medium.com › se-notes-by-alexey-novakov › shell-script-in-java-8b3339be0280
Shell Script in Java. If you always wanted to write a shell… | by Alexey Novakov | SE Notes by Alexey Novakov | Medium
December 26, 2018 - Apart from the shebang file mode, one can run single-file source-code program via java command directly, for example: java -Dtrace=true --source 11 myprogram some_param1 · Let’s imagine some use case where we could apply this feature: Set Docker image tag for local Docker images and push them to specific Docker registry. Let’s solve it with with shell program in Java.
🌐
Stack Overflow
stackoverflow.com › questions › 31116296 › run-java-commands-through-a-shell-script
bash - run Java commands through a Shell script - Stack Overflow
May 1, 2016 - After that, no command in my script works unless I quit that console. Any solutions please? And if it's not feasible using shell scripts, any suggestions please? ... Thanks for your answer. The problem is, the commands I'm executing after that are no Shell commands but commands related to vuze like create or show torrents. Therefore I got an error message. ... Basically, the moment you run that command, your java program runs 'in the foreground', which means the rest of your script stops executing until your program exits.
Top answer
1 of 4
3

I don't know anything about Java, but I can show you a proof of concept. Say we have localfile.txt:

Here is the local file.

and on the remote machine, we have remote.sh:

#!/bin/bash
cat /dev/stdin

Note that the script on the remote machine invokes a program which reads from stdin. Then pass the contents of localfile.txt to your ssh command:

user@local:~$ cat localfile.txt | ssh user@remote remote.sh
Here is the local file.

Your Java program is trying to read a file which does not exist on the remote machine. I guess you could try to mimic a local file.

Change remote.sh to:

#!/bin/bash
cat "$@"

and invoke it with

user@local:~$ cat localfile.txt | ssh user@remote 'remote.sh <(cat /dev/stdin)'
Here is the local file.

I think it would be easier to change that part in your Java program to read from stdin.

I guess things might get messy if localfile.txt contains anything that might be interpreted by the shell as expandable (such as *), but that's for you to figure out.

2 of 4
2

The problem is that the shell redirection (<) sends the file over the ssh tunnel. And the Java class is expecting not the file, but a string with the "filename" of a local file that will be read with a FileReader.

Instead of passing the filename to the FileReader, read from the standard input.

InputStreamReader isReader = new InputStreamReader(System.in);
BufferedReader iR  = new BufferedReader (isReader);

Used this as a reference: https://stackoverflow.com/questions/5724646/how-to-pipe-input-to-java-program-with-bash

Now your class will be:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;

public class ReadFirstLine 
{
    public static void main(String[] args) throws Exception 
    {
       String filename = args[0];
       System.out.println(filename);

       //BufferedReader iR  = new BufferedReader (new FileReader(filename));
       InputStreamReader isReader = new InputStreamReader(System.in);
       BufferedReader iR  = new BufferedReader (isReader);

       BufferedWriter oW = new BufferedWriter(new OutputStreamWriter(System.out));

       //outputWriter.write(iR.readLine());
       System.out.println(iR.readLine());

       iR.close();
       oW.close();
    }
}

But for this task I would definitely use instead:

head -1 filename.txt

:)

🌐
Kevin Boone
kevinboone.me › exec.html
How to run a shell script from a Java application - Kevin Boone
Running a shell script from a Java program using Runtime.exec() appears simple. In practice, there are many pitfalls. This article describes how to avoid at least some of them.
🌐
Belief Driven Design
belief-driven-design.com › revisiting-java-for-shell-scripting-7ff3e
Revisiting Java for Shell Scripting | belief driven design
September 21, 2023 - Put in your Java code, make the file executable with chmod +x MyScriptFile, and you can run it with ./MyScriptFile. Now you have a Java shell script that’s easy to edit and doesn’t require any additional steps like before! Another thing is that the JEP anticipated using shebang files.
🌐
GeeksforGeeks
geeksforgeeks.org › java › how-to-execute-native-shell-commands-from-java-program
How to Execute Native Shell Commands from Java Program? - GeeksforGeeks
March 3, 2021 - For example, a Java program running specifically Linux shell commands cannot run as-is on a Windows machine mainly because Windows has a different folder structure and shell commands. ... The first three examples will look at implementing the ProcessBuilder class to run shell commands in Java.
Top answer
1 of 1
2

When the shell parses a command line, it removes quotes but remembers the text structure that they imply.  (That is a gross oversimplification; see bash(1) or Shell Command Language for more details.)  For example, the command-line input

-blah apple -secondfruit "green banana" -some more

causes the shell to identify six words, or tokens:

  1. -blah
  2. apple
  3. -secondfruit
  4. green banana
  5. -some
  6. more

which will be stored in memory as

-blahⓧappleⓧ-secondfruitⓧgreen bananaⓧ-someⓧmoreⓧ

where represents a null byte.  This will then sometimes be displayed or reported as

-blah apple -secondfruit green banana -some more

so you might believe that the quotes are just being ignored, and you have seven words, while, in fact, you have what you want.

Note:

In the above, represents a null byte.  What I'm describing here is standard shell argument-parsing processing.  If you type

ls -l fruit.sh "I came here for an argument" startScheduledTask.sh

the /bin/ls program gets invoked with the string

lsⓧ-lⓧfruit.shⓧI came here for an argumentⓧstartScheduledTask.shⓧ

in memory, and this gets interpreted as

  • argv[0] = ls
  • argv[1] = -l
  • argv[2] = fruit.sh
  • argv[3] = I came here for an argument
  • argv[4] = startScheduledTask.sh

This exact same process happens if you are

  1. typing a java command directly into your primary, interactive shell,
  2. executing a java command that is in a shell script, or
  3. running a shell script by typing a command like ./startScheduledTask.sh directly into your primary, interactive shell,

so this is not the problem.  Any program that cannot handle having its arguments separated by null characters cannot work in Unix & Linux.

TL;DR

Your first command is correct.  "$@" gives you what you want; it is the correct way for a shell script to pass its arguments to a program that it calls.  If you add debug code to your program to loop through its arguments, printing each one on a new line, and/or in brackets (but not all on one line, separated only by spaces), you will see that the "$@" is passing six arguments to the program.


OK, even more:

  • Your class path has asterisks (*s) in it?  Really?  I’m a little out of practice with Java, but that seems odd to me.  Please double-check that you’re doing that correctly for your system.  But, if it works correctly when you type the classpath with asterisks “directly” (i.e., directly into your main shell; your primary, interactive shell; your login shell), then that’s probably not the problem.

    But please humor me and put that string into quotes, anyway.

  • Your problem is too complicated.  When you’re building an airplane, you don’t build the entire plane and then try to fly it.  And then, when it doesn’t fly, you don’t step back and ask, “What’s wrong with the plane?”  No, you test it in pieces.  You need to simplify.

    • Stop running it in the background.
    • Stop saying nohup.
    • Stop redirecting the output.
    • Don’t show your 42-character long shell prompt in your question.
    • Your question is about an argument with spaces in it, so don’t take that out, but it doesn’t have to be 60 characters long with eight spaces.  green banana is a great test value.
    • Try it with arguments to your program not beginning with - (dash).
    • Maybe even comment out the new TaskRunner().run(args) part of your program, leaving only the DEBUG and System.exit(0);.

    None of these should make a difference.  But they are distractions that make it hard to see what’s important.  If you can demonstrate the problem in a minimal test configuration, we can rule out all those other things as being related to the problem.  But, if the problem goes away when you remove the irrelevant things, then one of them was probably causing the problem.

    Also, please stop mixing fake/test data and real data (i.e., fruits and tasks) in the question.

  • Please write this script (call it fruity.sh):

    #!/bin/sh
    
                    # classpath
    CP="/opt/fxudply/fxcal-client-jar/current/lib:/opt/fxudply/fxcal-client-jar/current/lib/*:/opt/fxudply/fxcal-config/current/wib-config:/opt/fxudply/fxcal-config/current/wib-config/*"
                    # package.name.classname
    PC=wib.runner.TaskRunner
    
    "$JAVA_HOME"/bin/java  -cp "$CP"  "$PC"  "$@"
    

    and run

    ./fruity.sh taskExtRef "green banana"
    

    If the debug says

    …[taskExtRef, green banana]
    

    then the "$@" is working correctly, and the problem lies elsewhere in your script.  Try to find it.  Make one change at a time and see how the behavior changes.  If you can’t figure it out, we may be able to help you, but only if you show us the part of the script that’s causing the problem. 

    But if the debug says

    …[taskExtRef, green, banana]
    

    then let us know.