3

I've been struggling for a while now with this problem and i can't seem to fix it. i have tried ProcessBuilder for executing the custom command on linux terminal but its not working

Actually i have two .sh file setProto.sh and setTls.sh file which is used to set the environment.So for executing the command i need to run these two file first for each instance of linux terminal.Only then we can be able to run the custom command anloss on the same instance of linux terminal in which .sh file supposed to run.For some reason i'm not able to make it work what is the mistake in my code ? Here's the code.

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;

public class EngineTest {

    public static void main(String[] args) {
        try {
            ProcessBuilder builder = new ProcessBuilder(
                    "/. setProto.sh",
                    "/. setTls.sh",
                    "/anloss -i ${TOOL_INPUT}/census_10000_col5.csv  -d ${TOOL_DEF}/attr_all_def.txt -q k=14,dage=2 -g ${TOOL_RES}/census_100_col8_gen.csv");
            builder.directory(new File(System.getenv("HOME") + "/PVproto/Base"));
            File log = new File("log");
            builder.redirectErrorStream(true);
            builder.redirectOutput(Redirect.appendTo(log));
            Process process = builder.start();

            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
            String line = "";
            String output = "";
            while ((line = bufferedReader.readLine()) != null) {
                output += line + "\n";
            }
            System.out.println(output);
            int exitValue = process.waitFor();
            System.out.println("\n\nExit Value is " + exitValue);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
henrycharles
  • 1,019
  • 6
  • 28
  • 66

2 Answers2

4

Process does not by default execute in the context of a shell; therefore your shell scripts cannot be executed the way you tried.

ProcessBuilder pb =
    new ProcessBuilder( "/bin/bash",
                        "-c", 
                        ". setProto.sh && . setTls.sh && /anloss -i ${TOOL_INPUT}/census_10000_col5.csv  -d ${TOOL_DEF}/attr_all_def.txt -q k=14,dage=2 -g ${TOOL_RES}/census_100_col8_gen.csv" );

I am not sure about /anloss - it's unusual for a command to be in root's home /. (Also, the /. you had there in front of the shell scripts - what should they achieve?)

Later

Make sure to replace /anloss with an absolute pathname or a relative pathname relative to $HOME/PVproto/Base, e.g., if it is in this directory, use ./anloss, if it is in $HOME/PVproto/Base/SomeSub, use SomeSub/anloss, etc.

Also, if setProto.sh and . setTls.sh are not in $HOME/PVproto/Base, use an appropriate absolute or relative pathname. If they are, use ./setProto.sh and ./setTls.sh to avoid dependency on the setting of environment variable PATH.

laune
  • 31,114
  • 3
  • 29
  • 42
  • /. for script is to run on current directory and /anloss is not in root.If u see my code i have added builder.directory(new File(System.getenv("HOME") + "/PVproto/Base")); this is the path where all script and command has to run.if i made any mistake please do tell me. – henrycharles Jul 07 '14 at 18:08
  • i have tried ur way but its throwing error "cannnot run program /bash/bin"(in directory "/home/cloudera/PVproto/Base"): error=2,No such file or directory – henrycharles Jul 08 '14 at 06:06
  • The program is called `/bin/bash` (*not* /bash/bin) which must be there if it's Linux. You might also use `/bin/sh`. – laune Jul 08 '14 at 06:33
  • Setting a **working directory** has not the influence you think on the way pathnames for program errxecution need to be specified. If you set the working directory to /home/henry, then you may execute a file in this directory using ./aProgInHenry.exe, but if the program is elsewhere, specify an absolute pathname. `/anloss` *is* an **absolute pathname** and instructs the system to go to the root directory. – laune Jul 08 '14 at 06:40
  • Starting a command with `/.` to "run on current directory" - from where did you take this idea? `/.` is an absolute pathname referring to the root directory, i.e., `/`. (Try `ls /.` from a shell prompt.) If this is first in a command, it'll just try to call a program called `/`, which, of course, is nonsense. – laune Jul 08 '14 at 06:43
  • I have added instructions for replacing "/anloss", which is clearly wrong. – laune Jul 08 '14 at 06:47
  • i have given the absolute path but i am getting exit value as 126 as error code. I have give like this new ProcessBuilder("/bin/bash","-c","/home/cloudera/PVproto/Base/. setTls.sh && /home/cloudera/PVproto/Base/. setProto.sh && /home/cloudera/PVproto/Base/anloss -i ${TOOL_INPUT}/census_10000_col5.csv -d ${TOOL_DEF}/attr_all_def.txt -q k=14,dage=2 -g ${TOOL_RES}/census_100_col8_gen.csv") – henrycharles Jul 08 '14 at 06:49
  • This part is incorrect: "/home/cloudera/PVproto/Base/. setTls.sh && /home/cloudera/PVproto/Base/. setProto.sh ..." Please follow the extended advice in the updated answer. – laune Jul 08 '14 at 07:01
  • Where's this idea of a directory name as a separate word in front of a command's name coming from?? – laune Jul 08 '14 at 07:03
  • i have checked the permission on all file it is rwxr-xr-x including sh and anloss file – henrycharles Jul 08 '14 at 07:03
  • This I do believe. Please fix the invocations of those shell scripts! – laune Jul 08 '14 at 07:05
  • issue fixed, problem is with my script file that contain #!bin/bash ,i removed that, now exit code is coming 0 thnx for the help.One more question here is ,i am running command but output of that command is not coming in my eclipse console does i have make any mistake in my code for reading the output? – henrycharles Jul 08 '14 at 09:44
  • Standard output should appear there, but is "that command" really writing to *standard output*? Chancge String output = ""; to String output = "Output: "; and see what happens. – laune Jul 08 '14 at 10:02
  • no ouptut is visible instead of "Output:", but when i append >test12 in front of my command , output is coming to this test12 file can u please tell why its happening – henrycharles Jul 08 '14 at 10:08
  • Try moving this statement: `int exitValue = process.waitFor();` up after `Process process = builder.start();`. Thus, the process completes and all standard output is available before you read it in the loop. - BTW, don't collect it all into a String `output`, simply `System.out.println( line );` with a line after you have read it. – laune Jul 08 '14 at 11:00
0

I think you need to use Runtime.exec() for executing the commands on linux. I suppose you are executing your java code on linux machine where linux scripts needs to be run.

Below code snippet will help you in resolving it.

Process process = Runtime.getRuntime().exec(scriptWithInputParameters);
int exitCode = process.waitFor();
if (exitCode == 0) {
    System.out.println("Executed successfully");
}
else {
  System.out.println("Failed ...");
}


Please note you need to handle error and output stream in different threads to avoid buffer overflow.

If the above works for you then this article will help you further

Moorthy
  • 1
  • 3