簡體   English   中英

無法從Java運行完整的CMD命令

[英]complete CMD command not running from java

我正在使用psql在Postgres DB上通過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命令的輸出之前的部分工作正常。

我也嘗試過流程構建器

我什至用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();

我希望問題在於Runtime.getRuntime().exec(plpgsql)將命令行錯誤地拆分為參數。 基本上, exec不理解引用。 相反,它會在看到一個或多個空格的位置進行拆分...即使這些空格用引號引起來也是如此。

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

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

更新

我沒有注意到您也在使用>輸出重定向1

這對exec也不起作用。 所有 Shell語法也一樣。)要獲得重定向,您需要使用ProcessBuilder和其中一種redirect方法。

另一種選擇是在外殼中運行命令。 以字符串形式傳遞命令,然后讓外殼處理引號處理,環境變量的替換,globbing,重定向...等。

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

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

對於Windows

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

注意Windows情況下的“ / C”選項!


1-它為您服務,不會在您的源代碼中對〜200個字符的行進行換行! 檢查一下Java編碼標准對源代碼行長度的說明...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM