I am trying to run this dreadfully simple command in Bash
java -cp nasa-top-secret.jar gov.nasa.RocketToMoon | grep -v codehaus
but grep is not working (it does not filter out my string). How can I filter my java output using grep?
The output could be on STDERR, Try this instead:
java -cp nasa-top-secret.jar gov.nasa.RocketToMoon 2>&1 | grep -v codehaus
possible scenario
you actually have all the lines with
"codehaus", so grep -v gives you
nothing. I assume you know what -v
stands for.
your java program did not print
anything to stdout. check your
source and make sure your program spits out to stdout. Otherwise, check if its stderr that your program is spitting out.
possible troubleshooting step:
remove the pipe to grep, run only the java program and make
sure your program has output.
put 2>&1 at the end of the command
and try again with grep
Related
I have some java code which uses jsch to connect to our unix servers and run below command.
ls -lt /tempdirectory/ grep -v '^do | grep "$"(date '+%b %e')" | head
-1 | awk '{print %9}'
Above command shows all files in the /tempdirectory in long format (the first pipe removes directories). From the result it then filters for all files which were created today (I.e. it greps for "Oct 16"). Since I did ls -lt the files are ordered by time, so when I pipe against head -1 I will get the latest file today. And then the last pipe will print the filename out
On a normal putty terminal, once I switch to bash shell, and run above command, it will correctly print out the latest file today.
But the default shell seems to be Bourne (-sh) which the above command will fail (and hence my code will fail)
Is there a way to create above command that is safe for common shells? I think the main shells I've seen at work are:
Bourne (sh)
Bourne again (bash)
Korn (ksh)
This is where you should be using the find(1) command instead:
$ find /tmpdir -type f -ctime -1
gets all the files from /tmpdir created (ctime) today.
If you want all the files then you don't need any more modifiers. If you want to limit further, see the GNU Find manpage at https://linux.die.net/man/1/find.
The find(1) command is independent of which shell you have access to on the remote machine.
The code that you posted
ls -lt / grep -v '^do | grep "$"(date '+%b %e')" | head -1 |awk'{print %9}'
has syntax errors and cannot be run in any shell
Fixed it to
ls -lt /tempdirectory/ | grep -v '^d' | grep "$(date '+%b %e')" | head -1 | awk '{print $9}'
It is ANSI compatible and runs in sh, bash and zsh (what I have tested).
As per comments, I found the issue. Bourne cannot handle $(...) hence I needed to replace this with --> ` <--- (not the regular apostrophes)
Reference:
https://www.unix.com/shell-programming-and-scripting/188983-syntax-error-line-24-unexpected.html
So the command becomes
ls -lt /tempdirectory/ | grep -v '^d' | grep "date '+%b %e'" | head -1 | awk '{print $9}'
I dont whether this will work on many different shells but it seems to work on sh as well as bash
For some reason StackOverflow is not showing that apostrophe properly so I will clarify that I added the weird other apostrophe ` after the first double quote and before the last double quote in:
"{here}date '+%b %e'{here}"
(Also based on previous comments, it sounds like this is not just a matter of what shell you are using when determining command compatibility - your underlying OS may also have an impact. In my case, using uname -a shows i am using sunOS)
I am running java -jar xyz.jar command on the linux terminal. I have both system.out.println statements and System.exit statements in the code.
how to capture the system.exit or output to the OS on the linux? do i need to prepare a linux script for this?
This may be off-topic for SO.
You just redirect it:
java -jar xyz.jar > the_file_to_output
If you used System.err output as well as System.out output and wanted to redirect both, it's a tiny bit more complicated because you need to redirect out to the file and then redirect error to out:
java -jar xyz.jar > the_file_to_output 2>&1
The 2>&1 thing is what redirects error (standard stream #2) to out (standard stream #1). Note that the order matters, you have to do that after redirecting out to the file.
Java works as any other command.
If you want standard output (or error output) you can work with usual I/O operators: > 2> >> |
java -jar xyz.jar > output.file
java -jar xyz.jar | sort | less
For getting System.exit value you have special variable $?
java -jar xyz.jar
echo $?
To get more info Exit status and I/O redirection
I am running a job in Jenkins(Jenkins is an open source continuous integration tool) by executing a list of shell commands. One of the command is to run a Java program which does some data validation. If meets with invalid date, the Java program will exit with a none-zero exit code so that Jenkins can discover that this time the build fails.
Unfortunately the Java program prints too much log to stdout and stderr, only a few of them are useful. Since the Java program can not be modified, I decide to filter the output with grep. So I wrote the shell as:
java -cp $CLASSPATH MetaValidatorMain | grep -v "useless keyword1"| grep -v "useless keyword2"
But the problem is that, after the execution of the line of shell, the parent process(Jenkins) got exit code of grep indead of java, so that Jenkins could not determine whether the build was success.
I also tried this:
(java -cp $CLASSPATH MetaValidatorMain || exit 1) | grep -v "useless keyword1"| grep -v "useless keyword2"
also did not work.
Could anyone tell me how could I write the line of shell to filter output and obtain the right exit code at the same.
thx
Bit of a long way round, but you could redirect the program output to a file, capture the return and then grep the output file for the content you want:
java -cp $CLASSPATH MetaValidatorMain > /tmp/outfile.txt 2>&1
RETURN_CODE=$?
grep -v "useless keyword1" /tmp/outfile | grep -v "useless keyword2"
exit RETURN_CODE
There are 3 ways of doing this. However your current setup should work. The reason here being that the grep won't match anything if the command fails, so grep will return with status 1 (unless the program always shows that text no matter what).
Pipefail
The first way is to set the pipefail option. This is the simplest and what it does is basically set the exit status $? to the exit code of the last program to exit non-zero (or zero if all exited successfully).
# false | true; echo $?
0
# set -o pipefail
# false | true; echo $?
1
$PIPESTATUS
Bash also has a variable called $PIPESTATUS which contains the exit status of all the programs in the last command.
# true | true; echo "${PIPESTATUS[#]}"
0 0
# false | true; echo "${PIPESTATUS[#]}"
1 0
# false | true; echo "${PIPESTATUS[0]}"
1
# true | false; echo "${PIPESTATUS[#]}"
0 1
You can use the 3rd command example to get the specific value in the pipeline that you need.
This solution might not be available though. I think $PIPESTATUS might have been added in a fairly recent version of bash, and your OS may not have it.
Separate executions
This is the most unwieldy of the solutions. Run each command separately and capture the status
# java -cp $CLASSPATH MetaValidatorMain > /tmp/outfile.txt 2>&1
# RETURN_CODE=$?
# grep -v "useless keyword1" /tmp/outfile | grep -v "useless keyword2"
# exit RETURN_CODE
I have a java program that stops often due to errors which is logged in a .log file. What can be a simple shell script to detect a particular text line say
stream closed
and then run the following command
java -jar xyz.jar
Here's a bash script to do something like that (may contain typos):
#!/bin/bash
tail -f logfile.txt | grep "stream closed" |
while read line
do
java -jar xyz.jar
done
if grep 'stream closed' filename.log >/dev/null
then java -jar xyz.jar
fi
T1="`cat youfile.log | grep 'stream closed'`"
if [ "$T1" = "stream closed" ]; then
java -jar xyz.jar
fi
I am developing an application where i required to run some of the scripts of unix from Java Code.
Platform i am using is Unix, Tomcat 5.5..
For that, My Sample Code is as follows :
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("netstat -i|tail -n +3|cut -d ' ' -f1");
System.out.println("exitValue = "+proc.exitValue());
I have given all the rights to tomcat user.
Now, my program output cases are :
Script exitValue()
======= ============
netstat -i 0
netstat -i|tail -n +3 4
sudo netstat -i 1
sudo netstat -i|tail -n +3 1
Above table suggest that only 1st script is executing in unix, all others are failing.
I am not sure, but i am just assuming that i have to run Tomcat Server as a root user..
Can anybody have any other solution, then please reply..
Thanks in advance...
If I remember correctly, pipes ("|") are handled by the shell. Java will probably not handle them at all ...
There are a few workarounds :
run bash with your commands as a parameter :
runtime.exec("bash -c \"netstat -i|tail -n +3|cut -d ' ' -f1\"");
write a bash script that run all those commands and run this script from Java :
#!/bin/bash
netstat -i|tail -n +3|cut -d ' ' -f1
create the pipes in Java : read the output of netstat -i and connect it in Java to tail -n +3 ...
Using | to chain commands in Unix is part of the shell, and Runtime.exec() runs the command directly, not though the shell. A quick fix may be (untested as I don't have a Unix box available at this moment) to prefix the shell as the first command.
Process proc = runtime.exec("/bin/sh netstat -i|tail -n +3|cut -d ' ' -f1");
Got the solution of above problem..
I have just created simple shell script file, and put the script inside that .sh file.
Now at the java side, i am just calling simple shell script file..
Process proc = runtime.exec("sh /usr/tmp/try1.sh");
That's it!!!