Unable to run UNIX command from Java program - java

I am trying to create a java program that takes some user-input variables and passes them to a perl script (it actually finds a certain string within the perl script and replaces it with the user-input variables). Here is the code:
String sedMain = "sed -e ";
String sedFirstLine = "'s/AAA/"+newFirstLine+"/' -e ";
String sedNewCntr = "'s/BBB/"+newCntr+"/' -e ";
String sedNewSpacing = "'s/SPACE/"+newSpacing+"/' -e ";
String sedNewDmax = "'s/MAX/"+newDmax+"/'";
String sedFile = " /filepath/myperlscript.pl > /filepath/myNEWperlscript.pl";
String sedCommand=sedMain+sedFirstLine+sedNewCntr+sedNewSpacing+sedNewDmax+sedFile;
System.out.println("SED COMMAND: "+sedCommand);
String testRun = "touch /filepath/hello.txt";
Process runSedCommand;
runSedCommand = Runtime.getRuntime().exec(sedCommand);
I am using an IDE, and when the sed command is printed to the console, it looks correct. I copied the sed command from the console and ran it from the terminal, and it worked. I wrote the string "testRun" to see if there was a problem with the Process in Java, and it created the file "hello.txt". For some reason though, my program is not creating the output perl file "myNEWperlscript.pl". I am very confused as to why this is not working. Can anyone help out?

exec() takes a String[] with the program name and paramaters as its elements, but you are concatenating everything together into a single String and so effectively loosing the arguments.
Try something like this:
String[] cmd = {"sed", "first argument", "second argument"};
Runtime.getRuntime().exec(cmd);

use the
exec(String[] cmdarray)
signature.
the command is sed, -e is a parameter, 's/AAA/\n/' is another parameter and so on. So you will have
String[] command = new String[] {"sed", "-e", "s/AAA/\n/", "next parameter without single quotes", , "next parameter without quotes..."}
Runtime.getRuntime.exec(command);
This is the only way your parameters will get well formatted on it's way to the shell, otherwise weird sruff can happen as any quotes after the first token on the string will be considered to be just one parameter and so quotes can be escaped and things like that

Related

Pass parameter from array to powershell java program

I have a java code that execute a powershell script.My parameters are in a string array that I got from user.
String sentence = clientinp.readUTF();
String[] parts = sentence.split(",");
How should I put the parameters to the script every time I execute the code?
I tried this code:
String command = "powershell.exe $Add-DnsServerResourceRecordA -ZoneName -Name -IPv4Address -TimeToLive";
But I don't know how can I pass this array to powershell.What should I do?
Use a ProcessBuilder. You have to put each parameter (including path to the program) as items to an array or list and pass it to the constructor of ProcessBuilder.
for example:
String[] arguments = {"powershell.exe", "$Add-DnsServerResourceRecordA", "-ZoneName", "[your zone name]", "-Name", "[your name]", "-IPv4Address", "[your ipv4 address]", "-TimeToLive", "[your TTL]"};
ProcessBuilder processBuilder = new ProcessBuilder(arguments);
Process process = processBuilder.start();
As an alternative you can use Runtime.getRuntime().exec()

complete CMD command not running from 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()));
}
After this i am calling another function which is:
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();
}
}
The first function used to create the psql.log file, but now it does not even create it. Not sure where is the problem. Every time i run the code and from the second function,i get the printline that log file not found. The part before the redirection of the output of the cmd command works fine.
I tried process builder also..
I even tried it with 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();
I expect that the problem is that Runtime.getRuntime().exec(plpgsql) is splitting the command line into arguments incorrectly. Basically, exec does not understand quoting. Instead, it splits wherever it sees one or more spaces ... even if those spaces are in quotes.
The solution is to use the exec(String[]) overload, and pass each individual argument as a separate string; e.g.
.exec(new String[]{plpgsql_path,
"-U",
env.get("PG_USER"),
"-w,
"-h",
// etcetera
});
UPDATE
I didn't notice that you were using > output redirection as well1.
That doesn't work with exec either. (And the same applies to all shell syntax.) To get redirection, you need to use ProcessBuilder and one of the redirect methods.
The other alternative is to run the command in a shell. Pass the command as a string, and let the shell take care of the quote handling, substitution of environment variables, globbing, redirection ... and so on.
For example (if you were running on UNIX, Linux or MacOSX):
.exec(new String[]{"/bin/sh", "-c", plpgsql});
For Windows
.exec(new String[]{"cmd.exe", "/C", plpgsql});
Note the "/C" option in the Windows case!
1 - It serves you right for not line-breaking that ~200 character line in your source code! Check out what Java coding standards say about source line lengths ...

