i want to take backup of postgres database using java. I am using following code for this
but this is not working and not generating dump.
String pgDump = "C:\\Program Files\\PostgreSQL\\9.2\\bin\\pg_dump";
String dumpFile = "D:\\test\\"+ tenant.getTenantAsTemplate()+".sql";
String sql = pgDump+" -h localhost -U postgres -P postgres " + tenant.getTenantAsTemplate()+" > "+dumpFile;
Process p = Runtime.getRuntime().exec(sql);
int time = p.waitFor();
System.out.println("time is "+time);
if(time == 0){
System.out.println("backup is created");
}
else{
System.out.println("fail to create backup");
}
Here i am getting time is 1.
This is also operating system dependent and we need also pg_dump. is there any other way to generate backup of database without pg_dump?
please reply soon.
No, there is no way to generate a database backup without pg_dump, using the regular SQL connection. It's a bit of an FAQ, but the people who want the feature never step up to do the work to implement the feature in PostgreSQL.
I guess technically you could use a replication connection to do a physical base backup like pg_basebackup does, but that's not really what you want, requires copying all databases on the machine, and would be a lot of work.
You should use the String[] form of Runtime.exec as I mentioned in a related answer regarding pg_restore.
You must also check the process exit value to see if it terminated successfully or not, and you must be careful to handle, not just swallow, any exceptions thrown.
Your code fails to check the exit value, and I think it's probably generating a malformed command that's failing with a non-zero exit code, probably because you are not correctly quoting the path to pg_dump. To see what's wrong, print the final assembled command line, you'll see something like:
C:\Program Files\PostgreSQL\9.2\bin\pg_dump -h localhost ....
which cmd.exe will split into:
c:\Program
Files\postgresql\9.2\bin\pg_dump
-h
localhost
... etc
See the problem?
Do not just quote the path to pg_dump to work around this. Use the String[] form of exec and you won't have to, plus it'll work correctly for other things like accidental %environmentvars% in paths.
Related
I'm trying to execute bash script using karate. I'm able to execute the script from karate-config.js and also from .feature file. I'm also able to pass the arguments to the script.
The problem is, that if the script fails (exits with something else than 0) the test execution continues and finishes as succesfull.
I found out that when the script echo-es something then i can access it as a result of the script so I could possibly echo the exit value and do assertion on it (in some re-usable feature), but this seems like a workaround rather than a valid clean solution. Is there some clean way of accessing the exit code without echo-ing it? Am I missing on something?
script
#!/bin/bash
#possible solution
#echo 3
exit 3;
karate-config.js
var result = karate.exec('script.sh arg1')
feture file
def result = karate.exec('script.sh arg1')
Great timing. We very recently did some work for CLI testing which I am sure you can use effectively. Here is a thread on Twitter: https://twitter.com/maxandersen/status/1276431309276151814
And we have just released version 0.9.6.RC4 and new we have a new karate.fork() option that returns an instance of Command on which you can call exitCode
Here's an example:
* def proc = karate.fork('script.sh arg1')
* proc.waitSync()
* match proc.exitCode == 0
You can get more ideas here: https://github.com/intuit/karate/issues/1191#issuecomment-650087023
Note that the argument to karate.fork() can take multiple forms. If you are using karate.exec() (which will block until the process completes) the same arguments work.
string - full command line as seen above
string array - e.g. ['script.sh', 'arg1']
json where the keys can be
line - string (OR)
args - string array
env - optional environment properties (as JSON)
redirectErrorStream - boolean, true by default which means Sys.err appears in Sys.out
workingDir - working directory
useShell - default false, auto-prepend cmd /c or sh -c depending on OS
And since karate.fork() is async, you need to call waitSync() if needed as in the example above.
Do provide feedback and we can tweak further if needed.
EDIT: here's a very advanced example that shows how to listen to the process output / log, collect the log, and conditionally exit: fork-listener.feature
Another answer which can be a useful reference: Conditional match based on OS
And here's how to use cURL for advanced HTTP tests ! https://stackoverflow.com/a/73230200/143475
In case you need to do a lot of local file manipulation, you can use the karate.toJavaFile() utility so you can convert a relative path or a "prefixed" path to an absolute path.
* def file = karate.toJavaFile('classpath:some/file.txt')
* def path = file.getPath()
I am slowly trying to make a python script to SSH then FTP to do some manual file getting I have to do all the time. I am using Paramiko and the session seems to command, and prints the directory but my change directory command doesn't seem to work, it prints the directory I start in: /01/home/.
import paramiko
hostname = ''
port = 22
username = ''
password = ''
#selecting PROD instance, changing to data directory, checking directory
command = {
1:'ORACLE_SID=PROD',2:'cd /01/application/dataload',3:'pwd'
}
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname,port,username,password)
for key,value in command.items():
stdin,stdout,stderr=ssh.exec_command(value)
outlines=stdout.readlines()
result=''.join(outlines)
print (result)
ssh.close()
When you run exec_command multiple times, each command is executed in its own "shell". So the previous commands have no effect on an environment of the following commands.
If you need the previous commands to affect the following commands, just use an appropriate syntax of your server shell. Most *nix shells use a semicolon or an double-ampersand (with different semantics) to specify a list of commands. In your case, the ampersand is more appropriate, as it executes following commands, only if previous commands succeed:
command = "ORACLE_SID=PROD && cd /01/application/dataload && pwd"
stdin,stdout,stderr = ssh.exec_command(command)
In many cases, you do not even need to use multiple commands.
For example, instead of this sequence, that you might do when using shell interactively:
cd /path
ls
You can do:
ls /path
See also:
How to get each dependent command execution output using Paramiko exec_command
Obligatory warning: Do not use AutoAddPolicy on its own – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".
Well by accidentally trying something I managed to figure this out I believe. You need to do all the commands at one time and do not need to do them in a loop. for for my instance it would be
import paramiko
hostname = ''
port = 22
username = ''
password = ''
#selecting PROD instance, changing to data directory, checking directory
command = 'ORACLE_SID=PROD;cd /01/application/dataload;pwd'
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname,port,username,password)
stdin,stdout,stderr=ssh.exec_command(value)
outlines=stdout.readlines()
result=''.join(outlines)
print (result)
ssh.close()
I am trying to call a perl script from java runtime. It worked fine on my windows7 laptop with the following code,
try {
String cmdString= "c:\\perl64\\bin\\perl.exe c:\\perl64\\eg\\userinput.pl \""+arg1+"\" \""+arg2+"\"";
Process p = Runtime.getRuntime().exec(cmdString);
} catch(IOException e) {
System.out.println(e);
}
The perl script runs and produces what I expect (update database).
When I move the whole thing over to a remote CentOS server, it doesn't work anymore. The script is the same and the java code is,
try {
String cmdString= "/opt/lampp/bin/perl /home/support/scripts/userinput.pl \""+arg1+"\" \""+arg2+"\" > /tmp/userinput.log";
log(cmdString);
Process p = Runtime.getRuntime().exec(cmdString);
} catch(IOException e) {
System.out.println(e);
}
I added redirect to /tmp/userinput.log after I see the script is not working. But there is no log file created at all. I also added log to make sure this part of the java code did get executed, and indeed it did. I also tried to add "/bin/bash " in front of the comString and it didn't make a difference. However, when I run the cmdString directly on the remote server from command line, it works without problem.
Now, when I changed the cmdString to "touch /tmp/userinput.log", it does create the empty log file.
So I know the Runtime.getRuntime().exec(cmdString) command ran, and the cmdString works when entered on command line, and a simple "touch" command would work with this setup. But I am totally lost why the actual cmdString that calls the perl script doesn't work, and there is no message whatsoever to tell me what is wrong.
Can someone please help?
Frist, separate each parameter for the command and use the version of exec which takes a String[] (you won't have to worry about quoting issues). also, shell redirection won't work since java isn't executing a shell.
I know that by using the command in the terminal
date --set="2011-12-07 01:20:15.962"
you would actually be able to change the System clock, so I tried it in Java and came up with the following statement
Process p = Runtime.getRuntime().exec("date --set=\"2011-12-07 01:20:15.962\"");
but it was not able to set the clock.
Do you have any idea guys how it may be able work?
Premise:
The machine is Slackware,
The privilege is root level
There are two problems with this line of code:
Process p = Runtime.getRuntime().exec("date --set=\"2011-12-07 01:20:15.962\"");
You did not wait for the process to complete (see also http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html#waitFor())
Parameters should be separated from program name, try this:
"date", "-s", "2011-12-07 01:20:15.962"
Alternatively, invoke shell as the process, and pass in a line of code:
.exec("sh", "-c", "date --set=\"2011-12-07 01:20:15.962\"")
Process p=Runtime.getRuntime().exec(new String[]{"date","--set","2011-12-07 01:20:15.962"});
The above statement worked like magic. #Howard Gou was right with "Parameters should be separated from program name"
The parts of the command statement should be passed by using a String array.
I need to get a list of chunks after sharding inside my Java code. My code is simple and looks like this:
Mongo m = new Mongo( "localhost" , 27017 );
DB db = m.getDB( "admin" );
Object cr = db.eval("db.printShardingStatus()", 1);
A call of eval() returns an error:
Exception in thread "main" com.mongodb.CommandResult$CommandFailure: command failed [$eval]: { "serverUsed" : "localhost/127.0.0.1:27017" , "errno" : -3.0 , "errmsg" : "invoke failed: JS Error: ReferenceError: printShardingStatus is not defined src/mongo/shell/db.js:891" , "ok" : 0.0}
at com.mongodb.CommandResult.getException(CommandResult.java:88)
at com.mongodb.CommandResult.throwOnError(CommandResult.java:134)
at com.mongodb.DB.eval(DB.java:340)
at org.sm.mongodb.MongoTest.main(MongoTest.java:35)
And, really, if we look into the code of db.js, in line 891 there is a call to a method printShardingStatus() that is not defined inside a file. Inside of sh.status() method in utils_sh.js file, there is even a comment:
// TODO: move the actual commadn here
Important to mention, when I run these commands in mongo command line, everything works properly!
My questions are:
Is there any other possibility of getting a full sharding status within Java code? (eg. with DB.command() method)
If not, any other suggestions how to avoid my problem?
Many of the shell's helper functions are not available for server-side code execution. In the case of printShardingStatus(), it makes sense because there isn't a console to use for printing output and you'd rather have a string returned. Thankfully, you should be able to pull up the source of the shell function and reimplement it in your application (e.g. concatenating a returned string instead of printing directly).
$ mongo
MongoDB shell version: 2.2.0
connecting to: test
> db.printShardingStatus
function (verbose) {
printShardingStatus(this.getSiblingDB("config"), verbose);
}
So, let's look at the printShardingStatus() function...
> printShardingStatus
function (configDB, verbose) {
if (configDB === undefined) {
configDB = db.getSisterDB("config");
}
var version = configDB.getCollection("version").findOne();
// ...
}
Before turning all of the output statements into string concatenation, you'd want to make sure the other DB methods are all available to you. Performance-wise, I think the best option is to port the innards of this function to Java and avoid server-side JS evaluation altogether. If you dive deeper into the printShardingStatus() function, you'll see it's just issuing find() on the config database along with some group() queries.
If you do want to stick with evaluating JS and would rather not keep this code within your Java application, you can also look into storing JS functions server-side.
Have you deployed a shard cluster properly?
If so, you could connect to a mongo database that has sharding enabled.
Try calling the method db.printShardingStatus() with a that database within the mongo shell and see what happens.
Apparently the Javascript function 'printShardingStatus' is only available for the mongo shell and not for execution with server commands, to see the code start mongo.exe and type only 'printShardingStatus' and press enter.
In this case writing an extension method would be the best for solving this...
Javascript way of printing output of MongoDB query to a file
1] create a javascript file
test.js
cursor = db.printShardingStatus();
while(cursor.hasNext()){
printjson(cursor.next());
}
2] run
mongo admin --quiet test.js > output.txt