2016-03-07 91 views
0

運行我正在通過Java上一個Postgres數據庫使用PSQL下面的查詢:完整的CMD命令不能從Java

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

最初,在相當一段時間的java程序沒有創建該文件。然後我遇到了另一個問題,那就是它沒有覆蓋日誌文件。所以我在每次通過java創建這個日誌文件之後都使用了file.delete()函數。

現在,由於某種原因,Java甚至沒有創建日誌文件。如果我在命令提示符下手動運行上面的代碼,它運行得非常好,但不能通過java代碼。我可以看到這個命令在java日誌中運行,但它不會創建日誌文件,即使我已經刪除file.delete()函數

我研究了很多,但找不到任何解決方案。任何幫助將不勝感激。

它的長碼..所以我會告訴你相關的部分。

我從一個線程調用函數。代碼如下爲該函數:

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())); 
    } 

在此之後我打電話的另一個功能是:

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(); 
       } 
} 

用於創建psql.log文件中的第一個功能,但現在它甚至不創造它。不知道問題在哪裏。每當我運行代碼並從第二個函數,我得到的日誌文件沒有找到的印刷線。 cmd命令的輸出重定向之前的部分工作正常。

我試過進程生成器也..

我甚至與進程生成試過

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

我想到的是,問題是,Runtime.getRuntime().exec(plpgsql)被分裂命令行參數將不正確。基本上,exec不明白報價。相反,它在任何看到一個或多個空間的地方都會分裂......即使這些空間在引號內。

解決方法是使用exec(String[])重載,並將每個單獨的參數作爲單獨的字符串傳遞;例如

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

UPDATE

我沒有注意到你正在使用>輸出重定向以及。

這也不適用於exec。 (這同樣適用於所有的 shell語法。)要獲得重定向,您需要使用ProcessBuilderredirect方法之一。

另一種方法是在shell中運行命令。將該命令作爲字符串傳遞,並讓shell負責處理引號,替換環境變量,通配符,重定向...等等。

例如(如果你是在UNIX,Linux或MacOSX上運行):

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

對於Windows

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

注意在Windows情況下, 「/ C」 選項!


1 - 你活該不斷行的那個〜200字線在你的源代碼! 「SQL」查看一下Java編碼標準說關於電源線長度...

+0

我嘗試過,但沒有似乎工作.... 字符串文件名=文件路徑+「副本_」 + tb_name + auditid +; String psqllog_file =「C:\\ ER \\ ETL \\ logs \\ psql_」+ auditid +「。log」; 進程p =調用Runtime.getRuntime()。EXEC(新的String [] {plpgsql_path, 「-U」, env.get( 「PG_USER」), 「-w」, 「-H」, ENV獲得( 「PG_HOST」), 「-d」, env.get( 「PG_DB」), 「-a」, 「-f」, 文件名, 「2>」, psqllog_file }) ; –

+0

我嘗試使用進程生成器也... –

+0

我更新了我的問題與進程生成器部分也 –