How can I kill a just started Java process in shell script? - java

I have this simple script where I execute a .jar file and I'd need its PID for killing it after the sleep command:
java -jar test.jar &> output.txt & pid=$! sleep 10
The problem is: the PID changes after the application gets fully launched, this pid I get in first place is not the same PID the application has after 10 seconds sleeping (I checked it using ps).
How can I track down the PID so that I can kill the fully launched application?
I've tried using pstree -p $pid but I get a long list of Java children processes and I thought there might be a better way to implement this other than getting every child process, extracting PID using grep and killing it, also because I'm not 100% sure this is working.
I found another solution using jps but I'd prefer use native linux commands for compatibility.
I don't necessarily need PID, using process name could be a way but I don't how to retrieve that either having only parent process' PID.

If you want to use process name, might run :
$ kill -9 $(ps aux | grep '[t]est.jar' | awk '{print $2}')
Options Details:
kill: sends a kill signal (SIGTERM 15: Termination) to terminate any process gracefully.
kill -9: sends a kill signal (SIGTERM 9:Kill) terminate any process immediately.
ps: listing all processes.
grep: filtering, [p] prevent actual grep process from showing up in ps results.
awk: gives the second field of each line, which is PID. (ps output : $1:user, $2:pid ...)

Two ways.
use system. Exit() inbuilt function.
or
redirect the pid number to a file and use later to kill the process.
Ex:-
java -jar test.jar &> output.txt & echo $! > pid-logs
cat pid-logs | xargs kill -9

Related

Getting PID of a process that has just started

I am working on a Gradle Java project. Which starts Tomcat for testing and stops it later.
I am supposed to kill this Tomcat instance when the test fails.
I tried using "ps aux| grep tomcat | grep -v grap | awk {print $2}" command to get the process id and kill the process.
But on Production, there will be so many Tomcat processes running simultaneously by many users, I just want the tomcat process started by my build.gradle for test execution.
So how can I accomplish the task? Please provide me some guidelines.
You need to find a unique string in the output of 'ps aux' which differentiates your test tomcat and others'.
I currently use the below script to run 'shutdown.sh' first and then kill the PID as most of the times, the application stops but the process does not stop.
PID=`ps -ef | grep $JAVA_HOME/bin/java | grep "$TOMCAT_LOC"/conf | grep -v grep | awk '{ print $2 }'`
if [ $PID ]; then
echo tomcat is running with PID:$PID.
# Stop or Kill running Tomcat
if [[ -f $TOMCAT_LOC/bin/shutdown.sh ]]; then
[[ ! -x $TOMCAT_LOC/bin/shutdown.sh ]] && chmod a+x $TOMCAT_LOC/bin/shutdown.sh
$TOMCAT_LOC/bin/shutdown.sh >>/dev/null
sleep 20
fi
kill -9 $PID
sleep 3
else
echo tomcat is not running
fi
You may also look at configuring a PID file by editing the 'catalina.sh' which you can read later to find out your PID.
# CATALINA_PID (Optional) Path of the file which should contains the pid
# of the catalina startup java process, when start (fork) is
# used
Java JRE has tool called jps in $JAVA_HOME/bin folder.
It's similar to unix ps command but for java only.
You can use it to determined exac java process you need.
Using this tool is more recommended and actually it is more useful, when you have more than one java applications is running on your host...
for example I have running h2 database and many other apps, but wanna kill only h2, so I can use jps to get it PID
$ jps
17810 GradleDaemon
17798 GradleWrapperMain
17816 h2-1.4.197.jar
17817 GradleDaemon
17818 GradleDaemon
18011 Jps
16479
and then just kill needed process:
kill -9 17816
and all other java apps will continue work normally. I not sure about tomcat, but I think it can be done in similar way, something like that:
kill -9 $(jps | grep tomcat | awk '{print $1}')
Lastly, little bit offtopic, but a specially to your case: correct way would be using start/stop/restart scripts provided by tomcat
The correct way to terminate a Tomcat instance is via its own shutdown command. You should not be thinking of processes, or PIDs, or kills, at all.
so if you want to kill tomcat from that user from which you have logged in then try following and let me know if this helps you.
ps -ef | grep -v grep | grep `whoami` | grep tomcat
So by ps -ef I am listing all the processes then grep -v grep will remove the grep command's process then grep whoami will look for your currently logged in user then grep tomcat will look only for tomcat process, test it once and if All is Well then you could kill it.
By the way how about tomcat stop script? In case it is there you could use that also.
You can use shell variable $!. It represents the PID of the most recent background command.
yourCommand &
CMD_PID=$!
echo $CMD_PID

How do I get the PID of this Java app?

