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.
Related
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().
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 am using a .jar file, but unfortunatley as a black box, i.e. I do not know what exactly is in there nor how it all works.
I am sending commands to the Mac terminal from a Python script. I enter the following command:
java -jar jarfile.jar req_data /abs_path/to/required/data input path/to_my_/input/file.txt
This does what I need: analyses input using the 'black box' and creates and new file with analysis output. This new file is created in the folder where jarfile.jar is located.
I want to have this file put somewhere else upon creation.
I have tried using the > operator, specifying a path, e.g.:
java -jar jarfile.jar req_data /abs_path/to/required/data input path/to_my_/input/file.txt > /output/path/
this created a file in my desired location, but it was simply the message from Terminal, saying "The operation was carried out successfully" - the analysis results file was created in the same folder as before.
I tried %*> too, but it threw an error.
As a poor workaround I now have a function, which retrospectively finds and moves all the newly created files (analysis output) to my desired folder.
Is there a way to control the output files with the command line within the original command? Or is it something that is specified somewhere in my jar file? My problem is that editing it is not allowed.
I'm new to python. However, I may suggest to try few things, if they can work for you. Apology me, if does not work! I believe that you have already done the following step:
import subprocess
subprocess.call(['java', '-jar', 'Blender.jar'])
Like, if you have a properly configured jar path, then can run jar directly.
Secondly, look at the cwd parameter (is used for executable). Include a cwd param as x
def run_command(command, **x):
with subprocess.Popen(command,...., **x) as p:
for run_command specify the path of either the working directory (possibly it should be) or the full system path. I'm not sure, just try both.
for outputline in run_command(r'java -jar jarfilepath', cwd=r'workingdirpath', universal_newlines=True):
print(outputline, end='')
Alternatively, you can try to run command from the directory in which you wish to store output file. Try: run the popen as
subprocess.Popen(r'directory of running command', cwd=r'workingdir')
where workingdir could be your current directory path.
If it does not work, try without r'. If still does not work, try doubling slash in the path like (C:\\ abc\\def)
I want to run some unix/shell commands in Java and process the output. I used getRuntime.exec(), but it is not giving correct output for some commands like ls directory_path/*.tar.gz . For that command my program is not giving any output but it is giving error saying No such file or directory. But the same command is giving correct output on command prompt.
Is there any other way to execute commands which include wildcards in Java?
Is there any other way to execute commands which include wildcards in Java?
Yes there is.
You have three potential problems in your code:
Assuming you want to see the output of the external command you need to take care of the output it produces, and print it yourself.
Follow the example I've provided over here:
How to make a java program to print both out.println() and err.println() statements?
The shell expansion of * doesn't work if you naively go through Runtime.exec.You have to go through /bin/bash explicitly.
If you try to list the content of directory_path/*.tar.gz you should know that (if you're not starting with a /) directory_path will be resolved relative to the current working directory. Try at first to give the absolute path to make sure it works, and then try to figure out why it can't find the relative path.
Here's a complete example that should work:
Process proc = new ProcessBuilder("/bin/bash", "-c",
"ls /.../directory_path/*.tar.gz").start();
Reader reader = new InputStreamReader(proc.getInputStream());
int ch;
while ((ch = reader.read()) != -1)
System.out.print((char) ch);
reader.close();
That is because you specified a relative path to the directory and your application is running in a working directory. The path you specified is relative to that working directory.
To find out what the absolute path is, you can check out the working directory.
System.out.println("Working directory: " + System.getProperty("user.dir"));
"ls directory_path/*.tar.gz" works relative to CURRENT directory.
I have a specific need to unrar files found in different subdirectories during execution of my program on Os x. I do this by calling the freeware command line tool unrar, which works very well.
However, unrar will always unrar files in the current working directory, which means that I have to specify a working directory for the executed process or get every unpacked file in my .jar home folder.
This is easy enough to do using either the processBuilder.directory(dir) or runTime.getRuntime().exec(args,null,dir) for example where dir is a File.
This works excellent but not when the working directory contains a space. As a short example:
File dir=new File("/Users/chargedPeptide/rar 2");
String[] cmd = { "/Users/chargedPeptide/rar/unrar", "e", "-o+","/Users/chargedPeptide/rar", "2/weather.rar"};
Process pr = Runtime.getRuntime().exec(cmd,null,dir);
int exitValue=pr.waitFor();
Will not work, while using: Process pr = Runtime.getRuntime().exec(cmd); instead will launch the command successfully but leave me with all of the files in the jars working directory.
Using processbuilder instead and using processbuilder.directory(dir); to set the directory
exits with the message:
Exception: Cannot run program "/Users/chargedPeptide/rar/unrar" (in directory "/Users/chargedPeptide/rar 2"): error=2, No such file or directory
Help? How do I handle the spaces? I've tried adding backslashes before the spaces to make them literal no help since the File object treats them like actual part of the path.
Edit: To make the whole thing a bit more clear:
1. I have a separate method that feeds the execute method a command and a directory to processbuilder, all directories are found by the previous method and exist. This works except when the dir contains a space.
2.I need to set the working dir or the command will execute in the wrong place.
3.Parsing the file object by:
dir=new File(dir.tostring.replace(" ","\ ");
to put a backslash in front of all spaces does not work since the java File object then looks for a path containing actual backslashes. No luck.
4.Using rt.exec instead of processbuilder dosen't help either.
Any ideas most welcome.
How about:
dir.mkdirs();
before launching the process.
This creates the missing directory.
Edit:
This looks strange.
String[] cmd = { "/Users/chargedPeptide/rar/unrar", "e", "-o+","/Users/chargedPeptide/rar", "2/weather.rar"};
If this was a shell you'd write:
unrar e -o+ "/Users/chargedPeptide/rar 2/weather.rar"
You actually have to put the .rar file in quotes, since otherwise it will be interpreted as 2 arguments to the process.
The way you've split 'cmd' will do exactly that, break the rar argument in two. Try:
String[] cmd = { "/Users/chargedPeptide/rar/unrar", "e", "-o+","/Users/chargedPeptide/rar 2/weather.rar"};
Not sure if it will work, but can you try putting a / at the end of the path.
i.e.,
File dir=new File("/Users/chargedPeptide/rar 2/");