how to enable some commands during run time in a shell script - linux

I have written 1 shell script to run Jstack command for a particular Process ID (PID).
But some time it may happen that multiple PIDs are there in a server for Java process.
At that case i want to run that many Jstack commands giving respective PIDs as input to the command.
Eg. If one application has 2 servers (1 tomcat and 1 jboss), then I need to run 2 JStack commands to capture 2 different logs for 2 processes.
So how to handle or check so that the script will automatically decide how many PIDs r there for java process and will run the commands written inside the script?
My script is getting all the PIDs active by
PID1=$(ps -ef|grep java|grep jboss| awk '{print $2}' )
and
PID2=$(ps -ef|grep java|grep tomcat| awk '{print $2}' )
after that I am running Jstack commands as
jstack $PID1 > jStack1.txt & and jstack $PID2 > jStack2.txt &

To get the pid you can just use pgrep instead of ps/grep/grep/awk:
for pid in $(pgrep -f "tomcat|jboss")
do
jstack $pid >> jStack1.txt
done

you need to combine the pids into one list and loop round them.
So something like this to get a seperate file for each pid:
for pid in $( ps -ef | egrep "tomcat|jboss" | awk '{print $2}')
do
jstack $pid > jstack.$pid.txt
done
Following on from your last comment
I'm not sure what you are trying to do with the array and multiple jstack calls in the loop as it will iterate once for each pid, not give you two pids in the loop, and the $0 & $1 indices don't make sense (did you mean just 0 & 1?), and you are using $N each time but the increment for it is commented out so will stay as 0.
If you are sure there can only be two pids, one for tomcat and one for jboss, then your inital code with sleeps added would do it:
#!/bin/bash
Sleep1=$1
# sleep for the first requested time
sleep $Sleep1
# do the tomcat jstack
PID1=$(ps -ef | grep java| grep tomcat | awk '{print $2}')
jstack $PID1 > jstack.tomcat.$PID1.txt
# sleep for another 60secs
sleep 60
# do the jboss jstack
PID2=$(ps -ef | grep java| egrep "jboss|JBoss" | awk '{print $2}')
jstack $PID2 > jstack.jboss.$PID1.txt
If there can be multiple tomcat processes and multiple jboss processes, then you need two loops:
#!/bin/bash
Sleep1 = $1
# sleep for the first requested time
sleep = $Sleep1
# Do all the tomcat jstacks
for pid in $(ps -ef | grep java| grep "tomcat" | awk '{print $2}')
do
jstack $pid > jstack.tomcat.${pid}.txt )
done
# sleep for another 60secs
sleep 60
# Do all the jboss jstacks
for pid in $(ps -ef | grep java| egrep "jboss|JBoss" | awk '{print $2}')
do
jstack $pid > jstack.jboss.${pid}.txt )
done
Or some combinations of these methods could be used depending on exactly what you are after.

Related

Shell script executes fail

I wrote a shell script for restart celery. My os is Ubuntu 16.04.3.
I try to run this shell script, just killed celery processes, but not start
a new celery processes. Why?
This is my code.
ps -ef | grep celery | awk '{print $2}' | grep -v grep |xargs kill -9;
celery -A loan_app.tasks worker --loglevel=info --workdir=`pwd` --logfile=/tmp/celery.log --pidfile=/var/run/celery_pid -D
From official documentation:
http://docs.celeryproject.org/en/latest/userguide/workers.html
Please read the text highlighted in bold.
Stopping the worker
Shutdown should be accomplished using the TERM signal.
When shutdown is initiated the worker will finish all currently executing tasks before it actually terminates. If these tasks are important, you should wait for it to finish before doing anything drastic, like sending the KILL signal.
If the worker won’t shutdown after considerate time, for being stuck in an infinite-loop or similar, you can use the KILL signal to force terminate the worker: but be aware that currently executing tasks will be lost (i.e., unless the tasks have the acks_late option set).
Also as processes can’t override the KILL signal, the worker will not be able to reap its children; make sure to do so manually. This command usually does the trick:
$ pkill -9 -f 'celery worker'
If you don’t have the pkill command on your system, you can use the slightly longer version:
$ ps auxww | grep 'celery worker' | awk '{print $2}' | xargs kill -9
There is a miskate in following command.
ps -ef | grep celery | awk '{print $2}' | grep -v grep |xargs kill -9;
It should be as following
ps -ef | grep celery | grep -v grep | awk '{print $2}' |xargs kill -9;
You are excluding "grep" process after taking just process ids and you can never find grep process id
Hope this helps
Just simply use like below it will solve your issue:-
IF you just want to stop all the instances of process celery use below command
ps -ef | grep [c]elery |awk '{print $2}' | xargs kill -9
If you want to stop all the instances of process celery and re-start it again use below command
ps -ef | grep [c]elery |awk '{print $2}' | xargs kill -9
pids=$(ps -ef | grep [c]elery |awk '{print $2}')
if [ "$pids" != "" ]; then
PWD=$(pwd)
celery -A loan_app.tasks worker --loglevel=info --workdir=$PWD --logfile=/tmp/celery.log --pidfile=/var/run/celery_pid -D
else
echo "Failed to kill process celery"
fi
Straight forward example:-
ps -ef | grep [c]elery |awk '{print $2}' | xargs kill -9
PWD=$(pwd)
celery -A loan_app.tasks worker --loglevel=info --workdir=$PWD --logfile=/tmp/celery.log --pidfile=/var/run/celery_pid -D

