i have a Java program which executes the following shell script to restart it self.
sleep 5
nohup java -jar /home/my-dir/MyJar.jar &
If i run the script from a terminal, it just works as expected. However if the Java Program executes the script, the program starts normally but nothing gets written to the output file.
I start the script via the following code
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("/bin/sh", "/home/my-dir/start.sh");
try {
processBuilder.start();
logger.info("Successfully started");
} catch (IOException e) {
e.printStackTrace();
}
Following command worked for me. It writes all the output to the specified file.
nohup java -jar /home/my-dir/MyJar.jar > /home/my-dir/log.txt & tail -f /home/my-dir/log.txt &
Related
I was trying to execute shell scripts using java code. The following is a sample code to demonstrate the issue :
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("/home/otaku/Programming/data/test1.sh");
try {
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println(output);
} else {
System.out.println("Script exited abnormally");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
The shell script file test1.sh that I am trying to execute :
#!/bin/bash
mkdir -p -- teeh
echo 'Succesfully executed script'
I am getting echo message and was able to print in the java console indicating that the shell script is executed successfully. But no directory is being created even though the command mkdir -p -- teeh is executed. If I manually execute the script file using terminal it works like a charm. I would like to know the reason behind this and a possible solution to this as well.
mkdir -p -- teeh
In this command the teeh path is a relative one rather than an absolute one: it will be created in the script's current working directory.
Your bash script is by default executed with the working directory of your JVM, which depends on where you executed your java application from. If you're executing your code from your IDE, by default this will be the project's root directory. If you're executing from the command line, it will be the directory you execute the java command from.
In any case you shouldn't expect a /home/otaku/Programming/data/teeh directory to be created by your current code unless you run the java application from the /home/otaku/Programming/data/ directory.
There are many possible solutions, whose relevance depend on your context :
execute your java code from the /home/otaku/Programming/data/ directory
use an absolute path in your bash script
use cd in your bash script
use ProcessBuilder.directory(File dir) to execute the bash script with the appropriate working directory
I wrote a bash script. As an example, a really easy on:
#!/bin/bash
gnuplot -e "set terminal pdf; set output'/tmp/test.pdf'; plot [-10:10] sin(x);"
This script shall have the name test.sh .
I can execute this script through my shell and the test.pdf is created. Should I execute this script through a Java application that calls this script through a ProcessBuilder, no pdf is created. The script is accessed and other programs like gedit are opened. Awk etc works. There just seems to be a problem with gnuplot.
Does anyone know why that is and how I could fix this?
The java code is:
String command = "/tmp/test.sh";
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c",command);
pb.start();
}catch (IOExeption e1) {
e1.printStackTrace()
}
--- Update ---
There seems to be another issue. Thanks to ccarton and muzido the gnuplot script is executed if the java-jar file is executed through the shell. If I embed it into another shell that looks simplified like this execute_jar.sh:
#!/bin/bash
java -jar test.jar
And this execute_jar.sh is executed by another java application that only can execute shell scripts and that I can't modify.
Is there a problem with this parent application? Or is a workaround possible?
The gnuplot script has to be executed through my test.jar because other parameters are generated in the jar and given to the script.
--- Update 2 ---
So I have been searching some more and to test a little bit I changed the test.jar so that it doesn't execute the test.sh but just opens a shell with "xterm". Here I then manually type in the script and I get the error "gnuplot: symbol lookup error: /usr/lib64/libQtSvg.so.4: undefined symbol"
Any ideas?
--- Update 3 ---
I tought it my be a Library problem because the "/usr/lib64/libQtSvg.so.4" exists. So I tried export LD_LIBRARY:$LD_LIBRARY:/usr/lib64 but still the same error.
--- Update 4 ---
I changed the title
add to " end of line.
#!/bin/bash
gnuplot -e "set terminal pdf; set output'/tmp/test.pdf'; plot [-10:10] sin(x);"
to executable file;
chmod +x /tmp/test.sh
this is java code; when run this, test.pdf is created in /tmp/.
public class RunShellScript
{
public static void main(String[] args)
{
String command = "/tmp/test.sh";
try{
ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c",command);
Process p = pb.start();
p.waitFor();
int shellExitStatus = p.exitValue();
System.out.println(shellExitStatus);
}catch(Exception e){
e.printStackTrace();
}
}
}
when run this, what is the java console output?
Scripts are not actually executables. The shebang (#!) is interpreted by your command shell. ProcessBuilder won't do that. To run this from Java you need to execute /bin/bash directly and pass this script as a command line argument.
Example:
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "test.sh");
I am creating a server/client application, where the client can send system commands.
// Server Side
// command can be *nix/Windows system commands
public void run() {
while(true) {
try {
Runtime.getRuntime().exec(command);
} catch (Exception e) {e.printStackTrace();}
}
}
command is sent from client, and by executing it, in console it wont execute the command but just print it. So if command = "echo Hello", output in console(server side) will be echo Hello instead of just Hello.
Which method should I use to execute system command ?
cmd /C echo hello
echo is not a known/normal Windows executables but a cmd.exe input command.
One way to do this could be dump the client sent commands to a temp file (assuming) Linux like /tmp/some_cmds.sh and use bash to execute it e.g./usr/bin/sh /tmp/some_cmds.sh. Then use java ProcessBuilder API to execute the shell with argument as temp file. You can redirect the stdout and stderr to appropriate files and then send it back to the client as command output.
NOTE: This method is not portable across OS and it is dangerous too as hackers can potentially run arbitrary cmds from the client on your server.
I have tried running a shell script from a Java program, but the entire script is not being executed. And idea why we might come across such problem?
The Java code to execute shell script:
File file = new File("/path/to/script");
String COMMAND= "./run";
ProcessBuilder p = new ProcessBuilder(COMMAND);
p.directory(file);
try {
Process startProcess= p.start();
} catch (IOException e) {
e.printStackTrace();
}
The script runs fine but not whole script is executed. It seems like only the 1st line is being executed.
If you are sure that the script starts running the problem is not in java but in script itself.
The reason of difference may be the wrong path or wrong environments. When you are running script from console you are in your user's environment, so script can use all environment variables.
Try to add some debug outputs to figure the problem out.
I have a python script that runs on windows and uses win32 extensions and WMI to get some information. If I run the script using the command line, it executes perfectly. But, if I try to run the same script using java Runtime.exec("python myscript.py") it seems to get blocked on the waitFor(). The code is like this:
Process p = Runtime.getRuntime().exec("python myscript.py");
int exitCode = p.waitFor();
If I try to use this same java code with some very simple python script like
print "hello world"
I get the exitCode to be 0, which means it works. Can I execute a python script that imports WMI library, using java Runtime.exec()?
Thanks
One likely reason is that your IO buffers are full and need to be flushed, so try flushing both stdout and stderr from your Process in the java code (example code).
Alternatively, you could try redirecting all output to NUL or a text file with one of the following arguments to exec:
cmd.exe /c python myscript.py > NUL 2>&1
cmd.exe /c python myscript.py > output.txt 2>&1