Home > Enterprise >  Execute shell commands by ProcessBuilder In java but seems nothing work
Execute shell commands by ProcessBuilder In java but seems nothing work

Time:04-01

I want to export the selected database in a container. When using shells commands I use this

kubectl exec -it pg-container -n data-prod -- /bin/bash -c "pg_dump -U nsc -d nsc -n public -f nsc.sql"

when data-prod is namespace and pg-container is the container having PostgreSQL database.

This command works well in the shell. But I want to execute this command in Java using ProcessBuilder.

The implementation in java is like this:

public class ExportDBInfo {
        String dbname;
        String schemaname;
        ArrayList<String> tablesname;
        String dbuser;
        String output;
    }
for (ExportDBInfo dbinfo : Array_db_info){
            String export_database_cmd = String.format("kubectl exec -it pg-container -n data-prod -- /bin/bash -c \"pg_dump -U %s -d %s -n %s %s -f %s.sql\"",dbinfo.dbuser,dbinfo.dbname,dbinfo.schemaname,query_tables,dbinfo.output);
            ProcessBuilder pb = new ProcessBuilder(export_database_cmd);
            pb.start().waitFor();
}

But that doesn't work. I'm wondering if there are some mistakes in my implementation. Thanks a lot!

CodePudding user response:

Java isn't bash, or shell. You don't really ever want to use exec, its rules are somewhat bizarre. It tries very haphazardly to split on spaces.

Instead, use ProcessBuilder, and specify a list of arguments, not the single string variant.

That whole pg_dump thing is a single argument and should not contain quotes - those quotes are 'eaten' by bash and tell bash to treat it all as a single argument; java isn't bash and just blindly passes them to the kubectl tool which doesn't know what it means.

All the other args (including --) are their own thing.

So..

List.of("/bin/kubectl", "exec", "-it", "pg-container", "-n", "data-prod", "--", "/bin/bash", "-c", String.format("pg_dump -U %s -d %s -n %s %s -f %s.sql", dbinfo.dbuser, dbinfo.dbname, dbinfo.schemaname, query_tables, dbinfo.output));

And pass that to the constructor of ProcessBuilder.

  • Related