繁体   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