Multiple PIDs being stored in PID file

I have a System V init script I've developed that starts a Java program. For some reason whenever the PID file gets created, it contains multiple PIDs instead of one.
Here's the relevant code that starts the service and writes to the PID file:
daemon --pidfile=$pidfile "$JAVA_CMD &" >> $logfile 2>&1
RETVAL=$?
usleep 500000
if [ $RETVAL -eq 0 ]; then
touch "$lock"
PID=$(ps aux | grep -vE 'grep|runuser|bash' | grep <myservice> | awk '{print $2}')
echo $PID > $pidfile
When I test the ps aux... command manually, a single line returns. When running as a script, it appears that this call is returning multiple PIDs.
Example contents in the PID file: 16601 16602 16609 16619 16690. 16619 is the actual process ID found when manually running the ps aux... command mentioned above.
Try reversing your greps. The first one (-vE) may run BEFORE the myservice one starts up. Grep for your service FIRST, then filter out the unwanted lines:
PID=$(ps aux | grep <myservice> | grep -vE 'grep|runuser|bash' | awk '{print $2}')
I encounted the same issue but not the same statement, it was like this:
PID="$(ps -ef|grep command|grep options|grep -v grep|awk '{print $2}')"
in which I used the same grep order as #Marc said in first answer, but did not filter all the unwanted lines.
So I tried the below one and it worked:
PID="$(ps -ef|grep command|grep options|grep -vE 'grep|runuser|bash'|awk '{print $2}')"

Awk not working inside bash script

Im trying to write a bash script and trying to take input from user and executing a kill command to stop a specific tomcat.
...
read user_input
if [ "$user_input" = "2" ]
then
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}| xargs kill -9
echo "Search Tomcat Shut Down"
fi
...
I have confirmed that the line
ps -ef | grep "search-tomcat"
works fine in script but:
ps -ef | grep "search-tomcat" |awk {'"'"'print $2'"'"'}
doesnt yield any results in script, but gives desired output in terminal, so there has to be some problem with awk command
xargs can be tricky - Try:
kill -9 $(ps -ef | awk '/search-tomcat/ {print $2}')
If you prefer using xargs then check man page for options for your target OS (i.e. xargs -n.)
Also noting that 'kill -9' is a non-graceful process exit mechanism (i.e. possible file corruption, other strangeness) so I suggest only using as a last resort...
:)

How to terminate a job dispatcher in back ground in Linux?

I have a job dispatcher bash shell script containing below codes:
for (( i=0; i<$toBeDoneNum; i=i+1 ))
do
while true
do
processNum=`ps aux | grep Checking | wc -l`
if [ $processNum -lt $maxProcessNum ]; then
break
fi
echo "Too many processes: Max process is $maxProcessNum."
sleep $sleepSec
done
java -classpath ".:./conf:./lib/*" odx.comm.cwv.main.Checking $i
done
I run the script like this to be in the background:
./dispatcher.sh &
I want to terminate this dispatcher process with kill -9. But I didn't record the pid of the dispatcher process at the first time. Instead I used jobs to show all the process but it shows nothing. Even this fg cannot bring the process to foreground.
fg
bash: fg: current: no such job
But I think this dispatcher process is still running because it still continues to assign java program to run. How should I terminate this job dispatcher bash shell script process?
Edit: I used jobs, jobs -l, jobs -r and jobs -s. Nothing showed.
create test.sh with content
sleep 60
then
jobs -l | grep 'test.sh &' | grep -v grep | awk '{print $2}'
this gives me the process id on Ubuntu and OSX
you can assign it to a variable and then kill it
pid=`jobs -l | grep 'test.sh &' | grep -v grep | awk '{print $2}'`
kill -9 $pid

How can I kill a process by name instead of PID, on Linux? [duplicate]

