jonnie
jonnie

Reputation: 12680

Pass a string with spaces to an execute command in Java to execute a bash script

How do I pass a string with spaces to an execute command in Java to execute a bash script?

I'm trying to use a script to generate and send a email using the unix mail command but it ignores the quotes surrounding the message string:

#!/bin/bash

######################################################
#
# Params:
# 1) Email recipient
# 2) Subject line (in quotes)
# 3) Message (in quotes)
#
# Returns:
# 0 if success, else non-zero
#####################################################

MAIL_TO=$1
SUBJECT_LINE=$2
MESSAGE=$3

echo "Mail To= ${MAIL_TO}" >> /logs/terminalLog.txt
echo "Subject= ${SUBJECT_LINE}" >> /logs/terminalLog.txt
echo "Message= ${MESSAGE}" >> /logs/terminalLog.txt
echo "" >> /logs/terminalLog.txt

echo "$MESSAGE" | mail -s "$SUBJECT_LINE" $MAIL_TO >> /logs/terminalLog.txt

and this is how I'm calling it in java :

Process proc = Runtime.getRuntime().exec(scriptName+" [email protected] \"My Test Subject Line\" \"This is the test message!!\"");

The problem is it takes "My as the subject argument and Test as the message argument and ignores the rest.

I have tried using single quotes, exec(command, args) where

args = {"[email protected]","My Test Subject Line","This is the test message!!" } 

but still has the same result.

I have searched here and online but most people seem to suggests what I have tried and while it worked for them, it did not for me.

Update

On the Advice of a number of comments/Answers I have changed from using the exec to

ProcessBuilder pb = new ProcessBuilder(scriptName, "[email protected]","My Test Subject Line", "This is the test message!!");
pb.start();

I now successfull get the correct Arguments as shown by the output to log BUT I never recieve the email. If I call the script via the terminal manually I do recieve the email

Upvotes: 0

Views: 3757

Answers (3)

jonnie
jonnie

Reputation: 12680

This was actually solved by changing:

String command =    scriptName+" "+mailTo+" "+"\""+subject+"\""+" "+"\"" + message + "\"";
Runtime rtime = Runtime.getRuntime();
Process proc = rtime.exec(command.toString());
int retCode = proc.waitFor();           

To:

 Runtime rtime = Runtime.getRuntime();
 Process proc = rtime.exec(new String[] {this.scriptName, mailTo, subject, message} );
 int retCode = proc.waitFor();

I had also Perviously tried passing an array of strings args = {this.scriptName, mailTo, subject, message} but for some reason it did not like this

Upvotes: 2

Aaron Digulla
Aaron Digulla

Reputation: 328556

Don't use Runtime.exec(), always use ProcessBuilder which allows you to pass arguments as an array or a collection of Strings.

And for better error handling, you should really use the Java Mail API and a logging framework like slf4j.

If you're unsure how to use ProcessBuilder and I/O between processes, you should better use Commons Exec which solves many of the common problems like handing the three I/O streams correctly.

Upvotes: 1

VGR
VGR

Reputation: 44293

As others have mentioned, use ProcessBuilder. However, just starting the process isn't enough; you must consume its output, and you may or may not want to wait for it to complete. For example:

ProcessBuilder pb = new ProcessBuilder(scriptName, "[email protected]","My Test Subject Line", "This is the test message!!");
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.start();

int returnCode = pb.waitFor();
if (returnCode != 0) {
    throw new IOException("Command failed with code " + returnCode);
}

It isn't just the process invocation that needs to quote spaces. I'm pretty sure you need quotes in your script:

SUBJECT_LINE="$2"
MESSAGE="$3"

Upvotes: 1

Related Questions