I am running a java program using a Jar file. Inside this packaged jar file I have my shell script. I understand that the best way to access the file would be through getResourcesAsStream because I can't access it via regular directory structures. So this is what I'm using:
InputStream input = this.getClass().getResourceAsStream("/script/sample_script.sh");
However, The only way I know how to execute this is if I go through the script line by line using a loop and bufferReader. I Statements like "If" or "While" loops get me an error. Is there a way to input the stream to achieve the desired results.
Here is my current code:
InputStream input = this.getClass().getResourceAsStream("/script/sample_script.sh");
BufferedReader brCmd = new BufferedReader(new InputStreamReader(input));
String cmd;
while ((cmd = brCmd.readLine()) != null){
proc = Runtime.getRuntime().exec(cmd);
proc.waitFor();
}
I've tried concatenating the whole file line by line to a string and using that but it doesn't seem to work. How can I get to make my script file run using inputStream? Any help would be appreciated
You could read the script file through InputStream and write it to a temp file under the system temp directory, and execute this file in following way:Runtime.getRuntime.exec("/bin/sh " + tempFilePath);
About reason to rewrite the script file to another temp file, you said you are executing your program by run the jar file directly, thus the script file is packed into the jar file and java won't unpack the jar file to the file system. To let the script file be accessible to cmd.exe, we need to rewrite the script file manually.
By the way, you could get the system temp directory path from system properties, or using apache common.io: FileUtils.getTempDirectory().
Related
I have been working on java app that uses python script to run some 3d visualization, it worked when I was running it from intellij but once I created jar file it just doesn't run. OS: MAC OS
How I run script:
Process p1 = Runtime.getRuntime().exec("python3 vizualize3D.py");
The problem had multiple layers and solutions:
1. I didn't put .py file in jar build config
2. After putting it I always got an exception that it is null because of a typo in code
3. After trying many ways to run it this one worked Cannot run python script from java jar
. The important thing is to check if you added py file to the build config and to run it in a proper way since python cannot runt files from the zip and compressed states.
Assuming the script is in the jar file, you can get an input stream from the resource, and use it as the input to a Process created from the python interpreter:
// Note: the path to the script here is relative to the current class
// and follows strict resource name rules, since this is in a jar file
InputStream script = getClass().getResourceAsStream("visualize3D.py");
// The following creates a process to run python3.
// This assumes python3 is on the system path. Provide the full
// path to the python3 interpreter (e.g. /usr/bin/python3) if it's
// not on the path.
// The - option to python3 instructs it to execute a script provided
// as standard input.
Process process = new ProcessBuilder("python3", "-")
.start() ;
OutputStream out = process.getOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
while((read = script.read(buffer)) != -1) {
pos.write(buffer, 0, read);
}
script.close();
For details on getting the correct path for the script, see How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?
I tried to run the batch file from java code, bat file is running but in bat file internally it is calling proxyServer.js file.This .js file is not running.
Below is the sample code.
try {
String path="cmd /c start C:\\AxoneES_Viewers_Integration-2016Q3-SNAPSHOT_201609021003\\AxoneViewers.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
} catch(IOException ex) {
System.out.println("Exception Found");
}
As i mentioned internally it is calling .js file where they declared path of the .js file, below is the code , which declared the path.
cd viewers\apps\maxq\
node proxyServer.js
while running the bat file it is not able to find the path of .js file and it not running.
Can you help me is there any approach to execute the bat file from java.
Try editing the batch file to use absolute file names instead of relative file names. You mentioned your batch file has the lines
cd viewers\apps\maxq\
node proxyServer.js
Change the first line to something like C:\full\path\to\viewers\apps\maxq\. Check out this answer for the difference between absolute and relative file names.
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().
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Run Java program into another Program
i try to run jar file from java application which was created in eclipse.
when i run jar file using below source code then fire Unable to access jarfile error
Process process = run.exec("java -jar TestJava.jar");
InputStream inError = process.getErrorStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inError));
System.out.println("Error=" + bufferedReader.readLine());
Sounds like TestJava.jar is in a different directory. If you're running this code within Eclipse, then the present working directory is going to be the same as your Eclipse project's folder (unless you've configured it differently, this is Eclipse's default run location). Either specify a path to TestJava.jar via an absolute path or a path relative to the present working directory.
One other thing you'll need to be mindful of - you need to consume both the error stream and the output stream of the Process you're creating. The default output/error stream buffer sizes of Process instances are not very big and, if full, will cause that Process to block indefinitely for more buffer space. I recommend consuming each stream in a separate Thread.
Set the working directory where this process should run. Set the working directory using the below statement.
Runtime.getRuntime().exec(command, null, new File("path_to_directory"));
First try the java -jar command on cmd window and see if you can run TestJava.jar. Then try running the same command from your code.
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("java -jar TestJava.jar");
System.exit(0);
You need to supply the full path to the Java command.
For example, under windows you'd need something like
C:/Program Files/java/jre/bin/java.exe
ProcessBuilder & Runtime.exec don't take the system path into account when trying to execute your command
I have a .sh file i am creating a war file wheter in the classes are under web-inf/classes/test/test.class .i am accessing .sh file from test class using the following syntax
string cmd="./test.sh"
runtime api
i am not able to access this file if i place it under web-inf/classes .i want to know where can i place .s file in war to access the path from test.class as ./test.sh ?
According to your comment in the other question, you are using the following code to call your script:
Process p = Runtime.getRuntime().exec(cmd);
As explained in the javadoc, this is equivalent to the invocation of exec(command, null, null) which behaves in exactly the same way as the invocation exec(cmdarray, envp, dir). Now, if we look at the javadoc of exec(String[] cmdarray, String[] envp, File dir), we can read:
The working directory of the new subprocess is specified by dir. If dir is null, the subprocess inherits the current working directory of the current process.
In other words, in your case, your script test.sh is expected to be located in the working directory of your application server, i.e. the location in the file system from where the java command was invoked (which is certainly not WEB-INF/classes). This directory is set in the user.dir system property that you can read as follow:
String cwd = System.getProperty("user.dir")
Also note that you can't change the working directory. Actually, you should theoretically write your code so it does not depend on the current working directory for portability (even if this doesn't really matter in your case as using the Runtime API makes your code not really portable anyway).
To summarize, you have several options (none of them is really portable as I said but the last one is "less worse"):
Put the hello.sh script in the working directory of the app server.
Put it somewhere else and point on it relatively to the working directory (./path/to/hello.sh).
Put it somewhere else and point on it with an absolute path (/path/to/hello.sh).
Put it somewhere else and use the dir parameter when invoking exec().
Put it in the WAR and read it using getResourceAsStream(), write it in the tmp dir, make it executable and exec() it as suggested by Brian.
In my opinion, the last option is the (only) way to go and can be implemented like this (assuming the script is in the same package as your class i.e. WEB-INF/classes/test/hello.sh):
InputStream is = this.getClass().getResourceAsStream("hello.sh");
String[] cmd = null;
File tempFile = null;
tempFile = File.createTempFile("hello", "sh");
// extract the embedded hello.sh file from the war and save it to above file
OutputStream os = new FileOutputStream(tempFile);
byte[] buffer = new byte[1024];
int bytes;
while( (bytes = is.read(buffer)) != -1) {
os.write(buffer, 0, bytes);
}
os.close();
tempFile.setExecutable(true);
cmd = new String[] { tempFile.getAbsolutePath() };
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(cmd);
I would read the .sh via ClassLoader.getResourceAsStream().
You then have two choices:
Write it to a directory (perhaps /tmp ?), change the permissions and then execute it from there.
(a little more involved). Execute a /bin/bash via Runtime.exec() and then pipe the script in via stdin.
You won't be able to execute the script directly from the .war structure.