Dick Kennedy
Dick Kennedy

Reputation: 153

Bash variable change doesn't persist

I have a short bash script to check to see if a Python program is running. The program writes out a PID file when it runs, so comparing this to the current list of running processes gives me what I need. But I'm having a problem with a variable being changed and then apparently changing back! Here's the script:

#!/bin/bash
# Test whether Home Server is currently running
PIDFILE=/tmp/montSvr.pid
isRunning=0
# does a pid file exist?
if [ -f "$PIDFILE" ]; then
  # pid file exists
  # now get contents of pid file
  cat $PIDFILE | while read PID; do
    if [ $PID != "" ]; then
      PSGREP=$(ps -A | grep $PID | awk '{print $1}')
      if [ -n "$PSGREP" ]; then
        isRunning=1
        echo "RUNNING: $isRunning"
      fi
    fi
  done
fi
echo "Running: $isRunning"
exit $isRunning

The output I get, when the Python script is running, is:

RUNNING: 1
Running: 0

And the exit value of the bash script is 0. So isRunning is getting changed within all those if statements (ie, the code is performing as expected), but then somehow isRunning reverts to 0 again. Confused...

Upvotes: 0

Views: 662

Answers (2)

cdarke
cdarke

Reputation: 44354

It's the pipe that is the problem. Using a pipe in this way means that the loop runs in a sub-shell, with its own environment. Kill the cat, use this syntax instead:

while read PID; do
    if [ $PID != "" ]; then
      PSGREP=$(ps -A | grep $PID | awk '{print $1}')
      if [ -n "$PSGREP" ]; then
        isRunning=1
        echo "RUNNING: $isRunning"
      fi
    fi
  done < "$PIDFILE"

Upvotes: 0

choroba
choroba

Reputation: 241828

Commands after a pipe | are run in a subshell. Changes to variable values in a subshell do not propagate to the parent shell.

Solution: change your loop to

while read PID; do
    # ...
done < $PIDFILE

Upvotes: 6

Related Questions