1

I have put a command in a bash script to kill processes as below

#!/bin/bash
kill -9 $(ps ux | grep 'fluent' | awk '{print $2}')

As I run the script, e.g. ./mykill, it has no effect

$ ps ux | grep fluent
ko 21690  0.0  0.0 112664   972 pts/3    S+   15:28   0:00 grep --color=auto fluent
ko 26573  5.1  1.0 1743688 673592 ?      Sl   May14 836:08 /state/partition1/ans190/v190/fluent/cortex.19.0.0 -f fluent -cmd-port:35881:compute-0-4.local -workbench-session (fluent "3ddp -pshmem  -host -alnamd64 -r19.0.0 -t16 -mpi=ibmmpi -path/state/partition1/ansys190/v190/fluent -ssh")
ko 26581  0.0  0.0      0     0 ?        Z    May14   0:00 [fluent] <defunct>
$
$
$ ~/mykill
Killed
$ ps ux | grep fluent
ko 21690  0.0  0.0 112664   972 pts/3    S+   15:28   0:00 grep --color=auto fluent
ko 26573  5.1  1.0 1743688 673592 ?      Sl   May14 836:08 /state/partition1/ans190/v190/fluent/cortex.19.0.0 -f fluent -cmd-port:35881:compute-0-4.local -workbench-session (fluent "3ddp -pshmem  -host -alnamd64 -r19.0.0 -t16 -mpi=ibmmpi -path/state/partition1/ansys190/v190/fluent -ssh")
ko 26581  0.0  0.0      0     0 ?        Z    May14   0:00 [fluent] <defunct>

However, if I run the command in the terminal, it will kill them.

$ kill -9 $(ps ux | grep 'fluent' | awk '{print $2}')
-bash: kill: (21899) - No such process
$ ps ux | grep fluent
ko 21915  0.0  0.0 112664   972 pts/3    S+   15:31   0:00 grep --color=auto fluent

What is the reason then?

mahmood
  • 1,211
  • 1
  • What is the relation between my question and that? I didn't understand. – mahmood May 25 '19 at 19:44
  • 1
    You may want to try pkill instead. – Kusalananda May 25 '19 at 19:44
  • pkill is also incomplete. Because I have to kill multiple process names. for example, pkill fluent, pkill cortex and others. That command will kill all things. – mahmood May 25 '19 at 19:45
  • 3
    I posted the link to that other question because you are using kill -9. This is usually not a good idea in the general case. It's a related question. – Kusalananda May 25 '19 at 19:46
  • Then you should try using pkill -f. – Kusalananda May 25 '19 at 19:46
  • I know, but as you can see there are some defunct processes and I think kill -9 is the best at the moment. – mahmood May 25 '19 at 19:47
  • Defunct processes (zombies) don't respond to signals. They will hang around until their parent process reaps them. – Kusalananda May 25 '19 at 19:48
  • "Generally, send 15, and wait a second or two, and if that doesn't work, send 2, and if that doesn't work, send 1. If that doesn't, REMOVE THE BINARY because the program is badly behaved!" – jesse_b May 25 '19 at 19:49
  • 2
    Notice too that depending on the ordering of the returned PIDs from ps, the grep may be killed before other processes, which is why it's always better to use pkill. – Kusalananda May 25 '19 at 19:56
  • The grep should be dead and reaped by the time the kill runs. The danger is that its PID could be already reused for another innocent process. But yes, kill $(ps ...) sucks, doubly so because of the pretentious grep | awk mannerism. –  May 25 '19 at 21:05
  • @mahmood surely the difference between ~/mykill and ./mykill is just a typo? you're not running a different script than the one you're showing? –  May 25 '19 at 21:14
  • @mosvy: the script is in home. So, ~/ and ./ are the same. – mahmood May 26 '19 at 20:40
  • your problem is not reproducible, sorry. use pkill instead. –  May 26 '19 at 22:18

1 Answers1

1

There are several problems with your approach.

The way you detect processes is not reliable. A process may have fluent in its command line even if it isn't the one you wanted to kill. For example, if you call your script kill-fluent, it'll kill itself. Never kill a process just based on its name. It's far too unreliable.

The best way to kill a process is to use its own remote control mechanism to send an exit command. If that's not possible, kill it based on what files it has open with fuser. Executing a binary counts as having it open. For example, to kill all processes that are executing /usr/bin/fluent, run fuser -k /usr/bin/fluent.

In cases where you really have to kill a process based on its command line, don't use grep. ps … | grep … may include the grep process: the ps command and the grep command run in parallel, so ps may or may not list grep depending on the relative speed at which the two processes start. Use pkill instead.

As for the <defunct> processes, forget about killing them: they're already dead. That's what “defunct” means: they're zombies.

  • FWIW, always fuser -TERM -k /path/to/binary -- if someone really wants to send a SIGKILL, they will figure out how to remove the -TERM or change it to -KILL. –  May 25 '19 at 22:16