0

I'm dealing with an application, that brings up a multitude of separate processes, some of which sometimes do not go away, when asked politely -- by using the application's own means.

Which means, they have to be evicted rudely (with SIGTERM) and then, for the particularly stubborn ones -- brutally (with SIGKILL).

The trouble is finding them all... How do you list all processes, which consider a given directory -- or a subdirectory thereof -- its working-directory (cwd)?

The best method I was able to come up with was to invoke: lsof -b -w -u $(whoami), then parsing the last column looking for my directory, and then running the second column (the PID) through sort -u.

Is there, perhaps, anything better?

Mikhail T.
  • 3,043
  • 3
  • 29
  • 46
  • Is this a long-running system service? If so try to leverage the init system, e.g. systemd, to manage the process. Systemd is available in modern Debian and Red Hat distros and does all of this and more. You don't want to reinvent the wheel if you don't have to. – John Kugelman Apr 01 '21 at 01:34

2 Answers2

1

If you only care about working directories, you can use awk to test if the 4th column of the output is cwd. And awk can also check the last column to see if it's in the directory you care about.

procs=$(lsof -b -w -u $(whoami)  | awk '$4 == "cwd" && $NF ~ /^\/path\/to\/directory(\/|$)/ { print $2 }')

Since each process only has one cwd reference, you don't need to use sort -u to remove duplicates.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • The limiting to `$4 == "cwd"` is a good idea, but overall this variation does not work -- at least on RHEL7 -- because using `-b` and the explicit directory are mutually exclusive: `lsof` will not `stat` the directory as that's "potentially blocking". It will also not list processes operating in a *subdirectory* of the given one, which I also want to kill -- hence parsing of the last column... – Mikhail T. Apr 01 '21 at 01:03
  • OK, I changed it to check for the directory in `awk`. That also allows it to find subdirectories. – Barmar Apr 01 '21 at 01:10
  • Yes, @barmar, that's what I'm doing, but I was wondering, if there was a better way to do this -- some kind of `pwdx` or `pgrep` trick, for example... – Mikhail T. Apr 01 '21 at 01:32
  • Not that I'm aware of, as it's not something commonly needed. – Barmar Apr 01 '21 at 01:33
1

Assuming a typical linux environment with a procfs filesystem mounted at /proc:

#!/usr/bin/env bash

# Script takes the desired directory as its argument and prints out
# all pids with that directory or a child directory as their working
# directory (As well as what the cwd is)

shopt -s extglob

dir=${1#/}

for p in /proc/[0-9]*; do
    cwd=$(readlink -m "$p/cwd")
    if [[ ${cwd#/} == $dir?(/*) ]]; then
       printf "%d\t%s\n" "${p#/proc/}" "$cwd"
    fi
done
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • Thank you, this might work too... Personally, I prefer the `lsof` approach, as that is more likely to work outside of the Linux world. But I was hoping for some clever use of `pwdx` or `pgrep`... – Mikhail T. Apr 01 '21 at 21:18