-1

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 ?

dfa
  • 114,442
  • 31
  • 189
  • 228
sarah
  • 2,387
  • 13
  • 43
  • 50
  • 2
    I don't mean to be rude but, really, you should: 1. Take some time to format your questions, use proper capitalization and punctuation 2. Don't post X time the same question (see http://stackoverflow.com/questions/1893099/not-able-to-run-sh-file-using-java) 3. Learn how to ask "smart questions" 4. Read the FAQ. – Pascal Thivent Dec 12 '09 at 12:22

2 Answers2

1

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);
Community
  • 1
  • 1
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
0

I would read the .sh via ClassLoader.getResourceAsStream().

You then have two choices:

  1. Write it to a directory (perhaps /tmp ?), change the permissions and then execute it from there.
  2. (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.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440