Daemon en BASH

GNU/Linux

GNU/Linux

A decir verdad esto es un poco inutil, pero estuve jugando recientemente con BASH (con un script que espero poder terminar en cuanto tenga tiempo, y que si funciona bien publicaré aquí), y en algún momento de delirio se me ocurrió que podría usar una especie de daemon en BASH. La verdad que no es una muy buena alternativa ni un gran uso del lenguaje, seguramente usando otro lenguaje tendría un daemon mejor y para usar BASH probablemente sería más sencillo usar un cron. Pero estaba aburrido y se me ocurrió hacerlo. Por lo tanto, no lo tomen como algo particularmente útil, sino como un ensayo que me sirvió para practicar un poco con este lenguaje que lo tenía medio dejado de lado.

Este daemon no es más que un proceso que corre (“desatachandose” de la consola), con un while(1) y va imprimiendo un texto. En un uso normal, adentro del while iría alguna tarea repetitiva definida por la finalidad del demonio. El script recibe un parámetro opcional (que puede ser “start” o “shutdown”) para iniciar y detener el daemon. Cuando se inicia llama a la función “start” que hace un sanity check para ver si hay otra instancia del demonio corriendo, y si no la hay ejecuta la función “main” que es donde está el while. Otra cosa importante a notar: para que el script se “desatachee” de la consola, el while está dentro de un bloque delimitado por llaves ({}) con un ampersand al final (&). En todo caso también se podría agregar ahí una redirección del output y el error stream.

Sin más introducción, les dejo el script.

#!/bin/bash

function sanityCheck {
    q=`ps -ef |grep $0 |grep -v "grep"|grep -v $$| wc -l`
    if [ $q != "0" ]; then
        echo "Another instance of $0 running..."
        exit 1
    fi
}

function start {
    sanityCheck
    echo "Starting daemon..."
    main
}

function shutdown {
    echo "Shutting down daemon..."
    kill `ps -ef |grep $0|grep -v $$ |grep -v "grep"|awk '{print($2)}'`
}

function main {
    {
        while [ 1 ]; do
            echo "Test..."
            sleep 2
        done
    } &
}

case $1 in
    "start")
       start
    ;;
    "shutdown")
        shutdown
    ;;
     *)
         start
     ;;
esac

Uso:

# chmod +x ./daemon.sh
# ./daemon.sh
Starting daemon...
Test...
# Test...Test...Test...
# ./daemon.sh shutdown
Shutting down daemon...
#
  1. En

    kill `ps -ef |grep $0|grep -v $$ |grep -v “grep”|awk ‘{print($2)}’`

    no es mejor hacer..

    pidof $0

    y en realiadad aca:

    case $1 in
    “start”)
    start
    ;;
    “shutdown”)
    shutdown
    ;;
    *)
    start
    ;;
    esac

    podria ser:

    case $1 in
    “shutdown”)
    shutdown
    ;;
    *)
    start
    ;;
    esac

  2. Lo de pidof lo probé y no me andaba. Capaz me estaba equivocando en algún lado, pero no mataba nada.
    kill `pidof $0`
    También probé hacer:
    pkill $0
    Pero ni bola. La que hice es bastante más fea pero anduvo.
    Y con respecto a la segunda parte, si, tenés razón. Lo había puesto así por una cuestión de claridad, pero lo más lógico es lo que ponés vos.

  3. Jejeje, ahora que me avivo:

    killall $0

    y si es modo “muerte subita”

    killall -9 $0

  4. Jeje en realidad ahora me acuerdo por qué lo hice así!!
    Porque como decís vos me mato a mi mismo, es decir al proceso que se supone que tiene que matar al daemon. Lo que yo quiero matar es el otro proceso, con el mismo nombre (pero distinto PID) que está corriendo.
    Por eso busco los procesos con el mismo nombre y saco (grep -v), el grep y el proceso con mi mismo PID ($$). Y mato al que queda.

    Y por cierto, antes que hacer “killall -9 $0″, sería “kill -9 $$”. Pero no es lo que quiero hacer.

  5. hola amigo

    Una cosa tienes mal la function sanityCheck siempre te va a dar un falso positivo. Mira prueba esto:

    ps -ef |grep $0 |grep -v “grep”|grep -v $$ > /dev/null
    if [ $? = "0" ]
    then
    echo “$0 ya esta corriendo…”
    exit 1
    fi

  6. Por qué me daría un falso positivo?
    En las pruebas que hice siempre anduvo bien.

  7. Buenas Tardes hermanazo! si yo quisiera imprimir el mensaje en un archivo .log en /var/log/ como podria hacer? y otra pregunta si pueden poner el script completo mejorado para estudiarlo, ya que estoy aprendiendo bash y me gusta mucho!

  8. No tengo un script más completo, solamente hice ese para probar.

    Para loggear en un archivo, podés agregar esta funcion:

    function log
    {
    echo “`date`: $*” >> $LOG_FILE
    }

    Y después desde donde lo necesitás la llamás:

    log “Loggeando un mensaje…”.

    Otra que podés hacer, si querés loggear en el syslog es:

    function log
    {
    logger “$*”
    }

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks and Pingbacks: