0

I am running the below query through Java on a Postgres DB using psql:

psql.exe -U <user> -w -h <host> -d <db_name> -a -f <file> 2> "<path_to_file>\psql.log"

Initially, for quite some time the java program did create the file. Then I ran into another problem, that it was not overwriting the log file. So i used file.delete() function after every time this log file got created via java.

Now, Java is not even creating the log file for some reason. If I run the above manually in command prompt, it runs absolutely fine, but not via java code. I can see this command getting run in the java log, but it does not create the log file even when i have removed the file.delete() function

I researched a lot on it but could not find any solution. Any help would be highly appreciated.

its a long code..so i will tell you the relevant part.

I am calling a function from a thread. Code is below for that function:

public static void SaveACopyfileToServer(int auditid,String filepath,String fname,String tb_name,String plpgsql_path) throws Exception
    {
        Map<String, String> env = System.getenv();

        String plpgsql = "\""+plpgsql_path+"\" -U "+env.get("PG_USER")+" -w -h "+env.get("PG_HOST")+" -d "+env.get("PG_DB")+" -a -f "+"\""+filepath+"copy_"+tb_name+auditid+".sql\" 2> \"C:\\ER\\ETL\\logs\\psql.log\"";
        System.out.println(plpgsql);
        Process p = Runtime.getRuntime().exec(plpgsql);
        p.getOutputStream().close(); 
        p.waitFor();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        Calendar cal10 = Calendar.getInstance();
        System.out.println("Data loaded for "+tb_name+auditid+" at "+sdf.format(cal10.getTime()));
    }

After this i am calling another function which is:

public static void extracterrorreason(String fname,int auditid,String sessionid,Connection con_pg) throws FileNotFoundException, IOException, InterruptedException{
    File file = new File("C:\\ER\\ETL\\logs\\psql.log");

    if(file.exists())
    {
      System.out.println("File present");
        }
    else
        {
         System.out.println(file+" not found");
        }
    if (file.length()!=0){
        System.out.println("Log file being read is "+file);
                    BufferedReader br = new BufferedReader(new FileReader(file));
                    String line = br.readLine();
                    String out_err = line.substring(line.indexOf("ERROR"));

                    System.out.println(out_err);
                    System.out.println("Error while loading the file into Database for file "+fname);

                    String comment = "CopyToStage','"+out_err;
                          Utils.updateAuditDetailTable(auditid, sessionid, -1, comment, true, con_pg,"");

                    br.close();
                    //file.delete();
                }
}

The first function used to create the psql.log file, but now it does not even create it. Not sure where is the problem. Every time i run the code and from the second function,i get the printline that log file not found. The part before the redirection of the output of the cmd command works fine.

I tried process builder also..

I even tried it with Process builder

String plpgsql = "\""+plpgsql_path+"\" -U "+env.get("PG_USER")+" -w -h "+env.get("PG_HOST")+" -d "+env.get("PG_DB")+" -a -f "+"\""+filepath+"copy_"+tb_name+auditid+".sql\" 2> \"C:\\ER\\ETL\\psql_" +auditid +".log\"";
ProcessBuilder pb = new ProcessBuilder("cmd.exe",plpgsql);
Process p =pb.start();
p.getOutputStream().close();
p.waitFor();

1 Answer 1

1

I expect that the problem is that Runtime.getRuntime().exec(plpgsql) is splitting the command line into arguments incorrectly. Basically, exec does not understand quoting. Instead, it splits wherever it sees one or more spaces ... even if those spaces are in quotes.

The solution is to use the exec(String[]) overload, and pass each individual argument as a separate string; e.g.

 .exec(new String[]{plpgsql_path,
                    "-U",
                    env.get("PG_USER"),
                    "-w,
                    "-h",
                    // etcetera
                   });

UPDATE

I didn't notice that you were using > output redirection as well1.

That doesn't work with exec either. (And the same applies to all shell syntax.) To get redirection, you need to use ProcessBuilder and one of the redirect methods.

The other alternative is to run the command in a shell. Pass the command as a string, and let the shell take care of the quote handling, substitution of environment variables, globbing, redirection ... and so on.

For example (if you were running on UNIX, Linux or MacOSX):

 .exec(new String[]{"/bin/sh", "-c", plpgsql});

For Windows

 .exec(new String[]{"cmd.exe", "/C", plpgsql});

Note the "/C" option in the Windows case!


1 - It serves you right for not line-breaking that ~200 character line in your source code! Check out what Java coding standards say about source line lengths ...

Sign up to request clarification or add additional context in comments.

3 Comments

i tried it but didnt seem to work.... String filename = filepath+"copy_"+tb_name+auditid+".sql"; String psqllog_file = "C:\\ER\\ETL\\logs\\psql_" +auditid +".log"; Process p = Runtime.getRuntime().exec(new String [] { plpgsql_path, "-U", env.get("PG_USER"), "-w", "-h", env.get("PG_HOST"), "-d", env.get("PG_DB"), "-a", "-f", filename, "2>", psqllog_file });
I have updated my question with the process builder part also
Your Update Windows case should be { "CMD.EXE" , "/C", plpgsql} . Otherwise concur.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.