java Runtime.exec to run shell script

I am using Runtime.getRuntime().exec() to run a shell script from Java code. The code works fine when I pass the parameter as string
Runtime.getRuntime().exec("sh test.sh")
Since I have to pass additional arguments which are paths with spaces, so I replaced String with String array.
String[] cmd = {"sh test.sh", "/Path/to my/resource file"};
Runtime.getRuntime().exec(cmd)
I also tried with
String[] cmd = {"sh test.sh"};
Runtime.getRuntime().exec(cmd)
But neither of them worked. It's throwing an exception:
java.io.IOException: Cannot run program "sh test.sh":
java.io.IOException: error=2, No such file or directory
Why is the same script file when passed as String worked and when used with String array is throwing exception? How can I make this work with string array as argument to Runtime.exec()?
First string became the command. There is no file 'sh test.sh' to be executed.
Change
String[] cmd = {"sh test.sh", "/Path/to my/resource file"};
to
String[] cmd = {"sh", "test.sh", "/Path/to my/resource file"};
(In general use process builder API)

Bash script with multiple string arguments

I'm having problem separating two string variables as arguments for a bash script. My bash script takes two arguments like so:
#!/bin/bash
DATA1=$1
DATA2=$2
However, DATA1 and DATA2 are not what I intended, because bash is reading my strings wrongly. DATA2 is only the first part of the argument I wanted to put in, because I'm having trouble making a complicated(relatively) string into a single arguemnt.
I call this script from a Java app with variables like this:
String m1 = "some data";
String m2 = "some more"+mystring+"even more data"+anotherstring;
myscript.sh m1 m2
Only the first part of m2 is passed to DATA1 in the bash script. I've tried wrapping the whole thing in single quotes and double quotes I can't get it to accept the whole of m2 as the second argument.
Any help in creating two string arguments is appreciated.
It works for me, see:
Runtime.getRuntime().exec(new String[]{"/bin/sh", "/tmp/myscript.sh", m1,m2});
Your code calls:Runtime.getRuntime().exec(String)
It calls method exec(command,null,null) (see source code in src.zip) exec(String command, String[] envp, File dir) .
Method exec(String command, String[] envp, File dir) parse command by StringTokenizer. So text "some data" or "\"some data\"" is split to some data (or "some data ")

File copy using getRuntime().exec()

I am trying to copy a file. Here is the source. Note, des is string variable containing the URL.
Process process = Runtime.getRuntime().
exec("cmd.exe\t/c\tcopy\t"+source+"\t"+des);
Can anyone tell me why it does not work?
I think you should use FileUtils.copyFile() but anyways try this.
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/c";
command[2] = "copy";
command[3] = "test.java";
command[4] = "D:";
Process p = Runtime.getRuntime().exec (command);
Instead of passing your command as a single string construct an array and than pass it to exec.
I tried this
String command = "cmd /c copy test.java D:";
worked fine for me.
Advice:
Use ProcessBuilder to construct the Process.
That automatically takes care of '2' - break the command into parts.
Merge the output streams (not entirely necessary, but makes it simpler to ..).
Consume (and display) the output streams.
But in general, read and implement all the recommendations of When Runtime.exec() won't.
Runtime.exec, I believe, send the string to the command processor cmd.exe. So this is running cmd.exe, running another cmd.exe inside it, and passing your arguments. I don't have a Windows machine to test it on (thank Gods) but I think there are arguments to cmd.exe to tell it to run the arguments as a command line.
Why not just use FileUtils.copyFile()?

Categories

Resources