How can I cut the 3rd line from java -version? - linux

To preface this, yes, I have already searched for ways to do this with cut, sed, and tail. However, I have found that none of the traditional ways of obtaining the third line of an output work.
java -version | sed 3p
java -version | tail -1
java -version | cut -d$'\n' -f3
All of these commands simply return the same thing as
java -version
What's going on here? How can I get only the third line?

java -version 2>&1 | tail -1

Related

How to isolate part of a line of text in order to use it as a variable

I'm creating bash script and want to check version number of program from a line in a file and use it to make different checks and operations.
The version line in file is looking like this (examples):
Program Version 1.3
or
Program Version 1.3.1
It's on different lines in different versions but always follow the same syntax. How to remove the first part and isolate only the version number in order to put it in a variable?
Using GNU grep with -P for perl-style regEx match, and -o flag to return only the matching pattern.
grep -oP 'Program Version \K[^ ]*' file
1.3.1
To save it in a variable
versionNo="$(grep -oP 'Program Version \K[^ ]*' file)"
printf "%s\n" "$versionNo"
1.3.1
Use perl regEx itself,
perl -lne 'print "$1" if /^Program Version (\d.+)/' file
1.3.1
in variable,
versionNo="$(perl -lne 'print "$1" if /^Program Version (\d.+)/' file)" file
printf "%s\n" "$versionNo"
1.3.1
Using GNU sed
sed -r 's/Program Version ([[:digit:]].+).*/\1/' file
1.3.1
and
versionNo="$(sed -r 's/Program Version ([[:digit:]].+).*/\1/' file)" file
printf "%s\n" "$versionNo"
1.3.1
I guess you obtain that Program Version 1.3.1 for example launching some kind of command. Well, try this:
#!/bin/bash
version=$(yourCommandWhichShowsVersion 2> /dev/null | egrep "^Program Version [0-9]" | awk '{print $3}')
Explanation:
You need to launch the command which show the version
You redirect the output to egrep which search through all lines matching only which starts ^ <- this is to start string, with the desired text Program Version, and this [0-9] is to match one number. If you don't know if the version can be 1.3 or 1.3.1 or 1 that's all you need.
awk is going to "select" the second column (first is "Program version" and second is the version number)
Good luck!
Value=$(cat program.txt | grep Program\ Version\ | sed "s/Program \Version\ //g")
Just finds Program Version then strip it out with sed.
Edit: Sorry misread. Removed version number
I would just use grep and cut for this, since the pattern is fixed:
# find the first occurrence of the line (-m 1) starting with the pattern (^) and
# the third field (cut -f3) is the version
# this makes sure we ignore
# a) multiple occurrences of the pattern, if any
# b) occurrence of "Program Version" anywhere else on a line
# we make no assumption about the format of the version number
version=$(grep -m 1 "^Program Version " program.txt | cut -f3 -d' ')
if [[ -z $version ]]; then
# version not specified
# your exception handler here
fi
Some possible solutions for the problem:
awk awk '/Program Version/{print $3}' file.txt
grep grep -oP "Program Version \K[^ ]*" file.txt
sed sed -n '/Program Version /s///p' file.txt
perl perl -lane 'if (/Program Version/) {print $F[2]}' file.txt
(HTH) Hope This Helps.
Here is what I have used at the end:
Version=`find . -type f -name "filename" -exec grep -h 'Program Version' {} + | awk -F " " '{print $3}'`
I have used find + grep to receive the line with the version that I need and -f in awk to define field separator to be blank space and with that I have separated the version number from the rest of the results. Thank you all for your answers.

how to get only version number of a program? pipe into grep

rsync --version
gives lots of info but I just want to grab the first line
rsync version 3.1.1
How to do this? I tried to pipe into grep but I can't
There are lots of ways to slice this pie. If you want the whole first line, you can use any of these:
rsync --version | head -n 1
rsync --version | awk NR==1
rsync --version | sed -n 1p
rsync --version | grep '^rsync *version'
If you want just the version number without the rest of the line, that's not much harder, but it depends which part of the line you want. On my Mac, the version line reads rsync version 2.6.9 protocol version 29, and a naïve grab would likely yield the 29 - presumably not what you want. Either of the following will output just the 2.6.9 by itself:
rsync --version | awk 'NR==1 {print $3}'
rsync --version | sed -n '1s/^rsync *version \([0-9.]*\).*$/\1/p'
If you just need to get the first line of output use head command
rsync --version | head -1

How to fetch Java version using single line command in Linux

