Killing a process - linux

I have a for loop to get the list of PID's and kill each PID. I want to display the entire line of PS output and write it to the /tmp/outfile . But from each line of PS output each field(PID,PPID,...) is written along with a new line in the /tmp/outfile. So if PS output has three lines as output i want to log these three lines into /tmp/outfile but it's breaking each field in the line and adding a new line. how can i do it.
for list in `ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep`
do
echo "$list" >> $CUSTOM_TMP/test5566
PID=`echo $list | awk '{print $2}'`
kill -TERM "$list"
done

Your for loop does not iterate the lines but each individual field.
Also your kill command was slightly wrong.
Just change your code to something like:
ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep | while read list
do
echo "$list" >> $CUSTOM_TMP/test5566
PID=`echo $list | awk '{print $2}'`
kill -TERM "$PID"
done

Isn't it easier to use the killall command for what you are trying to do?

No need for a loop at all. And this uses tee to write your temp file.
list=$(ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep | tee $CUSTOM_TMP/test5566 | awk '{printf "%s ", $2')
kill -TERM $list

You want to run ps before looping:
ps -ef | grep $"{process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep > $CUSTOM_TMP/test5566 2>/dev/null
for PID in `cat $CUSTOM_TMP/test5566 | awk '{print $2}'`; do
kill -TERM $PID
done
rm -f $CUSTOM_TMP/test5566
I would also insert some sanity, possibly using wc to make sure the file actually got some data from ps.

Just move the awk part to the top line, otherwise your code is fine.
for list in `ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep | awk '{print $2}`
do
echo "$list" >> $CUSTOM_TMP/test5566
PID=`echo $list`
kill -TERM "$list"
done

For a one liner - if your system has pgrep --
pgrep -d ' ' ${process_name} > kill.log && kill -TERM $(< kill.log)

Related

alias in .cshrc to kill processes

I have a bunch of 'abcd' processes that I want to kill and restart frequently. I do this to kill them
kill -9 `ps -ef | grep abcd | grep -v grep | awk '{print $2}'`
Because I do it so frequently, I want to create an alias in the .cshrc file.
alias killabcd 'kill -9 `ps -ef | grep abcd | grep -v grep | awk '{print $2}'`'
But it seems like $2 of awk is getting expanded and I get this error when I open a terminal
Missing }.
What am I doing wrong? How can I create an alias for this in my cshrc?
Simply with pkill command:
alias killabcd 'pkill abcd'
Nevermind! I figured it out!
This is one of the ways to do it:
alias killabcd 'kill -9 `ps -ef | grep abcd | grep -v grep | awk \{print\ \$2\}`'

Strange grep behaviour in scripts

In one of my tools is needed the PID of specyfic process in system. I try do this by following command:
parasit#host:~/# ps -ef | grep beam.smp |grep -v grep |awk '{ print $2 }' |head -n1
11982
Works fine, but when i try use the same command in script in the vast majority of cases got PID of grep instead of target process (beam.smp in this case) despite of 'grep -v grep`.
parasit#host:~/# cat getPid.sh
#!/bin/bash
PROC=$1
#GET PID
CMD="ps -ef | grep $PROC |grep -v grep |awk '{ print \$2 }' |head -n1"
P=`eval $CMD`
parasit#host:~/# bash -x ./getPid.sh beam.smp
+ PROC=beam.smp
+ CMD='ps -ef |grep beam.smp |grep -v grep |awk '\''{ print $2 }'\'' |head -n1'
++ eval ps -ef '|grep' beam.smp '|grep' -v grep '|awk' ''\''{' print '$2' '}'\''' '|head' -n1
+++ head -n1
+++ awk '{ print $2 }'
+++ grep -v grep
+++ grep beam.smp
+++ ps -ef
+ P=2189
Interestingly, it is not deterministic, I know it sounds strange, but sometimes it works OK, and sometimes no, I have no idea what it depends on.
How it is possibile? Is there any better method to get rid of "grep" from results?
BR
Parasit
pidof -s is made for that (-s: single ID is returned):
pidof -s "beam.smp"
However, pidof also returns defunct (zombie, dead) processes. So here's a way to get PID of the first alive-and-running process of a specified command:
# function in bash
function _get_first_pid() {
ps -o pid=,comm= -C "$1" | \
sed -n '/'"$1"' *$/{s:^ *\([0-9]*\).*$:\1:;p;q}'
}
# example
_get_first_pid "beam.smp"
-o pid=,comm=: list only PID and COMMAND columns; ie. only list what we need to check; if all are listed then it is more difficult to process later on
-C "$1": of the command specified in -C; ie. only find the process of that specific command, not everything
sed: print only PID for first line that do not have "defunct" or anything after the base command name

