So I trying to use Runtime.getRuntime().exec to execute a openview command from Java code. This exact command runs fine on command prompt on the server does the necessary updates, but fails to perform when executed through Java code. The issue is that it returns exit status code of success i,e "0" when invoked through Java, but doesn't performs the updates it is suppose to do (appears like it is not executing).
Here is the command :
opcmsg application='Tester Down 11' object='My Support' severity=minor msg_grp='MyGroup' msg_text='DEV: -m=New Details:Request Detail description'
Here is the code :
String[] command = {
"opcmsg",
"application=\'Tester Down 11\'",
"object=\'My Support\'",
"severity=minor",
"msg_grp=\'MyGroup\'",
"msg_text=\'DEV: -m=New Details:Request Detail description\'"
}
p = Runtime.getRuntime().exec(command);
InputStream stderr = p.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String errorDescription = null;
while ( (errorDescription = br.readLine()) != null)
LOGGER.info(errorDescription);
exitStatus = p.waitFor();
LOGGER.info("exitStatus : " + exitStatus);
This worked :
String[] command = { "/bin/sh",
"-c",
"opcmsg application=\'Tester Down 11\' object=\'My Support\' severity=minor msg_grp=\'MyGroup\' msg_text=\'DEV: -m=New Details:Request Detail description\' " }
Related
Java code
try {
String command = "/opt/compress.sh param1 param2 param3";
Process ps = Runtime.getRuntime().exec(command);
ps.waitFor(60 * 5, TimeUnit.SECONDS);
br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
result = sb.toString();
log.info("shell logļ¼\n" + result);
}finally {
br.close();
}
shell Code
#Other business codes
zip -m -jP $3 ${zipOutPath} ${fileIputPath}
The workflow engine calls jar packages to execute Java code, and the zip command in the shell often fails. Manually executing the JAR package on the server is normal.Zip compresses only a CSV file,the file size is 2G.Try to enable shell Debug, only get -> addling XXx. CSV (%)
You are not consuming output streams properly so this may lead to freeze, and waitFor must be after reading STDOUT. Try using ProcessBuilder instead and see what errors it reports, it may help you to the next step:
ProcessBuilder pb = new ProcessBuilder(cmd);
// No STDERR => merge to STDOUT (or redirect elsewhere)
pb.redirectErrorStream(true);
Process p = pb.start();
try(var merged = p.getInputStream()) {
merged.transferTo(System.out);
}
// Check the executable worked:
int rc = p.waitFor();
if (rc != 0)
throw new RuntimeException("failed: "+Arrays.toString(cmd));
I'm playing a bit around with a small JAVA gui for the command line mode of cloudcompare.
Therefore I'm using a short snippet like these:
var processBuilder = new ProcessBuilder();
try {
var process = processBuilder
.command("open", "-a", "CloudCompare.app", "-n",
"--args", "-NO_TIMESTAMP", "-C_EXPORT_FMT", "LAS",
"-O", "/Users/se/pcl_1.las",
"-O", "/Users/se/pcl_2.las",
"-MERGE_CLOUDS")
.start();
String error, line;
BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = inputStream.readLine()) != null) {
System.out.println("line = " + line);
}
BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((error = errorStream.readLine()) != null) {
System.out.println("error = " + error);
}
var ret = process.waitFor();
System.out.printf("Program exited with code: %d", ret);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
But if I run it on macOS the command line window opens, the process runs normal, but I can't grab any of the informations in it. There is an option to write log files from cloudcompare. That works - the log file shows that all cloud processing steps are done.
Does anybody knows, how to grab the command line output?
As mentioned here, the /usr/bin/open command is not an option to grab the stdinput stream.
I change the command to /Applications/CloudCompare.app/Contents/MacOS/CloudCompare and it works.
The next question is, how to grab the InputStream with a thread. I tried some stack overflow topics, but it doesn't work at the moment, to get the output stream in realtime. It is flushed at the end of the CloudCompare process.
How can I call a shell script through java code?
I have writtent the below code.
I am getting the process exit code as 127.
But it seems my shell script in unix machine is never called.
String scriptName = "/xyz/downloads/Report/Mail.sh";
String[] commands = {scriptName,emailid,subject,body};
Runtime rt = Runtime.getRuntime();
Process process = null;
try{
process = rt.exec(commands);
process.waitFor();
int x = process.exitValue();
System.out.println("exitCode "+x);
}catch(Exception e){
e.printStackTrace();
}
From this post here 127 Return code from $?
You get the error code if a command is not found within the PATH or the script has no +x mode.
You can have the code below to print out the exact output
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s= null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
BufferedReader stdOut = new BufferedReader(new InputStreamReader(process. getErrorStream()));
String s= null;
while ((s = stdOut.readLine()) != null) {
System.out.println(s);
}
If you are getting an exit code, then your script is executed. There is a command that you are running inside of "Mail.sh", which is not succeccfully executed and returning a status code of 127.
There could be some paths that are explicitly set in your shell, but is not available to the script, when executed outside of the shell.
Try this...
Check if you are able to run /xyz/downloads/Report/Mail.sh in a shell terminal. Fix the errors if you have any.
If there are no errors when you run this in a terminal, then try running the command using a shell in your java program.
String[] commands = {"/bin/sh", "-c", scriptName,emailid,subject,body};
(Check #John Muiruri's answer to get the complete output of your command. You can see where exactly your script is failing, if you add those lines of code)
I am executing grep command from java on a linux file. Its always returning null for the following code.
Process p;
String matchStr="testmatch";
String output = null;
try {
String command = "grep \""+matchStr+"\" "+ filename;
System.out.println("Running command: " + command);
p = Runtime.getRuntime().exec(command);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (br.readLine() != null) {
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println("in while loop");
System.out.println(output);
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
System.out.println("***********************************");
// Process your output here
}
System.out.println("exit: " + p.exitValue());
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
If i grep it directly it shows output but from java it never gets into while loop.
Please suggest whats wrong here.
The problem is that you do not write anything to output so it stays null. I guess you have to rewrite your while loop like this
while ((output = br.readLine()) != null) {
// Process your output here
}
Take a note that this syntax is discouraged by most style check due to it's abmiguity
Also it's a good idea to place p.waitFor() after while loop so grep would not hang on flushig std(err|out).
UPDATE
Also it is a good idea to use ProcessBuilder (available since java-7) instead of Runtime.getRuntime().exec(...) because you will have more control over the process i.e
final ProcessBuilder builder = new ProcessBuilder();
builder.command("grep", matchStr, filename);
// redirect stderr to stdout
builder.redirectErrorStream(true);
final Process process = builder.start();
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String output = null;
while ((output = br.readLine()) != null) {
System.out.println(output);
// Process your output here
}
process.waitFor();
After turning your code into a https://stackoverflow.com/help/mcve it works for me.
Here the file does not exist:
robert#habanero:~$ rm /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 2
Now the file does exist but does not contain the text to be found:
robert#habanero:~$ echo not found > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
exit: 1
Now the file exists and contains the text:
robert#habanero:~$ echo test this > /home/robert/greptest.txt
robert#habanero:~$ javac GrepTest.java && java GrepTest
Running command: grep test /home/robert/greptest.txt
test this
exit: 0
Here is the code:
import java.io.*;
public class GrepTest {
public static void main(String[] args) throws Exception {
String command = "grep test /home/robert/greptest.txt";
System.out.println("Running command: " + command);
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println("exit: " + p.exitValue());
p.destroy();
}
}
I was recently struggling with a similar issue, and I believe I the solution I found is an answer also to your problem (though your question is a bit malformed as others have pointed out).
The issue pertrains to the quote marks around your search string,
\""+matchStr+"\"
The java exec command will literally deliver these to the grep command, and instead of searching for matchStr, grep will be looking for "matchStr", and the results will not be what you are expecting.
This applies also in case one is executing the command as an array like
final Process process = Runtime.getRuntime().exec(new String[] { "grep", "-C1000", searchString, fileName } );
Pass the plain searchString without including quotation marks into the string.
I am trying to execute a bash script from Java with ProcessBuilder
my code is :
Process createUser = buildProcess(
"/bin/su",
"-c",
"\"/opt/somedir/testdir/current/bin/psql",
"--command",
commandForUserCreation,
/* "'select * from users'", */
"--dbname",
"mydbname\"",
"myuser"
);
The problem is that I receive error:
/bin/su: unrecognized option '--dbname'
If I put echo in first place of my commands it prints correct command in bash and if I copy/paste this command it works!
Please, help me to resolve this issue.
You need to supply the whole command to execute by su as a single argument. Try this:
Process createUser = buildProcess(
"/bin/su",
"-c",
"/opt/vmware/vpostgres/current/bin/psql --command " + commandForUserCreation + " --dbname mydbname",
myuser
);
This is what I use in processBuilder:
String[] command = new String[] {"echo", "Hello"};
String workspace = "/bin/su";
System.out.println("Trying to run command: "+ Arrays.toString(command));
ProcessBuilder probuilder = new ProcessBuilder(command);
probuilder.directory(new File(workspace));
Process process = probuilder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:\n",Arrays.toString(command));
while ((line = br.readLine()) != null) {
System.out.println(line);
}
I hope it helps.