Trying to run cmd commands through Java...only first half is runs - java

I am running the below query through Java on a Postgres DB using psql:
psql.exe -U <user> -w -h <host> -d <db_name> -a -f <file> 2> "<path_to_file>\psql.log"
Initially, for quite some time the java program did create the file. Then I ran into another problem, that it was not overwriting the log file. So i used file.delete() function after every time this log file got created via java.
Now, Java is not even creating the log file for some reason. If I run the above manually in command prompt, it runs absolutely fine, but not via java code. I can see this command getting run in the java log, but it does not create the log file even when i have removed the file.delete() function
I researched a lot on it but could not find any solution. Any help would be highly appreciated.
its a long code..so i will tell you the relevant part.
I am calling a function from a thread. Code is below for that function:
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()));
}
I have tried the following codes also:
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("C:/Windows/System32/cmd.exe",plpgsql);
System.out.println(plpgsql);
Process p =pb.start();
p.getOutputStream().close();
p.waitFor();
and
String filename = filepath+"copy_"+tb_name+auditid+".sql";
String psqllog_file = "C:\\ER\\ETL\\logs\\psql_" +auditid +".log";
Process p = Runtime.getRuntime().exec(new String [] { plpgsql_path,
"-U",
env.get("PG_USER"),
"-w",
"-h",
env.get("PG_HOST"),
"-d",
env.get("PG_DB"),
"-a",
"-f",
filename,
"2>",
psqllog_file });
If i run it through a batch file, then I am getting and error that Windows cannot find -U using the below code in java
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("C:/Windows/System32/cmd.exe","/c","start",plpgsql);
System.out.println(plpgsql);
Process p =pb.start();
p.getOutputStream().close();
p.waitFor();
I am stuck on this for a good amount of time now. Any help would be really really appreciated.
P.S: I am absolutely new to Stackoverflow, still trying to learn how to reply to comments to notify the other person, cz i think my replies are not being sent to the mailbox of others.

Related

Runtime.getRuntime().exec(command) doesn't do anything

In my XPages application I have to call curl commands
The code is simple:
public static InputStream executeCurlCommand(String finalCurlCommand) throws IOException
{
return Runtime.getRuntime().exec(finalCurlCommand).getInputStream();
}
However, it seems that the command isn't executed at all.
When I execute the following (in Linux terminal):
curl -k -i -X GET https://someHost/fws/api/esia/login?redirectUrl=https://redirectHost/sed/gecho/2019/gecho_apps_2019.nsf/Nav2.xsp
I get the output.
But whenever I execute it with Java nothing works. getInputStream() is empty.
At the same time, if I execute this code on my local Windows machine everything is fine. Same goes for the command executed from cmd.
But in XPages there are no exceptions, no errors, just nothing.
Is there a way to debug it?
UPD
If I change the command to something as simple as ls -la everything works fine :x
OK, guys, I figured it out. The thing was that I passed the full command to the shell. It doesn't work in UNUX.
So
You should NEVER use
public static InputStream executeCurlCommand(String finalCurlCommand) throws IOException
{
return Runtime.getRuntime().exec(finalCurlCommand).getInputStream();
}
In UNIX systems. Use ProcessBuilder instead
For example:
ProcessBuilder pb = new ProcessBuilder(
"curl",
"-k",
"-i",
"-X",
"GET",
"http://host.com");
pb.redirectErrorStream(true);
Process p = pb.start();
InputStream is = p.getInputStream();

Run SQL script on PostgreSQL with password supplied

I'm trying to run an SQL-script from within my Java app. This is my code:
Runtime rt = Runtime.getRuntime();
rt.exec("setx PGPASSWORD \"" + password + "\"");
String command = String.format("psql -d %s -h %s -p %s -U %s -w -f %s",
database, host, port, user, "create_tables.sql");
System.out.println("Executing command " + command);
Process p = rt.exec(String.format(command));
p.waitFor();
This prints
psql -d routes -h localhost -p 5432 -U postgres -w -f create_tables.sql
as expected.
However within my databases log I see the following:
psql: fe_sendauth: no password supplied
How do I supply the password to psql when calling it as process?
Your environment variable should be set in the same process as the psql is executed. This does not happen in your code as you execute two different processes.
The thing is, that environment variables are local to process contexts.
A new process gets a copy of the parent's environment but each copy is independent.
In your case, the Java process creates child process that modifies PGPASSWORD through setx command - so far so good.
However, this doesn't affect the Java process. Your second child process isn't running in a shell, so it ignores the PGPASSWORD variable as the process is created using OS services. Those services, take into consideration the old context of the Java process which is not aware of PGPASSWORD unless you change the environment in the shell before you start the original (parent) Java process.
Thus,to solve your problem, you have to set up the environment variable and then run the child as a shell command (cmd /c).
To set up environment variable we could follow #Little Santi's advice.
So the code would look something like the following
Runtime rt = Runtime.getRuntime();
String setCommand="PGPASSWORD=" + password;
String command = String.format("psql -d %s -h %s -p %s -U %s -w -f %s",
database, host, port, user, "create_tables.sql");
String finalCommand = "cmd /c \" " + command +"\"";
System.out.println("Executing command " + finalCommand);
Process p = rt.exec(finalCommand ,new String[]{setCommand});
p.waitFor();
Edit 2:
#Plirkee's diagnosis is right: The process in which you start psql misses the required environment variable. But to set it on properly it's better to use the Runtime.exec(String[] cmdarray, String[] envp) method.