I have a java app on my (Ubuntu) server. If I do this, then it starts correctly:
/usr/bin/java -cp /home/jenkins/veta/lily.jar com.sugarapp.lily.Main
but I don't know how to get its PID. I don't know how to stop it with an init.d script.
I have a different app, written in Clojure, and for it I was able to write an init.d script that works great. So I tried to refashion that init.d script for my Java app, and this is what I got:
WORK_DIR="/home/jenkins/veta"
NAME="lily"
JAR="lily.jar"
USER="jenkins"
DAEMON="/usr/bin/java"
DAEMON_ARGS=" -cp /home/jenkins/veta/lily.jar com.sugarapp.lily.Main"
start () {
echo "Starting lily..."
if [ ! -f $WORK_DIR/lily.pid ]; then
/sbin/start-stop-daemon --start --verbose --background --chdir $WORK_DIR --exec $DAEMON --pidfile $WORK_DIR/lily.pid --chuid "$USER" --make-pidfile -- $DAEMON_ARGS
else
echo "lily is already running..."
fi
}
stop () {
echo "Stopping lily..."
/sbin/start-stop-daemon --stop --exec $DAEMON --pidfile $WORK_DIR/lily.pid
rm $WORK_DIR/lily.pid
}
But this doesn't work. Although the PID in $WORK_DIR/lily.pid changes every time I run the script, no process with that PID ever seems to run. If I try:
ps aux | grep java
I don't see this app, nor if I try using the PID.
So is there a way I can use the first command, but somehow capture the PID, so I can store it for later?
I just want a reliable way to stop and start this app. That can be by PID or some other factor. I'm open to suggestions.
UPDATE:
Maybe my question is unclear? Something like jps or ps will give me too many answers. If I do something like "ps aux | grep java" I'll see that there are 5 different java apps running on the server. The start-stop-daemon won't know which PID belongs to this particular app, nor can I figure out what I should feed into my init.d script.
If your system has jdk installed there is an utility called jps which resides in jdk/bin. It will display the list of running java process. Make use of it.
If jdk is not installed in your machine then you have to grep the java process from ps -eaf command.
If you want the pid from the command line, this might work:
myCommand & echo $!
Which I copied from the accepted response to a very similar topic in ServerFault: https://serverfault.com/a/205504

Why do I see multiple running instances of the same service (Elasticsearch) on Ubuntu, but only one is responsive?

I am running Elasticsearch (ES) on a small AWS Ubuntu box, and working on tuning the performance of the box overall.
After a recent deploy using Saltstack, I noticed the number of running instances went from two to three -- after being at two for several months. The uptick in instances seems to correspond to an uptick in memory usage.
I confirmed with ps that there are three java processes running on the box:
PID TTY TIME CMD
9295 ? 00:02:08 java
14398 ? 00:00:12 java
26175 ? 00:40:48 java
When I stop ES with command "sudo service elasticsearch stop", I was still left with two ES processes running according to ps:
PID TTY TIME CMD
9295 ? 00:02:08 java
26175 ? 00:40:48 java
I restarted the service and then I had three again. This seems really strange two me because it seemed like two of the services were unresponsive to the stop command. (Could this be a so-called Zombie or Orphan process?)
I manually killed all three processes and restarted ES, and now have only a single ES instance. I wondered if these wayward java processes were related to some other service, but after killing all three, New Relic confirmed a large drop in memory usage and processes -- so they were definitely all ES-related processes:
My question is why, after a deploy, would the number of running instances go up?
Is there a functional Elasticsearch reason for this, or was this a bug?
What would cause either Elasticsearch or any service on Ubuntu in general to go into this unresponsive state?
Any insight is greatly appreciated!
What do you get when running this command:
lsof -i :9200-9399 | tail -n +2 | awk '{print $2}' | xargs ps -p
lsof -i :9200-9399 will list all open files on the port range 9200-9399, i.e. the default port range used by ES. Change the range if your configuration differs.
tail -n +2 will ditch the first output line from the lsof command, it contains column headers and it's not useful
awk '{print $2}' will fetch only the process id (PID) from the lsof output
Finally, xargs ps -p will run the ps command to find out what process runs under the PID fetched by the awk command.
You should get an output like below and that might get you started in your investigation.
PID TTY TIME CMD
21199 ttys011 4:39.26 /usr/bin/java -Xms256m -Xmx1g....
22234 ttys012 5:12.22 /usr/bin/java -Xms256m -Xmx1g....
23444 ttys013 3:33.54 /usr/bin/java -Xms256m -Xmx1g....

terminal - run java app in background and how to close it?

I have game server and I want to launch it on Asustor NAS Server. I have PuTTy and I write
nohup java -jar server.jar &
Good, it launch in background, but now I want to close it. How to do it? And how to know if app is running or not?
Normally when starting you get the pid returend like so:
~ $ nohup java -jar server.jar &
[1] 3305
~ $ nohup: ignoring input and appending output to ‘nohup.out’
to see if it is running you can issue
~ $ ps -ef | grep server
user1 3305 2936 0 13:58 pts/1 00:00:00 java -jar server.jar
if you see a line like the above it is running. You may also hava a look at the nohup.out file, which is written to the directory you started the server in, by using
tail nohup.out
to kill the process issue kill . Where pid is the process id, you either remembered, or will find out by looking at the second row of the "ps -ef | grep server" command, in our case 3305
kill 3305
kill without options tries to end the process gracefully. Read more abut kill and ps by using
man kill
and
man ps
respectively.
Try like this.
Get number of your job using:
jobs
then use fg command:
fg %job_num
When it will be on foreground you can press CTRL+C to kill the process.

Get pid from a java subprocess started with xvfb-run

I'm trying to get the PID of a java process started with xvfb-run. When started without xvfb-run, I use $! to get the PID of the last backgrounded process but as soon as I use xvfb-run I obviously get the PID of xvfb-run.
Here is the code:
#! /bin/bash
logfile=/var/log/SleepTest.log
pidfile=/var/run/SleepTest.pid
command="java -jar /data/test/SleepTest.jar"
( eval exec -c xvfb-run $command < /dev/null >> $logfile 2>&1 ) &
$! > $pidfile
If I remove the xvfb-run part in the second last line, everything works ok (except the part that I don't have a display and the program crash). I probably have to play with the "()" and "&" but I'm not an expert.
The program SleepTest.jar is a small program I wrote so I don't have to deal with the real thing. It only sleep for 2 minutes.
For those wondering why I use xvfb-run, it's because the java application I need to start use SWT and I don't have display on my server.
For those wondering why I need the pid of the process, it's because I want to create a init.d file to be able to start|stop|status my application
So is there a simple way to get it ?
Run your entire script with xvfb-run (e.g. xvfb-run name_of_script.sh), and remove the xvfb-run from your eval line.

Categories

Resources