I want to fetch the Java version in Linux in a single command.
I am new to awk so I am trying something like
java -version|awk '{print$3}'
But that does not return the version. How would I fetch the 1.6.0_21 from the below Java version output?
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) 64-Bit Server VM (build 17.0-b16, mixed mode)
Redirect stderr to stdout.
Get first line
Filter the version number.
java -version 2>&1 | head -n 1 | awk -F '"' '{print $2}'
This is a slight variation, but PJW's solution didn't quite work for me:
java -version 2>&1 | head -n 1 | cut -d'"' -f2
just cut the string on the delimiter " (double quotes) and get the second field.
I'd suggest using grep -i version to make sure you get the right line containing the version string. If you have the environment variable JAVA_OPTIONS set, openjdk will print the java options before printing the version information. This version returns 1.6, 1.7 etc.
java -version 2>&1 | grep -i version | cut -d'"' -f2 | cut -d'.' -f1-2
Since (at least on my linux system) the version string looks like "1.8.0_45":
#!/bin/bash
function checkJavaVers {
for token in $(java -version 2>&1)
do
if [[ $token =~ \"([[:digit:]])\.([[:digit:]])\.(.*)\" ]]
then
export JAVA_MAJOR=${BASH_REMATCH[1]}
export JAVA_MINOR=${BASH_REMATCH[2]}
export JAVA_BUILD=${BASH_REMATCH[3]}
return 0
fi
done
return 1
}
#test
checkJavaVers || { echo "check failed" ; exit; }
echo "$JAVA_MAJOR $JAVA_MINOR $JAVA_BUILD"
~
You can use --version and in that case it's not required to redirect to stdout
java --version | head -1 | cut -f2 -d' '
From java help
-version print product version to the error stream and exit
--version print product version to the output stream and exit
Here's my variation (with thanks/acknowledgements to many answers prior to this). My goal is to produce a "Major Version" in line with JEP 223. Assumption are made; I don't know if it works across the board for all released (or to be released) versions of java.
java -version 2>&1 | fgrep -i version | cut -d'"' -f2 | sed -e 's/^1\./1\%/' -e 's/\..*//' -e 's/%/./'
Version
Results
1.6.0_65
1.6
1.8.0_282
1.8
11.0.10
11
15.0.2
15
This way works for me.
# java -version 2>&1|awk '/version/ {gsub("\"","") ; print $NF}'
1.8.0_171
Getting only the "major" build #:
java -version 2>&1 | head -n 1 | awk -F'["_.]' '{print $3}'

List of Java processes

How can I list all Java processes in bash?
I need an command line. I know there is command ps but I don't know what parameters I need to use.
try:
ps aux | grep java
and see how you get on
Recent Java comes with Java Virtual Machine Process Status Tool "jps"
http://download.oracle.com/javase/1.5.0/docs/tooldocs/share/jps.html
For example,
[nsushkin#fulton support]$ jps -m
2120 Main --userdir /home/nsushkin/.netbeans/7.0 --branding nb
26546 charles.jar
17600 Jps -m
jps -lV
is most useful. Prints just pid and qualified main class name:
2472 com.intellij.idea.Main
11111 sun.tools.jps.Jps
9030 play.server.Server
2752 org.jetbrains.idea.maven.server.RemoteMavenServer
Starting from Java 7, the simplest way and less error prone is to simply use the command jcmd that is part of the JDK such that it will work the same way on all OS.
Example:
> jcmd
5485 sun.tools.jcmd.JCmd
2125 MyProgram
jcmd allows to send diagnostic command requests to a running Java
Virtual Machine (JVM).
More details about how to use jcmd.
See also the jcmd Utility
You can use single command pgrep as well (doesn't require you to use pipes and multiple commands):
pgrep -fl java
For better output format check this command:
ps -fC java
This will return all the running java processes in linux environment. Then you can kill the process using the process ID.
ps -e|grep java
ps aux | grep java
or
$ ps -fea|grep -i java
pgrep -l java
ps -ef | grep java
If I want simply list java processes, use:
ps -A | grep java
ps axuwww | grep java | grep -v grep
The above will
show you all processes with long lines (arg: www)
filter (grep) only lines what contain the word java, and
filter out the line "grep java" :)
(btw, this example is not the effective one, but simple to remember) ;)
you can pipe the above to another commands, for example:
ps axuwww | grep java | grep -v grep | sed '.....' | while read something
do
something_another $something
done
etc...
When I want to know if a certain Java class is getting executed, I use the following command line:
ps ww -f -C java | grep "fully.qualified.name.of.class"
From the OS side view, the process's command name is "java". The "ww" option widens the colum's maximum characters, so it's possible to grep the FQN of the related class.
jps & jcmd wasn't showing me any results when I tried it using using openjdk-1.8 on redhat linux. But even if it did it only shows processes under the current user which doesn't work in my case. Using the ps|grep is what I ended up doing but the class path for some java apps can be extremely long which makes results illegible so I used sed to remove it. This is a bit rough still but removes everything except: PID, User, java-class/jar, args.
ps -o pid,user,cmd -C java | sed -e 's/\([0-9]\+ *[^ ]*\) *[^ ]* *\([^$]*\)/\1 \2/' -e 's/-c[^ ]* [^ ]* \|-[^ ]* //g'
Results look something like:
PID USER CMD
11251 userb org.apache.zookeeper.server.quorum.QuorumPeerMain ../config/zookeeper.properties
19574 userb com.intellij.idea.Main
28807 root org.apache.nifi.bootstrap.RunNiFi run
28829 root org.apache.nifi.NiFi
An alternative on windows to list all processes is:
WMIC path win32_process where "Caption='java.exe'" get ProcessId,Commandline
But that is going to need some parsing to make it more legible.
There's a lot of ways of doing this. You can use java.lang.ProcessBuilder and "pgrep" to get the process id (PID) with something like: pgrep -fl java | awk {'print $1'}. Or, if you are running under Linux, you can query the /proc directory.
I know, this seems horrible, and non portable, and even poorly implemented, I agree. But because Java actually runs in a VM, for some absurd reason that I can't really figure out after more then 15 years working the JDK, is why it isn't possible to see things outside the JVM space, it's really ridiculous with you think about it. You can do everything else, even fork and join child processes (those were an horrible way of multitasking when the world didn't know about threads or pthreads, what a hell! what's going in on with Java?! :).
This will give an immense discussion I know, but anyways, there's a very good API that I already used in my projects and it's stable enough (it's OSS so you still need to stress test every version you use before really trusting the API): https://github.com/jezhumble/javasysmon
JavaDoc: http://jezhumble.github.io/javasysmon/, search for the class com.jezhumble.javasysmon.OsProcess, she will do the trick. Hope it helped, best of luck.
ps -eaf | grep [j]ava
It's better since it will only show you the active processes not including this command that also got java string the [] does the trick
I use this (good on Debian 8):
alias psj='ps --no-headers -ww -C java -o pid,user,start_time,command'
The following commands will return only Java ProcessIDs. These commands are very useful especially whenever you want to feed another process by these return values (java PIDs).
sudo netstat -nlpt | awk '/java/ {print $7}' | tr '/java' ' '
sudo netstat -nlpt | awk '/java/ {print $7}' | sed 's/\/java/ /g'
But if you remove the latest pipe, you will be noticed these are java process
sudo netstat -nlpt | awk '/java/ {print $7}'
sudo netstat -nlpt | awk '/java/ {print $7}'
To know the list of java running on the linux machine.
ps -e | grep java

Why no output is shown when using grep twice?

Basically I'm wondering why this doesn't output anything:
tail --follow=name file.txt | grep something | grep something_else
You can assume that it should produce output I have run another line to confirm
cat file.txt | grep something | grep something_else
It seems like you can't pipe the output of tail more than once!? Anyone know what the deal is and is there a solution?
EDIT:
To answer the questions so far, the file definitely has contents that should be displayed by the grep. As evidence if the grep is done like so:
tail --follow=name file.txt | grep something
Output shows up correctly, but if this is used instead:
tail --follow=name file.txt | grep something | grep something
No output is shown.
If at all helpful I am running ubuntu 10.04
You might also run into a problem with grep buffering when inside a pipe.
ie, you don't see the output from
tail --follow=name file.txt | grep something > output.txt
since grep will buffer its own output.
Use the --line-buffered switch for grep to work around this:
tail --follow=name file.txt | grep --line-buffered something > output.txt
This is useful if you want to get the results of the follow into the output.txt file as rapidly as possible.
Figured out what was going on here. It turns out that the command is working it's just that the output takes a long time to reach the console (approx 120 seconds in my case). This is because the buffer on the standard out is not written each line but rather each block. So instead of getting every line from the file as it was being written I would get a giant block every 2 minutes or so.
It should be noted that this works correctly:
tail file.txt | grep something | grep something
It is the following of the file with --follow=name that is problematic.
For my purposes I found a way around it, what I was intending to do was capture the output of the first grep to a file, so the command would be:
tail --follow=name file.txt | grep something > output.txt
A way around this is to use the script command like so:
script -c 'tail --follow=name file.txt | grep something' output.txt
Script captures the output of the command and writes it to file, thus avoiding the second pipe.
This has effectively worked around the issue for me, and I have explained why the command wasn't working as I expected, problem solved.
FYI, These other stackoverflow questions are related:
Trick an application into thinking its stdin is interactive, not a pipe
Force another program's standard output to be unbuffered using Python
You do know that tail starts by default with the last ten lines of the file? My guess is everything the cat version found is well into the past. Try tail -n+1 --follow=name file.txt to start from the beginning of the file.
works for me on Mac without --follow=name
bash-3.2$ tail delme.txt | grep po
position.bin
position.lrn
bash-3.2$ tail delme.txt | grep po | grep lr
position.lrn
grep pattern filename | grep pattern | grep pattern | grep pattern ......

Resources