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
.