0

I have this shell script from ISPConfig:

#!/bin/sh

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin

. /etc/profile

umask 022

if [ -f /usr/local/ispconfig/server/lib/php.ini ]; then
        PHPINIOWNER=`stat -c %U /usr/local/ispconfig/server/lib/php.ini`
        if [ $PHPINIOWNER == 'root' ] || [ $PHPINIOWNER == 'ispconfig'  ]; then
                export PHPRC=/usr/local/ispconfig/server/lib
        fi
fi

cd /usr/local/ispconfig/server
/usr/bin/php -q /usr/local/ispconfig/server/server.php

cd /usr/local/ispconfig/security
/usr/bin/php -q /usr/local/ispconfig/security/check.php

This script is executed by cron each minute, but I need to make it recursive, that is, finish script and repeat itself.

I tried adding this on the last line:

sh /usr/local/ispconfig/server/server.sh

but for some reason, consumes all memory in a few minutes.

how can I solve it?

Diogo Braga
  • 441
  • 1
  • 8
  • 17

2 Answers2

2

When you recurse by invoking it at the end like that you are never letting the parent's finish and will use all your process allotment and/or memory. You could use exec to replace your current process with a new instance of it though:

exec sh /usr/local/ispconfig/server/server.sh

That way your current process will just be replaced by a fresh copy, instead of having an ever growing chain of children.

Eric Renouf
  • 939
  • 8
  • 19
2

I guess what you really want is to repeat the script in an endless loop.

So, instead of doing this recursively (really bad idea, as you found out) or with exec, I propose to just loop it:

!/bin/sh

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin

. /etc/profile

umask 022



if [ -f /usr/local/ispconfig/server/lib/php.ini ]; then
        PHPINIOWNER=`stat -c %U /usr/local/ispconfig/server/lib/php.ini`
        if [ $PHPINIOWNER == 'root' ] || [ $PHPINIOWNER == 'ispconfig'  ]; then
                export PHPRC=/usr/local/ispconfig/server/lib
        fi
fi

while : 
do 

   cd /usr/local/ispconfig/server
   /usr/bin/php -q /usr/local/ispconfig/server/server.php

   cd /usr/local/ispconfig/security
   /usr/bin/php -q /usr/local/ispconfig/security/check.php
done

This way, you repeat everything between do and done immediately and endlessly.

That said, you have to be careful as even this can have a big impact on your system, as you are forking new PHP interpreters all the time. Does this stuff really need to run more than once a minute? What does it do anyway?

Sven
  • 98,649
  • 14
  • 180
  • 226
  • I like your suggestion. No need to reprocess part of the code. To answer your question, this script (php) processes email accounts, and the closer to real time, better for the end user who will have your changes immediately processed. A doubt, from the moment that this script is run, in which situations it may have to stop running? Basically, I need it to remain always running (failsafe). – Diogo Braga Jun 18 '16 at 16:23
  • The part between `do` and `done` will never terminate, as the `while :` doesn't have any termination condition. This script could only be killed by `kill` (or a CTRL-C when running in the console), and this is pretty bad style - consider it as just a demonstration of the concept. I don't think it would be good performance wise to really have this process possibly multiple times per second - add `sleep 5` before the `done` to let it wait a few seconds before the next run. – Sven Jun 18 '16 at 16:43