Link to home
Start Free TrialLog in
Avatar of MehtaJasmin
MehtaJasminFlag for United States of America

asked on

Runtime.getRuntime().exec() is not working for "chmod" or even simple "ls" for IBM JRE

$java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build pap3260sr10-20111208_01(SR10))
IBM J9 VM (build 2.4, JRE 1.6.0 IBM J9 2.4 AIX ppc-32 jvmap3260sr10-20111207_96808 (JIT enabled, AOT enabled)


I want to change permission of some files using Java code. If I type in the command, it works fine but when the same command is executed using Runtime.getRuntime().exec(), its not working. What am I doing wrong?

This is my several trials:

Runtime.getRuntime().exec("chmod go+rw /sybwork/CURRENT/*.RSA");
Runtime.getRuntime().exec(new String[]{"/bin/ksh","-c","ls -l *.RSA"});

Even in windows:

Runtime.getRuntime().exec("cmd.exe /c dir");

does not list directory.

Please help me resolve this.

Thanks
Avatar of for_yan
for_yan
Flag of United States of America image

One thing - make sure that you are running java under the same privileges as you run command line direcly (uaully from the same prompt should be OK)

First try direct commads - there amy be some issues when you first start additional she'll like with "cmd..exe /c dir"

First try just "dir"

and also make sure you capture the output stream from java- how would you know that it works?



The same from Unix - try direct command -
why this does not work is strange:
Runtime.getRuntime().exec("chmod go+rw /sybwork/CURRENT/*.RSA");
maybe the privileeges issue

when you start another shell  within - it may be more tricky
Avatar of CEHJ
Try

http://technojeeves.com/joomla/index.php/free/52-runtimeexec

You need to capture stdout AND stderr
For the simplest examnple which must work open notepad.exe in windows
try {
            Process p = Runtime.getRuntime()
                               .exec(new String[] {
                        "/bin/bash", "-c", "ls -l *.RSA"
                    });
            IOUtils.outputProcessStreams(p);
            int exitValue = p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }

Open in new window


is the usage for your Unix command
Avatar of MehtaJasmin

ASKER

My Unix is not bash, its ksh so I changed the command to


 Process p = Runtime.getRuntime()
                               .exec(new String[] {
                        "/bin/ksh", "-c", "ls -l *.RSA"
                    });

and it did list the files..

So now I am back to my original problem of changing the permission.

Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", "/sybwork/CURRENT/*.RSA"});

For which the output is now displayed:

/bin/ksh: /sybwork/POLLFILES/L_STS/PROCESSED/LOSSP/CURRENT/TLOG_0028.000000.011312.ORPOS.001.RSA: 0403-006 Execute permission denied.
126
well you don't have permission to do chmod  - the permission are of the time when you starteted your java code
ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you so much CEHJ.

I got all working after setting my code:
{......
String chmodRunCmdStr = "chmod ugo=rwx /sybwork/CURRENT/*.RSA";
Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", chmodRunCmdStr});

outputProcessStreams(p);
int exitValue = p.waitFor();
System.out.println(exitValue);
..........}

public static void outputProcessStreams(final Process p) {
        Thread runStdout = new Thread() {
            public void run() {
                copyStream(p.getInputStream(), System.out);
            }
        };

        runStdout.start();

        Thread runStderr = new Thread() {
            public void run() {
                copyStream(p.getErrorStream(), System.err);
            }
        };

        runStderr.start();
    }
      /**
     * Copy a stream
     *
     * @param in The source stream
     * @param out The target stream
     */
    public static void copyStream(InputStream in, OutputStream out) {

      try {
          byte[] buffer = new byte[DEFAULT_READ_BUFFER_SIZE];
          int bytesRead = -1;

          while ((bytesRead = in.read(buffer)) > -1) {
            out.write(buffer, 0, bytesRead);
          }
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          try {
            in.close();
          } catch (IOException e) {
            /* ignore */
          }

          try {
            out.close();
          } catch (IOException e) {
            /* ignore */
          }
      }
Good :) For your 'real' code, look at collectProcessStreams
CEHJ,

I used collectProcessStreams instead of  outputProcessStreams, thinking that I can store the output and display the when I need. I am purposely trying to chmod on file extension that does not exist in the directory:

like:
chmod ugo=rwx /sybwork/CURRENT/*.RSA1

Open in new window

where I don't have any files with 'RSA1' extension.

Here is the code:

StringBuilder strErr = new StringBuilder(256);
StringBuilder strOut = new StringBuilder(256);
try
 {			
  Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", chmodRunCmdStr});
//EncryptDecryptUtils.outputProcessStreams(p);	
  EncryptDecryptUtils.collectProcessStreams(p, strErr, strOut);			
  int exitValue = p.waitFor();
  System.out.println(exitValue);
} catch (Exception e) {
	e.printStackTrace();
}
finally
{
  System.out.println("StrErr: " + strErr.toString() + ":");
  System.out.println("StrOut: " + strOut.toString() + ":");
}

Open in new window


But after execution, the screen is as below, I was expecting the message between StrErr or StrOut:

chmod: /sybwork/CURRENT/*.RSA1: A file or directory in the path name does not exist.
1
StrErr: :
StrOut: :
Are you sure that's the exact code you're using?
Yes I am. What should I expect as a result from the code that I wrote otherwise?
chmod: /sybwork/CURRENT/*.RSA1: A file or directory in the path name does not exist.

I'm interested where in the code the above is coming from - do you know?
The source line:

Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", chmodRunCmdStr});

where chmodRunCmdStr = "chmod ugo=rwx /sybwork/CURRENT/*.RSA1";

The output is result of execution of this line API. Runtime.getRuntime().exec()

Because I tried to put debug before and after and this below result line is Unix response for that exec() method execution.

chmod: /sybwork/CURRENT/*.RSA1: A file or directory in the path name does not exist.
The output is result of execution of this line API. Runtime.getRuntime().exec()

I don't see how it can be - you are meant to have captured stderr and stdout in a StringBuilder. Still - you've altered my code so i can't be sure of much
I did not alter your code, I used it:

EncryptDecryptUtils.collectProcessStreams(p, strErr, strOut);

because the method takes StringBuilder object, I cretaed before this call and gave it a size of 256 bytes, because default its just 16 bytes for any StringBuilder() constructor. All I am doing is copied your collectProcessStreams() method in my util class.

So yes, I am with you. I should see the error message from stdErr and stdOut object as per my code, but those objects remain empty and the message is displayed outside. Instead of 'finally' block, I tried to strErr.toString()  in 'try' block too after exec() call, but did not show any difference.
OK, can you please attach EncryptDecryptUtils.java as a file (you might need to change extension)?
Ok. Attaching  EncryptDecryptUtils.java. One more change that I made in your code is instead of using all copy functions, I used org.apache.commons.io.IOUtils which has exact same code as yours. I am already using org.apache.commons.io.IOUtils in several other Java files for this project, so thought of reusing the same instead of adding the same code from your IOUtils class.  Attaching org.apache.commons.io.IOUtils.java as well for your refernce.
EncryptDecryptUtils.java
IOUtils.java
OK i'll try to have a better look later, for which i'd like your calling source file if possible.

Just as an aside - you don't actually need throwableToString - just


log.error("", e);

Open in new window

Here is the calling source file.
EncryptClearTextFilesUsingRSA.java
Can you please eliminate whether the catch block was entered by putting in a sysout please?
I added this code in catch:

 
catch (Exception e) 
{
  System.out.println("in catch block : " + e.getMessage());
 e.printStackTrace();
}

Open in new window


It did not go in catch block, here is the output

chmod version
chmod str: chmod ugo=rwx /sybwork/CURRENT/*.RSA1
1
StrErr: :
StrOut: :
chmod: /sybwork/CURRENT/*.RSA1: A file or directory in the path name does not exist.
It might be interesting to revert to the non-collecting method to see if you get the same output or something different
Not much difference,

here is the code change:

try
{			
Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", chmodRunCmdStr});
//Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", "ls -l"});
EncryptDecryptUtils.outputProcessStreams(p);
		
//	EncryptDecryptUtils.collectProcessStreams(p, strErr, strOut);
		
	int exitValue = p.waitFor();
	System.out.println("exit value : " + exitValue);
} catch (Exception e) {
	System.out.println("in catch block : " + e.getMessage());
	e.printStackTrace();
}
finally
{
System.out.println("StrErr: " + strErr.toString() + ":");
System.out.println("StrOut: " + strOut.toString() + ":");
}

Open in new window


here is the Unix screen text:

hqibm18:/sybwork/POLLFILES/JavaProject/EncryptDecryptFilesUsingRSA $. ./FileEncryptionUsingRSA.ksh
chmod version
chmod str: chmod ugo=rwx /sybwork/CURRENT/*.RSA1
chmod: /sybwork/CURRENT/*.RSA1: A file or directory in the path name does not exist.
exit value : 1
StrErr: :
StrOut: :
That doesn't seem to correspond with your code at all. For instance, where in the above do you request this to be printed?

chmod str: chmod ugo=rwx /sybwork/CURRENT/*.RSA1
I did not give you whoe code, please refer the attachment from yesterday. You asked me to provide calling code, and I sent you whole java file EncryptClearTextFilesUsingRSA.java file. I thought you looked at it, so I did not give you whole code again. But here is the source line where that out put is coming from:


 

String chmodRunCmdStr = chmodRunCmdStrBuff.toString();
System.out.println("chmod str: " + chmodRunCmdStr);
StringBuilder strErr = new StringBuilder(256);
StringBuilder strOut = new StringBuilder(256);
try
{                  
Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", chmodRunCmdStr});
//Process p = Runtime.getRuntime().exec(new String[] {"/bin/ksh", "-c", "ls -l"});
EncryptDecryptUtils.outputProcessStreams(p);
                  
//      EncryptDecryptUtils.collectProcessStreams(p, strErr, strOut);
                  
      int exitValue = p.waitFor();
      System.out.println("exit value : " + exitValue);
} catch (Exception e) {
      System.out.println("in catch block : " + e.getMessage());
      e.printStackTrace();
}
finally
{
      System.out.println("StrErr: " + strErr.toString() + ":");
      System.out.println("StrOut: " + strOut.toString() + ":");
}
I can't account for this behaviour but i've never worked with AIX
Ok, I will try to reproduce this on windows and let you know.