execute multiple commands in cmd using java

I need to execute multiple comments in single cmd window using java.
The comments are
1. cd C:\Apps\wildfly-8.0.0.Final\bin
2. jboss-cli.bat --connect --command=\"deploy --force C:\Users\me\git\test\Test\build\libs\TestEAR.ear
Because I need to execute the second command from the folder "C:\Apps\wildfly-8.0.0.Final\bin".
I tried this :
Runtime.getRuntime().exec("cmd /c start cd C:\\Apps\\wildfly-8.0.0.Final\\bin\\ && start cmd.exe /c jboss-cli.bat --connect --command=\"deploy --force C:\\Users\\me\\git\\test\\Test\\build\\libs\\TestEAR.ear\"");
But it is executing these commands separate , that is it will open one cmd window and executes the first commands , then it will execute the second command in another cmd window , and showing the error :
Could not locate "C:\Users\me\git\test\Test\build\libs\TestEAR.ear".
Please check that you are in the bin directory when running this script.
Press any key to continue . . .
I found some solutions with batch file , but in my application I can't use batch file (must not use batch file ) .
Can anyone suggest a solution ?
If I understand your question you could use a ProcessBuilder and call directory(File). Something like
public static void main(String[] args) throws IOException {
String folder = "C:\\Apps\\wildfly-8.0.0.Final\\bin";
String command = "jboss-cli.bat --connect --command=\"deploy --force "
+ "C:\\Users\\me\\git\\test\\Test\\build\\libs\\TestEAR.ear\"";
ProcessBuilder pb = new ProcessBuilder(command);
pb.directory(new File(folder));
pb.inheritIO();
Process p = pb.start();
try {
p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Java execute debian terminal command with "|"

I am experiencing a really confusing issue about sending commands to terminal via Java.
I have exactly this code:
Process p = Runtime.getRuntime().exec(new String[]{"useradd", server, "-p", pass, "-d", "/home/dakadocp/servers/" + server, "-s", "/bin/false"});
Runtime.getRuntime().exec(new String[]{"echo", server + ":" + pass, "|", "chpasswd"});
The first command is this one "useradd user -p password -d /home/ftp/test/ -s /bin/false" and the second one should be this echo username:new_password | chpasswd, the first command works without any problem and creates the user which I define by the "server" variable, but when I try to execute the second command to change users pass this command probably never happen, output is null and the password is not changed, but when I type this command directly to the terminal it works perfectly so this is just Java issue.
I think the problem is in the character "|", before I tried also some command with "|" and its behavior was the same as with this command. What I am doing wrongly ?
Thanks.
Welite.
| is a shell feature, and requires a shell to run. The trivial fix is to run a shell:
Runtime.getRuntime().exec(new String[] { "sh", "-c", "echo something | chpasswd" });
However, java is more than capable of writing to a process with needing a shell or echo. The better way is to just run chpasswd by itself and writing the string to it:
Process p = Runtime.getRuntime().exec(new String[] { "chpasswd" });
PrintWriter writer = new PrintWriter(p.getOutputStream());
writer.println("foo:bar");
writer.close();

shell script if statement executed from java?

I'm trying to execute unix commands thru a java program. Some of these commands involve an if-then-fi statement. Can this be done thru java / Runtime class? Seems like it only handles 1 command at a time.
I'm looking to do something like this:
grep 'Error One' SystemErr.log > $HOME/tempFiles/output.txt
grep 'Error Two' SystemErr.log >> $HOME/tempFiles/output.txt
grep 'Error Three' SystemErr.log >> $HOME/tempFiles/output.txt
.
.
if [ -s $HOME/tempFiles/output.txt ]
then
mail -s "Subject here" "a#b.com" < $HOME/tempFiles/output.txt
fi
Basically, I just want to email the file (results) if the grep found anything.
I want to use java instead of a direct shell script so that the errors I search for can be database-driven, easier to change.
I know I could read the file myself in java and search/parse it myself. But grep and other unix commands have a lot of built-in functionality I want to use to make it easier.
Any ideas, or am I totally on the wrong track?
Here is some code, using simpler commands, but basically equivalent:
public static void main( String[] args ) throws Exception {
try {
ProcessBuilder pb = new ProcessBuilder( "/bin/bash", "-c",
"echo one >/tmp/xxx && echo two >>/tmp/xxx && " +
"if [ -s /tmp/xxx ]; then cp /tmp/xxx /tmp/yyy; fi" );
File log = new File( "/tmp/log.txt" );
pb.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
Process process = pb.start();
process.waitFor();
} catch( Exception e ){
// ...
} catch( Error e ){
// ...
}
}
The trick is to put it all into a single shell command so that you can call /bin/bash with the -c command option.
If composing this command is too complicated, write a shell file and source that.

Categories