简体   繁体   中英

Runtime.getRuntime.exec() works on Windows but not Linux

I am building a Java application that calls a system command and executes that command before returning control to the Java thread. The debugging step that I have is that I have made a perl script called test.pl and I call that script from the Java method and in Windows I get the expected output and a return value of 0. In Linux I get no output or error output and I get a return value of 136. I have spent extensive time online trying to figure out where I have gone wrong but as I have said, on Windows it runs. I think it must be a simple error that I am just not catching.

Here is the code derived from the excellent Runtime.exec() tutorial at http://www.javaworld.com/jw-12-2000/jw-1229-traps.html

try {

    FileOutputStream fos = new FileOutputStream("output/" + this.startPosition + ".txt");
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec(new String[]{"perl", "/data/stat-positive-selection/thaddeus/treesim/chr2YRI/test.pl"});

//System.out.println(commandLine);
// any error message?
StreamGobbler errorGobbler = new 
   StreamGobbler(proc.getErrorStream(), "ERROR");            

// any output?
StreamGobbler outputGobbler = new 
    StreamGobbler(proc.getInputStream(), "OUTPUT", fos);

// kick them off
errorGobbler.start();
outputGobbler.start();

// any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);

fos.flush();
fos.close(); 
} catch (Throwable e){
    e.printStackTrace();
    }
}

I have figured it out and fixed the code

new exec call, the use of the shell and the path to perl are required

Process proc = rt.exec(new String[]{"/bin/bash", "-c", "/usr/bin/perl /data/stat-positive-selection/thaddeus/treesim/chr2YRI/test.pl"});

The differences between the old and new versions are:

  • you are running the command from a shell, and
  • you are specifying the full pathname of the "perl" command.

In fact, in this context there doesn't seem to be a great deal of point in running the command from a shell. (Hypothetically, your Perl application might depend on environment variables that are set during shell initialization. However, the same environment variables would normally be inherited by and then from the Java command's environment. So unless the Java command is being launched in a strange way, this scenario is ... unlikely.)

So I think the substantative difference 1 is that you are using the full pathname for "perl" ... and you don't a subshell to do that.

So, in the interests of science ( :-) ) I suggest you try this:

    Process proc = rt.exec(new String[]{
            "/usr/bin/perl", 
            "/data/stat-positive-selection/thaddeus/treesim/chr2YRI/test.pl"});

1 - ... the difference that makes a difference

I replaced the whole Runtime.exec() structure with the Apache Commons Exec library. It fixed the problem I was having.

http://commons.apache.org/proper/commons-exec/tutorial.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM