1

I know that you can find the working directory of a process a few different ways, but is there any way to do the reverse? I have some server applications written in node that are unfortunately tricky to tell apart as processes (they all show up as node server.js in a ps output) and I would like to have a simple way to determine whether or not a specific server was running.

In other words the question I need answered is; given directory /x/y/z, is there a node server.js process running with the working directory /x/y/z?

Currently my best attempt is to do ps -ef | grep "[n]ode server.js", cutting the PID and looping over them, checking pwdx for each PID. It works, but it's cumbersome and I was wondering if there was a better way.

1

Since pwdx accepts PIDS then you can use:

$ pwdx $(ps -C "node server.js" --format pid --no-headers)
2781: /home/user
4405: /home/user/src.git/

And possibly define a function in your .zshrc or .bashrc:

function select_by_dir()
{
  if (( $# == 0))l then
    pwdx $(ps -C "node server.js" --format pid --no-headers) 
  else
    pwdx $(ps -C "node server.js" --format pid --no-headers) | grep $1
  fi
}

}

  • I'm not sure which part of your ps call it specifically objects to, but it fails with error: unsupported option (BSD syntax). I perhaps should have specified that I'm running Ubuntu 15.10. Edit: Actually, it might just be that node server.js is missing quotes. – Thor84no Mar 29 '16 at 7:54
  • It hadn't really occurred to me that pwdx accepted any number of PIDs. That's very helpful. Thanks. – Thor84no Mar 29 '16 at 7:57
  • Instead of using ps you can use pgrep. Possibly there will be no errors – Sergei Kurenkov Mar 29 '16 at 8:02
  • pgrep doesn't work for this at all. The only way to get the PIDs with that seems to be pgrep node, but that has too many false positives. – Thor84no Mar 29 '16 at 8:05
1

how about

pwdx `pgrep "server.js"` 
1

I'd just search /proc.

This will list all your pids for which you know the cwd and show the cwd next to it:

(cd /proc/; for p in [0-9]*; do
   cwd="$(readlink "$p/cwd")" || continue; echo "$p $cwd";
done)

You can grep that or insert your matcher right into the loop:

(cd /proc/; for p in [0-9]*; do
   cwd="$(readlink "$p/cwd")" || continue;
   [ "$cwd" != "$THE_CWD_IM_LOOKING_FOR" ] || { echo "$p"; break; }
done)
0

You may try this, if you "node" is the only process

pwdx `pidof node`
0

Based on the answer from @skwllsp I've come up with the following bash function that solves the issue:

function is-server-running {
    local path=$(realpath "${1-.}")
    pwdx $(ps -C "node server.js" --format pid --no-headers) | grep --silent "$path"
}

Thanks for the help everyone!

0

The commands fuser and lsof both list processes that have a file open. In this context, having a file open includes a process's current directory.

With fuser, you only get process IDs, so you need to call ps to get the command name.

pids=$(fuser -s /x/y/z 2>/dev/null | tr ' ' ',')
pids=${pids#,}
node_pids=$(ps -p "$pids" -o pid=,args= | awk '$2 == "node" && $3 == "server.js" {print $1}')
kill $node_pids

With lsof, you can specify that you only want processes with that current directory (as opposed to e.g. currently listing the directory contents). You can get the command name with the c output specified, but not the arguments.

pids=$(lsof -F p -a -d cwd . | sed '1s/^p//; s/p/,/' | tr -d \\n)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.