Grepping PID to kill process

Hello ,

In Script stopchkf,
I am just using simple grep to extract PID from 'ps -ef' output to kill that process.
Though the kill works to kill the process but along with giving message :

O/P :

./stopchkf
./stopchkf: line 5: kill: SIGQUIT: arguments must be process or job IDs
./stopchkf: line 5: kill: 11372
12301: arguments must be process or job IDs

script 'stopchkf ':

stop=`ps -ef | grep "[c]hkf $1" | tr -s " " | cut -d" " -f2 `
kill SIGQUIT "$stop"

Any idea of this behavior..

[back quotes put in 'ps -ef' statement while posting this are not being displayed]

Thanks ,

@dextergenious
revisit the notes on how to use markdown code tags at this site. It should make it easier for you and the others to better understand what you're after.
I've edited your post for now.

What's your OS?

you're calling ./stopchkf with no arguments while stopchkf is expecting ONE/first argument in grep "[c]hkf $1".
Why is that? And do you expect the $1 contain in grep?

@dextergenious , see if pgrep , pkill are on your system - use them rather than writing imitations of

https://manpages.org/pkill

Thanks for your kind advice .

Am using WSL

Don't intend to use argument. Forgot to remove the same. Apology..

Without any argument also, its the same.

Used "pgrep -f " instead , but same o/p.

Other info:

I even used expr command to typecast the obtained PID to an integer, though usually is not required, but still same o/p.

well, then just debug it "piece-meal" of your ps pipeline starting from the inside out and see what you end up with after all the pipes:

ps -ef | grep "[c]hkf $1" | tr -s " " | cut -d" " -f2

These are two newline-separated PIDs that have been assigned to the stop variable.
The quoted "$stop" refers to it with the embedded newline.
An unquoted $stop allows the shell to do word splitting (per $IFS that is "space tab newline", and the kill command actually wants two arguments(words).
Your OS supports pgrep then use

stop=$(pgrep -f "chkf $1")

Still the output is newline-separated. Use

[ -n "$stop" ] && kill SIGQUIT $stop

The [ -n argument ] command needs exactly one argument, the kill command needs each PID in a separate argument.

1 Like

The signal name is an option: my man page allows any of:

kill -3 
kill -s 3
kill --signal 3
kill -QUIT
kill -SIGQUIT
kill -s QUIT
kill -s SIGQUIT
kill --signal QUIT
kill --signal SIGQUIT

The result with no - is that Bash expects a pid, and rejects the signal name by itself.

The other issue is that, without a proper signame option, the default is SIGTERM.

It looks like it kills pid 11372, although it normally does not confirm success.

You might add debug to find out what pid 12301 was. It might just be coincidence, or a child process that also got ended. Usually it is the grep, but you seem to know how to avoid that matching.

Sorry -- @MadeInGermany nailed that issue while I was posting.

1 Like

First process I need to kill from that script :

root      3036    24 21 22:36 tty2     00:00:41 /bin/bash ./gh
root     21945    24  0 22:39 tty2     00:00:00 ps -ef 

--Script execution- (added line "echo $stop" to see value in $stop)

#./stopchkf
3036

Script './stopchkf':

 #!/bin/bash
 stop=`ps -ef | grep "[g]h" | tr -s " " | cut -d" " -f2`
echo "$stop"
kill -3 $stop

It shows correct PID value but don't make the process QUIT.

Process to be killed runs in background , does it makes any difference?

Thanks,

@MadeInGermany

Script :

#!/bin/bash

stop=$(pgrep -f "[g]h")
#stop=`ps -ef | grep "[g]h" | tr -s " " | cut -d" " -f2`
echo "$stop"
[ -n "$stop" ] && kill SIGQUIT $stop

Process listing:

root      2256    24 42 23:24 tty2     00:00:00 /bin/bash ./gh
root      2395    24  0 23:24 tty2     00:00:00 ps -ef
root      2397  2256  0 23:24 tty2     00:00:00 ps -ef
root      2398  2256  0 23:24 tty2     00:00:00 grep ^[] 2

Execution:

# ./stopchkf
2256
./stopchkf: line 6: kill: SIGQUIT: arguments must be process or job IDs

Though message is displayed, but the process quits , Kill acts.

Process listing after execution:

root         8     7  0 18:09 tty1     00:00:01 -bash
root        23     1  0 18:09 tty2     00:00:00 /init
root        24    23  0 18:09 tty2     00:00:01 -bash
root        60     1  0 18:14 tty3     00:00:00 /init
root        61    60  0 18:14 tty3     00:00:00 -bash
root      6853    24  0 23:27 tty2     00:00:00 ps -ef

One more time:
It's not supposed to be
kill SIGQUIT $stop
as it has to contain the - if you use this syntax, i.e.
kill -SIGQUIT $stop
(did you read Paul_Pedant's last reply?)

But -SIGQUIT and -SIGINT will apparently not work on a background process anyway, see here:

Yes, because since SIGQUIT is ignored (due to incorrect syntax used) the default signal sent is SIGTERM

1 Like

Jobs in background are protected from actions in the foreground window that launched them. You don't want to start a background job, then start something trivial in foreground, Ctrl-C that, and see your long-running job die as well.

It depends how your job got started, too. I would not like to vouch for what happens if you start a background process from inside a background shell, or use nohup or disown. crontab and at have other possible scenarios.

My usual method is to start with SIGTERM, which will generally take down a job. It can however be trapped by a process, which should then clean up anything it needs to do before it exits. The job can also completely ignore SIGTERM, so I usually follow it up with a SIGKILL after 10 seconds. SIGKILL used to be documented as "Terminate with extreme prejudice", a phrase borrowed from the FBI.

Sorry, I didn't see the missing - before the SIGQUIT

gh is very short, and grep gh or pgrep gh might match other process names. For example a process name light would match.

If your long process name (ps -ef) can be /bin/bash ./gh or gh
then it can be more precisely matched:

# pgrep and grep -E take extended RE:
# exact gh or prefixed by a /
for signal in TERM SYS KILL
do
  stop=$( pgrep -f '(^|/)gh$ )
  [ -z "$stop" ] && break
  kill -$signal $stop
  sleep 10
done

From the inputs from you all, which I really appreciate, the only error in my originally posted script was , as pointed by Matt-Kita, that I was not using '-' with the signal name/no. & not knowing that SIGINT & SIGQUIT don't work on background processes.

Thanks all for your contributions to add to my understanding.

Sincerely.