This question already has answers here:
Find and kill a process in one line using bash and regex
(30 answers)
Closed 1 year ago.
Sometimes when I try to start Firefox it says "a Firefox process is already running". So I have to do this:
jeremy#jeremy-desktop:~$ ps aux | grep firefox
jeremy 7451 25.0 27.4 170536 65680 ? Sl 22:39 1:18 /usr/lib/firefox-3.0.1/firefox
jeremy 7578 0.0 0.3 3004 768 pts/0 S+ 22:44 0:00 grep firefox
jeremy#jeremy-desktop:~$ kill 7451
What I'd like is a command that would do all that for me. It would take an input string and grep for it (or whatever) in the list of processes, and would kill all the processes in the output:
jeremy#jeremy-desktop:~$ killbyname firefox
I tried doing it in PHP but exec('ps aux') seems to only show processes that have been executed with exec() in the PHP script itself (so the only process it shows is itself.)
pkill firefox
More information: http://linux.about.com/library/cmd/blcmdl1_pkill.htm
Also possible to use:
pkill -f "Process name"
For me, it worked up perfectly. It was what I have been looking for.
pkill doesn't work with name without the flag.
When -f is set, the full command line is used for pattern matching.
You can kill processes by name with killall <name>
killall sends a signal to all
processes running any of the specified
commands. If no signal name is
specified, SIGTERM is sent.
Signals can be specified either by
name (e.g. -HUP or -SIGHUP ) or by number (e.g.
-1) or by option -s.
If the command name is not regular
expression (option -r) and contains a
slash (/), processes executing that
particular file will be selected for
killing, independent of their name.
But if you don't see the process with ps aux, you probably won't have the right to kill it ...
A bit longer alternative:
kill `pidof firefox`
The easiest way to do is first check you are getting right process IDs with:
pgrep -f [part_of_a_command]
If the result is as expected. Go with:
pkill -f [part_of_a_command]
If processes get stuck and are unable to accomplish the request you can use kill.
kill -9 $(pgrep -f [part_of_a_command])
If you want to be on the safe side and only terminate processes that you initially started add -u along with your username
pkill -f [part_of_a_command] -u [username]
Kill all processes having snippet in startup path. You can kill all apps started from some directory by for putting /directory/ as a snippet. This is quite usefull when you start several components for the same application from the same app directory.
ps ax | grep <snippet> | grep -v grep | awk '{print $1}' | xargs kill
* I would prefer pgrep if available
Strange, but I haven't seen the solution like this:
kill -9 `pidof firefox`
it can also kill multiple processes (multiple pids) like:
kill -9 `pgrep firefox`
I prefer pidof since it has single line output:
> pgrep firefox
6316
6565
> pidof firefox
6565 6316
Using killall command:
killall processname
Use -9 or -KILL to forcefully kill the program (the options are similar to the kill command).
On Mac I could not find the pgrep and pkill neither was killall working so wrote a simple one liner script:-
export pid=`ps | grep process_name | awk 'NR==1{print $1}' | cut -d' ' -f1`;kill $pid
If there's an easier way of doing this then please share.
To kill with grep:
kill -9 `pgrep myprocess`
more correct would be:
export pid=`ps aux | grep process_name | awk 'NR==1{print $2}' | cut -d' ' -f1`;kill -9 $pid
I normally use the killall command.
Check this link for details of this command.
I was asking myself the same question but the problem with the current answers is that they don't safe check the processes to be killed so... it could lead to terrible mistakes :)... especially if several processes matches the pattern.
As a disclaimer, I'm not a sh pro and there is certainly room for improvement.
So I wrote a little sh script :
#!/bin/sh
killables=$(ps aux | grep $1 | grep -v mykill | grep -v grep)
if [ ! "${killables}" = "" ]
then
echo "You are going to kill some process:"
echo "${killables}"
else
echo "No process with the pattern $1 found."
return
fi
echo -n "Is it ok?(Y/N)"
read input
if [ "$input" = "Y" ]
then
for pid in $(echo "${killables}" | awk '{print $2}')
do
echo killing $pid "..."
kill $pid
echo $pid killed
done
fi
kill -9 $(ps aux | grep -e myprocessname| awk '{ print $2 }')
If you run GNOME, you can use the system monitor (System->Administration->System Monitor) to kill processes as you would under Windows. KDE will have something similar.
The default kill command accepts command names as an alternative to PID. See kill (1). An often occurring trouble is that bash provides its own kill which accepts job numbers, like kill %1, but not command names. This hinders the default command. If the former functionality is more useful to you than the latter, you can disable the bash version by calling
enable -n kill
For more info see kill and enable entries in bash (1).
ps aux | grep processname | cut -d' ' -f7 | xargs kill -9 $
awk oneliner, which parses the header of ps output, so you don't need to care about column numbers (but column names). Support regex. For example, to kill all processes, which executable name (without path) contains word "firefox" try
ps -fe | awk 'NR==1{for (i=1; i<=NF; i++) {if ($i=="COMMAND") Ncmd=i; else if ($i=="PID") Npid=i} if (!Ncmd || !Npid) {print "wrong or no header" > "/dev/stderr"; exit} }$Ncmd~"/"name"$"{print "killing "$Ncmd" with PID " $Npid; system("kill "$Npid)}' name=.*firefox.*

Resources