How to pass parts of a command as variable bash?

a="grep ssh | grep -v grep"
ps -ef | $a | awk '{print $2}'
How can I make the above work? I have a section where I need to not just pass the grep term, but possible pass more than one grep term, meaning I need to pass "term1 | grep term2" as a variable.
Edit:
another.anon.coward answer below worked perfectly for me. Thank you sir!
Create a function instead:
a() {
grep ssh | grep -v grep
}
ps -ef | a | awk '{print $2}'
The other solution is to use eval but it's unsafe unless properly sanitized, and is not recommended.
a="grep ssh | grep -v grep"
ps -ef | eval "$a" | awk '{print $2}'
If you want just the pid of a process, then use pgrep.
pgrep ssh
You can put this in a bash like the following (a.bash) :
#!/bin/bash
pname=$1
pgrep "$pname"
or if you want ps -ef for other purposes as you've written, following inside a script might work:
pname=$1
ps -ef | grep "$pname" | grep -v grep | awk '{print $2}' # I would personally prefer this
OR
ps -ef | eval "$pname" | awk '{print $2}' # here $pname can be "grep ssh | grep -v grep"
change the permission to execute :
chmod a+x a.bash
./a.bash ssh

How to continue executing the next other commands after using "kill" in shell?

I want to merge two different script files into one script file which could do what the two different files do. And the script files is:
script file A:
pid=`ps -ef | grep temp_tool | grep -v grep | awk '{print $2}'`
kill -9 ${pid}
script file B:
nohup ./temp_tool &
the merged script file:
pid=`ps -ef | grep temp_tool | grep -v grep | awk '{print $2}'`
kill -9 ${pid}
nohup ./temp_tool &
The whole merged script file would stop after executing kill command, and I have to modify it to be:
pid=`ps -ef | grep temp_tool | grep -v grep | awk '{print $2}'`
out=`kill -9 ${pid}`
nohup ./temp_tool &
and it works well now, but I don't know why? Is there any difference?
I would say $pid also contains the pid of your script. You can filter it out:
script_pid=$$
pid=$(ps -ef | grep temp_tool | grep -Ev "grep|$script_pid" | awk '{print $2}')
Though if you want the pids of the command temp_tool I would suggest this:
ps -C temp_tool -o pid
Instead of the ps -ef | grep ...

Getting PID of process in Shell Script

I am writing one shell script and I want to get PID of one process with name as "ABCD". What i did was :
process_id=`/bin/ps -fu $USER|grep "ABCD"|awk '{print $2}'`
This gets PID of two processes i.e. of process ABCD and the GREP command itself what if I don't want to get PID of GREP executed and I want PID only of ABCD process?
Please suggest.
Just grep away grep itself!
process_id=`/bin/ps -fu $USER| grep "ABCD" | grep -v "grep" | awk '{print $2}'`
Have you tried to use pidof ABCD ?
It's very straight forward. ABCD should be replaced by your process name.
#!/bin/bash
processId=$(ps -ef | grep 'ABCD' | grep -v 'grep' | awk '{ printf $2 }')
echo $processId
Sometimes you need to replace ABCD by software name. Example - if you run a java program like java -jar TestJar.jar & then you need to replace ABCD by TestJar.jar.
ps has an option for that:
process_id=`/bin/ps -C ABCD -o pid=`
You can also do away with grep and use only awk.
Use awk's expression matching to match the process name but not itself.
/bin/ps -fu $USER | awk '/ABCD/ && !/awk/ {print $2}'
You can use this command to grep the pid of a particular process & echo $b to print pid of any running process:
b=`ps -ef | grep [A]BCD | awk '{ printf $2 }'`
echo $b
ps | pgrep ABCD
You can try the above command to return the process id of the ABCD process.
I found a better way to do this.
top -n 1 | grep "##" | grep -Eo '^[^ ]+'

Resources