Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 21/01/2007, à 17:37

Ch'Portos

Lancer un programme en mode daemon

Bonjour,

Je développe actuellement une application en structure client/serveur (client sous WinXP hmm, serveur sous 'NIX), et pour faire fonctionner le serveur, j'ai besoin qu'il soit lancé en mode daemon au démarrage de la machine.

Pour ce qui est du lancement au démarrage, pas de probleme, par contre pour lancer en tant que daemon, c'est une autre histoire ...

J'ai tenté de regarder comment un script shell présent dans /etc/init.d (j'ai regardé par exemple celui d'Apache) lancait le programme, mais je n'ai pas tout compris :

#!/bin/bash -e
#
# apache2		This init.d script is used to start apache2.
#			It basically just calls apache2ctl.

ENV="env -i LANG=C PATH=/usr/local/bin:/usr/bin:/bin"

#edit /etc/default/apache2 to change this.
NO_START=0

set -e
if [ -x /usr/sbin/apache2 ] ; then
	HAVE_APACHE2=1
else
	exit 0
fi

. /lib/lsb/init-functions

test -f /etc/default/rcS && . /etc/default/rcS
test -f /etc/default/apache2 && . /etc/default/apache2
if [ "$NO_START" != "0" -a "$1" != "stop" ]; then 
        [ "$VERBOSE" != "no" ] && log_warning_msg "Not starting apache2 - edit /etc/default/apache2 and change NO_START to be 0.";
        exit 0;
fi

APACHE2="$ENV /usr/sbin/apache2"
APACHE2CTL="$ENV /usr/sbin/apache2ctl"

apache_stop() {
	PID=""
	PIDFILE=""
	AP_CONF=/etc/apache2/apache2.conf

	# apache2 allows more than PidFile entry in the config but only the
	# last found in the config is used; we attempt to follow includes
	# here, but only first-level includes are supported, not nested ones

	for i in $AP_CONF `awk '$1 ~ /^\s*[Ii]nclude$/ && $2 ~ /^\// {print $2}' $AP_CONF`; do
		PIDFILE=`grep -i ^PidFile $i | tail -n 1 | awk '{print $2}'`
		if [ -e "$PIDFILE" ]; then
			PID=`cat $PIDFILE`
		fi
	done
	
	errors=`$APACHE2 -t 2>&1`
	if [ $? = 0 ]; then
		# if the config is ok than we just stop normaly

		if [ -n "$PID" ]
		then
			$APACHE2CTL stop

			CNT=0
			while [ 1 ]
			do
				CNT=$(expr $CNT + 1)
		
				[ ! -d /proc/$PID ] && break

				if [ $CNT -gt 60 ]
				then
					if [ "$VERBOSE" != "no" ]; then
						echo " ... failed!"
						echo "Apache2 failed to honor the stop command, please investigate the situation by hand."
					fi
					return 1
				fi

				sleep 1
			done
		else
			if [ "$VERBOSE" != "no" ]; then
				echo -n " ... no pidfile found! not running?"
			fi
		fi

	else
		[ "$VERBOSE" != "no" ] && echo "$errors"

		# if we are here something is broken and we need to try
		# to exit as nice and clean as possible

		# if pidof is null for some reasons the script exits automagically
		# classified as good/unknown feature
		PIDS=`pidof apache2` || true

		REALPID=0
		# if there is a pid we need to verify that belongs to apache2
		# for real
		for i in $PIDS; do
			if [ "$i" = "$PID" ]; then
				# in this case the pid stored in the
				# pidfile matches one of the pidof apache
				# so a simple kill will make it
				REALPID=1
			fi
		done

		if [ $REALPID = 1 ]; then
			# in this case everything is nice and dandy
			# and we kill apache2
			kill $PID
		else
			# this is the worst situation... just kill all of them
			#for i in $PIDS; do
			#	kill $i
			#done
			# Except, we can't do that, because it's very, very bad
			if [ "$PIDS" ] && [ "$VERBOSE" != "no" ]; then
                                echo " ... failed!"
			        echo "You may still have some apache2 processes running.  There are"
 			        echo "processes named 'apache2' which do not match your pid file,"
			        echo "and in the name of safety, we've left them alone.  Please review"
			        echo "the situation by hand."
                        fi
                        return 1
		fi
	fi
}

# Stupid hack to keep lintian happy. (Warrk! Stupidhack!).
case $1 in
	start)
		[ -f /etc/apache2/httpd.conf ] || touch /etc/apache2/httpd.conf
		# ssl_scache shouldn't be here if we're just starting up.
		[ -f /var/run/apache2/ssl_scache ] && rm -f /var/run/apache2/*ssl_scache*
		# /var/run and /var/lock could be on a tmpfs
		[ ! -d /var/run/apache2 ] && mkdir /var/run/apache2
		[ ! -d /var/lock/apache2 ] && mkdir /var/lock/apache2
		# Make sure /var/lock/apache2 has the correct permissions
		chown www-data /var/lock/apache2

		log_begin_msg "Starting apache 2.0 web server..."
		if $APACHE2CTL startssl; then
                        log_end_msg 0
                else
                        log_end_msg 1
                fi
	;;
	stop)
		log_begin_msg "Stopping apache 2.0 web server..."
		if apache_stop; then
                        log_end_msg 0
                else
                        log_end_msg 1
                fi
	;;
	reload)
		log_begin_msg "Reloading apache 2.0 configuration..."
		if $APACHE2CTL graceful $2 ; then
                        log_end_msg 0
                else
                        log_end_msg 1
                fi
	;;
	restart | force-reload)
		log_begin_msg "Forcing reload of apache 2.0 web server..."
		if ! apache_stop; then
                        log_end_msg 1
                fi
		if $APACHE2CTL startssl; then
                        log_end_msg 0
                else
                        log_end_msg 1
                fi
	;;
	status)
		exit 4
	;;
	*)
		echo "Usage: /etc/init.d/apache2 start|stop|restart|reload|force-reload" >&2
		exit 2
	;;
esac

Quelqu'un pourrait-il m'aider à comprendre ?

Merci d'avance,
Ch'Portos.

P.S.: Tant que j'y suis, j'en profite wink, y'a-t-il quelque chose de particulier à ajouter au code pour faire ce que je veux ?

Dernière modification par Ch'Portos (Le 21/01/2007, à 17:38)

Hors ligne

#2 Le 21/01/2007, à 18:00

Zoolonly

Re : Lancer un programme en mode daemon

Ya pas mal de temps j'en avait fais un.
Tu a besoin d'un script pour lancer ton programme et recuperer le PID (processus ID) pour le tuer apres.
J'avais fait ca a l'epoque :

#!/bin/bash
set -o noclobber
NAME=WebServer
LOCK=lock.pid

error () {
  echo "$1" 1>&2
  exit 1
}

launch () {
  if [ -f "$LOCK" ]
  then
    	if ./webserver >> log.tmp 
	then
		echo "Launching $NAME... [OK]"
	else
		error "Launching $NAME... [Failed]"
	fi
  fi
}

usage () {
    error "Usage: $0 [ start | stop ] "
}

if [ $# != 1 ]
then
    usage
fi
case "$1" in
  start)
     if [ -f "$LOCK" ]
     then
       error "WebServer already running (not launched)!"
     else
       echo -n '' > "$LOCK" || error "Cannot write $LOCK"
       launch &
     fi
     ;;
  stop)
     if [ -f "$LOCK" ]
     then
       PID=$(cat "$LOCK")
       case "$PID" in [1-9][0-9]*) ;; *) error "$LOCK does not contain a pid";; esac
       echo -n "Stoping $NAME "
       if kill  "$PID"
       #if killall webserver
       then
         echo "[Done]"
         rm "$LOCK"
       else
         echo "$NAME not running (cleaning $LOCK)!" 1>&2
         rm "$LOCK"
	 rm log.tmp
         exit 1
       fi
     else
       error "$NAME not running"
     fi
     ;;
  *) usage
esac

Ensuite dans le code de ton programme ca donne ca :

/*Creation du demon*/
	int fd;
	if(fork() != 0)
		exit(EXIT_SUCCESS);
	
	setsid();
	
	if(fork() != 0)
		exit(EXIT_SUCCESS);
		
    writePID();
    chdir("/");
	
	fd = open("/dev/null", O_RDWR);
	dup2(fd,0);
	close(fd);

	fd = open("/dev/console", O_WRONLY);
	dup2(fd, 1);
	dup2(fd,2);
	close(fd);

Je crois qu'il y a pas mal de doc la dessus. demande a google de chercher "Programmation system UNIX"

Hors ligne

#3 Le 22/01/2007, à 11:23

Ch'Portos

Re : Lancer un programme en mode daemon

OK, je crois comprendre comment marche ton script shell (en gros on mémorise qqe part le PID associé au process et on le récupere plus tard pour tuer le process), mais par contre je comprends pas trop ton code C. A quoi correspondent les fonctions dup2(), writePID(), setsid() ?

Ch'Portos.

Hors ligne

#4 Le 22/01/2007, à 13:03

Zoolonly

Re : Lancer un programme en mode daemon

Alors WritePID() c'est une fonction que j'ai ecrite et qui permet juste d'ecrire le PID dans un fichier. le pourquoi du comment ?? je me souviens pas trop mais ca avait un rapport avec le fait que Apres le fork() le papa se termine, et moi je veux pouvoir tuer le fils !

setsid permet de dire au fils de devenir le leader d'un nouveau groupe processus
man setsid !!

dup2 permet d'associer deux descripteur. Je connais pas trop ce truc en details ! Mais ca fait une sorte de pipe je crois !

Hors ligne