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");
Related
shell script file directory: /some/location/myShellScript.sh
Properties-Type: shell script (application/x-shellscript)
EDIT
content of shell script:
#!/bin/bash
export LD_LIBRARY_PATH=`pwd`
echo `pwd`
./someExecutable ../input/cfg/test1.ini
The test1.ini is generated one step before in the java code,
it provides settings for some testing, which is done in the background. Then the shell script ends up with the file I need for further processing.
/EDIT
When I am running this shell script on linux terminal in its own directory just with "./myShellScript.sh" it works perfectly fine...
The part my shell script shall be executed:
//Do something before
//Shell scripts creates a file
String cmd = /some/location/myShellScript.sh;
ProcessBuilder pb = new ProcessBuilder(cmd);
Process process = pb.start();
int exitValue = process.waitFor();
System.out.println(exitValue);
//Afterwards I am processing the generated file
When running my java program as an executable .jar file, this process gets not executed and the exitValue is 127, but I don't know why...
I tried many things like:
using the Runtime to exec
adding #!/bin/bash or #!/bin/sh on top of the shell script
adding a "sh" parameter to the process command in form of String[]
In my execution directory, I changed the permission with chmod 755 -R * recursively so every associated library used by the shell script is indeed available (also due to the fact, that I can just execute it on the terminal).
I really tried to find a proper answer on the internet but I wasn't successful.
And no, I cannot just do everything in java, the shell script is mandatory and cannot be replaced in this case.
Thanks in advance for helpful suggestions!
The script you are executing is highly sensitive to its working directory. It uses pwd to set the LD_LIBRARY_PATH and it attempts to execute another program via a relative path to that program, providing a relative path as a command-line argument, as well.
The working directory for an execution of the script has no essential relationship with the directory in which the script resides -- it completely depends on how and in what context the script is launched. For example, you report that the script works as you expect "When I am running this shell script [...] in its own directory." But when you run the script from Java you very likely are not running it with its own directory as the working directory, and that will strongly affect this script's behavior.
One solution would be to hardcode the script's installation path into the script itself, and to express all your paths relative to that:
#!/bin/bash
installation_dir=/path/to/the/script/dir
export LD_LIBRARY_PATH=$installation_dir
"$installation_dir"/someExecutable "$installation_dir"/../input/cfg/test1.ini
It's a bit kludgy to hardcode the path, though. You could further improve it by having the script identify its own directory at runtime:
#!/bin/bash
installation_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
export LD_LIBRARY_PATH=$installation_dir
"$installation_dir"/someExecutable "$installation_dir"/../input/cfg/test1.ini
That's obviously Bash-specific, but you were using bash anyway. Alternatively, if the executable your script launches is also sensitive to its working directory, then perhaps you just want the script to change directory (which will be effective only for the script and processes downstream from it, not for its parent process):
#!/bin/bash
cd "$( dirname "${BASH_SOURCE[0]}" )"
export LD_LIBRARY_PATH=`pwd`
./someExecutable ../input/cfg/test1.ini
The 127 exit status means that a command used in the script is not found.
EDIT
Debug the script, when bash is used, add the line below on the second line:
exec > /tmp/debug.txt 2>&1 ; set -x
After the next attempt, analyze the traces generated into the /tmp/debug.txt file.
OLD INTRO
(the script content was not yet provided)
The Java program which executes the myShellScript.sh script has probably not the same PATH environment variable than the one which is set in your environment when you execute the script manually from a terminal.
For vhdl beautifier, I am using Emacs and in Linux I am using the command in terminal:
emacs --batch --visit=FILENAME.vhd --funcall=vhdl-beautify-buffer --funcall=save-buffer
And this working fine, however when trying to call this command within a java file as below not working! :
String command = "emacs --batch --visit=FILENAME.vhd --funcall=vhdl-beautify-buffer --funcall=save-buffer";
Process p = Runtime.getRuntime().exec(command);
what can be causes for that?
I have this easiest bash script
arr=('one' 'two' 'three' 'four');
echo "${arr[#]:2}" > test.txt
(in fact i want to used ${#:2})
If I run this script in command line with ./my_script.sh, it work as expected. But when I try to use a java ProcessBuilder, the test.txt file is never created. (in fact the bash script stop the execution at the slice).
ProcessBuilder pb = new ProcessBuilder("./my_script.sh");
pb.start();
i tried with a lot of other command in my bash script and everything work fine with processBuilder, all exept the "${#:2}".
for exemple this script work fine and create test.txt in my project directory
echo "test" > test.txt
Someone know why?
I have written a shell script file which extracts the files, Please see below.
File Name: unzip.sh
#/bin/sh
cd /home/zip;
UNZIPDIR=/home/unzip/;
for i in *.zip; do
unzip "$i" -d "$UNZIPDIR"
rm "$i";
done;
This shell script executes sucessfuly on putty,
$> ./zip.sh
As i wanted to execute this script from my java class while i have tried several ways to invoke/execute the shell script file but it's not executing. Please see below java code.
//First try
File executorDirectory = new File("/home/zip");
ProcessBuilder processBuilder = new ProcessBuilder("./unzip.sh");
processBuilder.directory(executorDirectory);
Process p = processBuilder.start();
p.waitFor()
//Second try
Process p = Runtime.getRuntime().exec("/home/zip/unzip.sh");
The problem is that you fail to account for the process' standard output/error (as mentioned by #Yazan in the comments). You need to .get{Output,Error}Stream() from the created process and read from them (even if it is only to discard it).
The real problem however is that you use an external shell script for something which is entirely doable in Java itself. See this page which gives an example of how to extract a zip file entirely with Java code; to delete a file, use Files.delete().
I'm trying to run this command:
"C:\arduino\arduino --upload --board arduino:avr:nano --port COM3 -v ..\config\config.ino"
It works from my command line. It takes just a few seconds to run & finish.
The problem comes when I try to execute it from Java with:
String cmd = "C:\arduino\arduino --upload --board arduino:avr:nano --port COM3 -v ..\config\config.ino"
Process p = Runtime.getRuntime().exec(cmd);
It takes a minute to execute and ends with:
Launch 4j: an error occurred while starting the application
I've tried with ProcessBuilder too. I've also tried saving the command to a batch file and then running the batch file from Java...but I just got the same result.
EDIT:
If I run the batch file from command line it works too. As I said if I run it from Java, it doesn't.
I've realized that if I run the batch file from another batch file it doesn't work neither.
Maybe there is not a problem at all with Java, but with Arduino IDE.
EDIT 2:
Adding "start" parameter before the command and saving it to a batch file seems to work. Then you just run the batch from java.
Something like this:
arduino.bat
"start C:\arduino\arduino --upload --board arduino:avr:nano --port COM3 -v ..\config\config.ino"
Java code
String s = "PATH TO ARDUINO.BAT"
Process p = null;
ProcessBuilder pb = new ProcessBuilder(s + "arduino.bat");
pb.directory(new File(s));
p = pb.start();
I think the issue is with the relative path at -v argument. Use full path or set
actual working directory with ProcessBuilder.