views:

217

answers:

3

I wrote a bash script which tries to find a process and run the process if it had stopped. This is the script.

#!/bin/bash
process=thin
path=/home/deepak/abc/
initiate=thin start -d

process_id=`ps -ef | pgrep $process | wc -m`

if [ "$process_id" -gt "0" ]; then
  echo "The process process is running!!"
else     
  cd $path    
  $initiate
  echo "Oops the process has stopped"    
fi

This worked fine and I thought of using arrays so that i can form a loop use this script to check multiple processes. So I modified my script like this

#!/bin/bash
process[1]=thin
path[1]=/home/deepak/abc/
initiate[1]=thin start -d

process_id=`ps -ef | pgrep $process[1] | wc -m`

if [ "$process_id" -gt "0" ]; then
  echo "Hurray the process ${process[1]} is running!!"
else
  cd ${path[1]}
  ${initiate[1]}
  echo "Oops the process has stopped"
  echo "Continue your coffee, the process has been stated again! ;)"
fi

I get this error if i run this script.

DontWorry.sh: 2: process[1]=thin: not found
DontWorry.sh: 3: path[1]=/home/deepak/abc/: not found
DontWorry.sh: 4: initiate[1]=thin start -d: not found

I googled to find any solution for this, most them insisted to use "#!/bin/bash" instead of "#!/bin/sh". I tried both but nothing worked. What am i missing?

A: 

I wasn't actually aware you could set arrays like that. I've always used:

pax> initiate=("thin start -d" "xx")
pax> echo ${initiate[0]}
thin start -d
pax> echo ${initiate[1]}
xx

You may need quotes around the strings. In my bash (4.0.33),

initiate[1]=thin start -d

is being interpreted as "set initiate[1]=thin then run start -d" because you can:

fspec=/etc/passwd ls -al ${fspec}

to set an environment variable for a single command. What version of bash are you running (use bash --version)?

Update:

Deepak, I've gotten that script working under the same release of bash as yours. See the following transcript:

pax> bash --version
GNU bash, version 3.2.48(21)-release (i686-pc-cygwin)
Copyright (C) 2007 Free Software Foundation, Inc.

pax> cat qq.sh
#!/bin/bash
process=(sleep)
path=(/)
initiate=("sleep 3600")

process_id=`ps -ef | pgrep ${process[0]} | wc -m`

if [ "$process_id" -gt "0" ]; then
    echo "Hurray the process ${process[0]} is running!!"
else
    cd ${path[0]}
    ${initiate[0]} &
    echo "Oops the process has stopped"
    echo "Continue your coffee, the process has been stated again! ;)"
fi

pax> ./qq.sh
Oops the process has stopped
Continue your coffee, the process has been stated again! ;)

pax> ./qq.sh
Hurray the process sleep is running!!

pax> ps -ef
UID     PID    PPID TTY     STIME COMMAND
pax     112       1 con  10:16:24 /usr/bin/bash
pax    4568       1 con  10:23:07 /usr/bin/sleep
pax    5924     112 con  10:23:18 /usr/bin/ps

Can you try the modified script in your own environment and see how it goes?

paxdiablo
Thanks pax, I tried using quotes but still I get this error. My Bash version. bash --version GNU bash, version 3.2.48(1)-release (i486-pc-linux-gnu) Copyright (C) 2007 Free Software Foundation, Inc.
Deepak Prasanna
What happens when you use the alternative syntax 'initiate=("thin start -d")' ?
paxdiablo
Some errors have gone that is the string is getting assigned to the array, but "process_id=`ps -ef | pgrep ${process[0]} | wc -m`" this line throws an error. ERROR: DontWorry.sh: 6: Bad substitution
Deepak Prasanna
Sorry, @Deepak, did you change all *three* arrays to the new format? If you're still setting process[1], your pgrep *will* fail since it's using process[0]. I suggest you try my script in the update and see if that works. It works fine for me in that bash version (albeit under Cygwin).
paxdiablo
Pax, Thank you so much. It works great. But if i use "sh filename.sh" to execute it in the command line instead of "./filename.sh" i get some errors. Why is it?
Deepak Prasanna
That would depend on how sh is running the script. sh is the posix shell under some operating systems and *should* honor the shebang line at the top of your script. But it *may* be the Bourne shell on other systems - in other words, you may be running the script under the wrong shell.
paxdiablo
Pax, I understand and thanks a lot.
Deepak Prasanna
A: 

Deepak Prasanna, you may want to rethink the way you are monitoring the process.

lhunath gives reasons for not using ps to monitor/restart processes, and also a simple script wrapper to achieve the goal in a cleaner manner.

unutbu
A: 

Perhaps something like this:

#!/usr/bin/perl -w
use strict;

my @processes = ({process=>'thin',
                  path=>'/home/deepak/abc/',
                  initiate=>'thin start -d'
                 },
                 # more records go here...
                );

for $p (@processes) {
   my $cmd = 'ps -ef | pgrep ' . $p->{process} . ' | wc -m';
   if (`$cmd` > 0) {
     print "The process process is running!!\n";
   } else {
     exec('cd ' . $p->{path} . '; ' .  
          $p->{$initiate}. '; '.
          'echo Oops the process has stopped'); 
   }
}
rplevy