2009-10-04 5 views
4

J'ai un script d'arrêt pour Oracle dans /etc/init.d dir sur commande « stop », il fait:Kill processus dans bash qui s'exécute plus de temps spécifié?

su oracle -c "lsnrctl stop >/dev/null" 
su oracle -c "sqlplus sys/passwd as sysdba @/usr/local/PLATEX/scripts/orastop.sql >/dev/null" 

.. Le problème est quand lsnrctl ou sqlplus ne répondent pas - dans ce cas, ce Le script "stop" ne se termine jamais et le serveur ne peut pas s'arrêter. La seule façon - est de "tuer - 9" cela.

Je voudrais réécrire le script de sorte qu'après 5min (par exemple) si la commande n'est pas terminée - il devrait être terminé.

Comment puis-je y parvenir? Pourriez-vous me donner un exemple? Je suis sous Linux RHEL 5.1 + bash.

+0

Je ne voudrais pas écrire cela dans bash; Je chercherais un programme qui fasse ça pour toi. Nous avons un outil interne pour cela (qui est malheureusement fermé). – JesperE

+0

Est-ce difficile à Bash? Pourquoi préférez-vous votre propre outil? Je pourrais écrire un outil perl, java, mais je pense que faire dans bash est plus simple et natif? – zmische

+0

Eh bien, c'est plus facile à faire dans quelque chose où vous avez un accès direct à waitpid, qui prend en charge une valeur de délai d'attente en soi. Bash va bien, cependant, et je l'ai utilisé (littéralement pour exactement ce but) dans le passé. (Ancien employeur, pas d'accès continu aux scripts, et j'ai assez dormi depuis lors que je ne me souviendrai probablement pas de ce qui est spécifique au domaine et utile). –

Répondre

9

si elle est capable d'utiliser des outils de 3e parti, j'Equifax de la 3e partie, les aides pré-écrites, vous pouvez appeler à partir de votre script (doalarm et timeout sont tous deux mentionnés par the BashFAQ entry on the subject).

Si vous écrivez moi-même une telle chose sans utiliser de tels outils, je ferais probablement quelque chose comme ce qui suit:

function try_proper_shutdown() { 
    su oracle -c "lsnrctl stop >/dev/null" 
    su oracle -c "sqlplus sys/passwd as sysdba @/usr/local/PLATEX/scripts/orastop.sql >/dev/null" 
} 

function resort_to_harsh_shutdown() { 
    for progname in ora_this ora_that ; do 
    killall -9 $progname 
    done 
    # also need to do a bunch of cleanup with ipcs/ipcrm here 
} 

# here's where we start the proper shutdown approach in the background 
try_proper_shutdown & 
child_pid=$! 

# rather than keeping a counter, we check against the actual clock each cycle 
# this prevents the script from running too long if it gets delayed somewhere 
# other than sleep (or if the sleep commands don't actually sleep only the 
# requested time -- they don't guarantee that they will). 
end_time=$(($(date '+%s') + (60 * 5))) 
while (($(date '+%s') < end_time)); do 
    if kill -0 $child_pid 2>/dev/null; then 
    exit 0 
    fi 
    sleep 1 
done 

# okay, we timed out; stop the background process that's trying to shut down nicely 
# (note that alone, this won't necessarily kill its children, just the subshell we 
# forked off) and then make things happen.  
kill $child_pid 
resort_to_harsh_shutdown 
+0

AFAIR nous pourrions utiliser WAITPID dans bash? Et qu'en est-il de l'option waitpid + WHOHANG dans while-loop qui mesure le temps passé depuis exec et se termine alors? (Je pense au lieu de "if [[! -e/proc/$ child_pid]]", puis "construction?" – zmische

+0

Vous rappelez incorrectement; La construction d'attente de bash accepte un pid comme argument, mais rien d'autre (pas de timeout, donc vous perdez une grande partie de la puissance du syscall waitpid). –

+0

... mais oui, si nous pouvions le faire, ce serait * beaucoup * moins mauvais. :) –

6

wow, c'est une solution complexe. voici quelque chose de plus facile. Vous pouvez suivre le PID et le tuer plus tard.

my command & #where my command is the command you want to run and the & sign backgrounds it. 
PID=$! #PID = last run command. 
sleep 120 && doProperShutdown || kill $PID #sleep for 120 seconds and kill the process properly, if that fails, then kill it manually.. this can be backgrounded too. 
Questions connexes