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.

  • put it in a script and run the script with watch
    – cas
    Jan 5 '18 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 '18 at 7:50

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'
  • 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 '19 at 8:16

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


[ -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:


[ -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"


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


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  


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'

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.