shell script if statement executed from java? - 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.

Related

Bash command not working with ProcessBuilder

The following command executes fine in bash:
Command:
bash -c "$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)" - -a -b
Output:
Equal to or more than 2 arguments - -a -b
Wanted to know - how can I achieve this using Java's ProcessBuilder?
I tried the following:
ProcessBuilder processBuilder = new ProcessBuilder(args);
where args are:
bash
-c
"$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)"
-
-a
-b
But I keep on getting the following error:
-: if: command not found
Process finished with exit code 127
Can someone please point out the issue here?
Command substitution results, in bash, don't go through all parsing steps. That means that compound commands like if aren't honored, command separators like ; have no syntactic meaning, etc.
If you want to override that and force an additional parsing pass, you need to use eval. Thus:
args = String[]{
"bash",
"-c",
"eval \"$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)\"",
"-",
"-a",
"-b",
}
Why did this work when you ran it in a shell, instead of from a ProcessBuilder? Because that shell you ran it in would perform the command substitution in "$(...)", and put the results of that substitution in the text it passed to the child shell; so the substitution was already done at parsing time.

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

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.

java processbuilder ffmpeg pipe

i try to run ffmpeg out java. here my code:
String[] temp = {"ffmpeg\\ffmpeg.exe","-i","input_track.ac3","-threads","0","-af","volume=volume="0.0"dB","-acodec","pcm_s32le","-ac","6","-ar","48000","-f","wav","-","|","ffmpeg\\fdkaac","--ignorelength","-m","1","-o","ouput_track.aac","-"};
ProcessBuilder pb = new ProcessBuilder(temp);
Process p = pb.start();
int ev = 0;
if (p.waitFor() != 0)
{
ev = p.exitValue();
}
i try the comand at windows cmd, here have a problem with "|" at the ffmpeg command line.
maybe someone say my fould?
best regards
This question is similar to How to make pipes work with Runtime.exec()? ... except that it is for Windows.
The problem is essentially the same: the exec methods don't understand shell syntax such as pipes, input or output direction and so on. The solution is essentially the same too: exec the appropriate shell and get that to handle the shell syntax.
In this case, try something like this:
String[] temp = new String[] {
"cmd", "/c",
"ffmpeg\\ffmpeg.exe -i input_track.ac3 -threads 0 " +
"-af volume=volume=\"0.0\"dB -acodec pcm_s32le -ac 6 " +
"-ar 48000 -f wav - | " +
"ffmpeg\\fdkaac --ignorelength -m 1 -o ouput_track.aac -"
};
Note that the actual command is a single string. (The quotes around the 0.0 look a bit strange, but that is what you have in your question.)
| is a shell pipe character, in java you'll have to either run this command in a shall (bash -c "the whole commandline | goes here"), or you'll have to run two processes (the one before the | and the one after), where the stdout of the first writes into the stdin of the second. For this, you'd typically use redirectOutput(Redirect.PIPE) and redirectInput(Redirect.PIPE).

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();

Get Unix Thread Dump

I am trying to get a unix (solaris and linux) thread dump on a java application.
1) When the java application is a tomcat web application,
using kill -3 , the dump goes to the catalina.out file, as this is standard output.
kill -3 pid > td.out does not work.
2) For another spring standalone java application, how do I find the standard output for it.
I have used:
kill -3 pid, and I have checked in my application logs, and I cannot find anything.
Please advise how I can determine standard output for the java application and see the thread dump.
Thanks,
B.
If you're using OpenJDK or Sun JDK 6 or later, try the jstack command in the bin folder. This is useful when redirecting standard out to a file is problematic for some reason. Execute the following, passing in the Java process ID:
jstack -l JAVA_PID > jstack.out
Try using Process
Process p = null;
String cmd[] = {"bash","-c","ps -C java | awk '{ print $1; }' | sed -n '2{p;q;}'"};
try
{
p = Runtime.getRuntime().exec(cmd);
try
{
p.waitFor();
System.out.println("Executed Successfully");
}catch(Exception e)
{
e.printStackTrace();
}
}catch(Exception e)
{
e.printStackTrace();
}
Then read the line by BufferReader and use the above function to kill and output the same
Explanation for the command :
ps -C java | awk '{ print $1; }' | sed -n '2{p;q;}'
" ps -C ProcessName " tells the process if its running with pid, here Java is used as ProcessName
" awk '{ print $1; }' " outputs the 1st row of the output
" sed -n '2{p;q;} " to display the 2nd column

Categories