1

Hi I have a problem running watch command like this:

 watch cat /proc/$(ps ax | grep processname | grep -v grep | awk '{print $1}')/status

The command works when I start it. However, then I restart the process being watched and the watch command still uses old process id. I want it to refresh the process id and show the status of a new process with the same name. The part $(ps ax | grep processname | grep -v grep | awk '{print $1}') is obviously ran only at the start. How can I make it to be reevaluated every time the watch refreshes the output?

I would not like to put the cat command in a bash script and run that script from watch.

2
  • put it in a script and run the script with watch
    – cas
    Jan 5, 2018 at 7:47
  • 1
    btw, use pgrep. ps | grep | grep -v | awk "works" but there are many better ways - even ps ax | awk '/processname/ && ! /awk/ {print $1}' is better. or ps -o pid -C processname.
    – cas
    Jan 5, 2018 at 7:50

4 Answers 4

2

It is not a neat way, but if you really feel reluctant to create a script. You can try eval.

 watch eval 'cat /proc/$(ps ax | grep processname | grep -v grep | awk '"'"'{print $1}'"'"')/status'
1
  • This is a bit misleading. Since watch starts by "helpfully" concatenating all of its args together into a single command string, your command is actually exactly equivalent to: watch 'eval cat /proc/$(ps ax | grep processname | grep -v grep | awk '"'"'{print $1}'"'"')/status' . From that, it's evident that the eval isn't serving any purpose, so you can just leave it out: watch 'cat /proc/$(ps ax | grep processname | grep -v grep | awk '"'"'{print $1}'"'"')/status' which is the same as the final command in my answer.
    – Don Hatch
    Jun 6, 2019 at 8:16
1

Save the following as, e.g. ps-status.sh somewhere in your $PATH and make it executable with chmod +x:

#!/bin/sh

[ -z "$1" ] && echo "process name required" && exit 1

pid="$(pgrep -f "$1")"

[ -z "$pid" ] && echo "no such process: $1" && exit 1

countpids="$(echo "$pid" | wc -l)"
[ "$countpids" -gt 1 ] && "Warning: more than one pid matches $1" && exit 1


cat "/proc/$pid/status"

Then run watch like so:

watch ps-status.sh processname

$pid should probably be an array, but that would require bash rather than just sh:

#!/bin/bash

[ -z "$1" ] && echo "process name required" && exit 1

pids=( $(pgrep -f "$1") )

[ "${#pids[@]}" -eq 0 ] && echo "no such process: $1" && exit 1
[ "${#pids[@]}" -gt 1 ] && echo "Warning: more than one pid matches $1"

# display first matching PID, even if there were more than 1 matching.
cat "/proc/${#pids[0]}/status"
1

script.sh

#!/bin/bash
ps -eaf | grep -i processname| grep -v grep |awk '{print $2}'
/etc/init.d/servicename restart

explaination

schedule the crontab for every 1 minutes

Then use the below watch command to see the difference in process id after restarting the process name

watch -n 60 script.sh  

0

You can just single-quote the $(...) to prevent its expansion by the interactive shell you're running the thing from from. And then you have to escape the single-quotes that you have inside that, by temporarily switching to double-quotes and back. So the following works:

watch cat /proc/'$(ps ax | grep processname | grep -v grep | awk '"'"'{print $1}'"'"')'/status

However, in order to understand what watch is doing, here and in general, you have to keep in mind that watch starts by joining together all its non-flag args into a single command string. It does that in order to be "helpful", but I think it's actually counterproductive since it obscures what's going on. I think it's cleaner and easier to understand if you always give it just a single command string, in this case single-quoted to prevent your interactive shell from expanding anything in it:

watch 'cat /proc/$(ps ax | grep processname | grep -v grep | awk '"'"'{print $1}'"'"')/status'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .