Newsgroup: it.comp.os.linux.development
Titolo: Creare un demone con la bash

Sapete dove reperire della documentazione per creare dei demoni con la bash?

 Sapete dove reperire della documentazione per creare dei demoni con la bash?
Se si tratta di un server di rete, basta sfruttare inetd o xinetd: in
questo caso il programma (bash o quant'altro) comunica con remoto via
stdin e stdout e viene avviato con l'identita' che stabilisci tu nella
cfg di inetd. Vedi le man pages di inetd per i dettagli.
Altrimenti un demone tout-court lo puoi fare ricordandoti di alcune regole:
- girare in background
- chiudere i file non usati (cioe' tutti)
- settale l'umask in modo conservativo
- settare la working dir. in un posto sicuro
- fatto!
Ecco un esempio:
    #!/bin/bash
    if [ "$1" != daemon ]; then
        exec $0 daemon &
        exit 0
    fi
    0<&-
    1<&-
    2<&-
    umask 0
    cd /
    logger "$0: ciao, sono id=$( id )"
    ...
Per avviarlo con una data identita' meno privilegiata di root:
    # su -c /path/del/demone - unutente
dove "unutente" deve essere un utente esistente.
Ciao,
// Umberto Salsi
//
// 
http://digilander.libero.it/salsi
  --  GnuPG Key ID = BE2C F6CD 77E9 29AE

 - fatto!
uhm... domanda: un demone non dovrebbe anche "slinkarsi" dal terminale di 
controllo? intendo riferirmi a quel "double fork" di cui si parla in 
certi documenti...
HappyCactus con un paio di dubbi da sciogliere...
-- 
HappyCactus - Registered Linux User #209744
http://www.angelfire.com/jazz/happycactus/index.html
Made with 100% recycled electrons

certi documenti...
Dovrebbe essere una cosa del genere: 
--------
int pid;
.
.
.
pid = fork();
if (pid == 0) { /* FIGLIO */
	pid = fork();
	if (pid == 0) { /* figlio del figlio */
		...esegui ciò che vuoi...
		} // fine del figlio del figlio
	else { //Figlio
 
	waitpid(parametri) // Aspetta la terminazione
 
	} // Fine figlio
} 
/* qui c'è il padre che termina e quindi restituisce
*  subito il controllo all'utente */
} // Fine programma, cioè del main che ho tralasciato
------
Spero di aver scritto giusto 


si`, quello che hai scritto e` giusto, solo che non c'entra nulla con il
discorso ;)
O meglio, c'entra, ma si chiedeva come programmare demoni in bash, non (come hai
scritto tu) in C. ^__^
Adieu,
-- 
Lestat de Lioncourt                               |          Ciro Mattia Gonano
  JabberID: 
les...@jabber.students.cs.unibo.it
    |    Undergraduate Student in
  ICQ#: 52631406                                  |         Computer Science at
  URL: 
http://www.CS.UniBO.It/~gonano
             |       University of Bologna
            <powered by Linux Slackware 8.1 on Kernel 2.4.18-xfs>

 certi documenti...
Giusto, bisogna (si dovrebbe) invocare setsid() per togliere il terminale
di controllo per vari motivi. In realta', una volta chiusa la shell di
partenza, il terminale di controllo del daemon viene comunque "azzerato".
Il doppio fork, invece, non c'entra nulla col terminale di controllo e
non credo proprio che sia necessario in GNU/Linux.
Un'altra cosa: il cd meglio farlo in una dir. dove il demone abbia
permesso di scrittura, in modo da accogliere eventuali core file, e
poi meglio redirigere stdout e stderr su di un file di log, in modo da
facilitare il debugging dello script.
P.S. - Non so' cosa ci si possa fare con un demone bash che non si
possa fare o con inetd o con crontab, ma la cosa e' comunque curiosa
da investigare...


 non credo proprio che sia necessario in GNU/Linux.
Hai ragione, non c'entra nulla.
AFAIR, il doppio fork serve per permettere il rilascio delle risorse 
senza utilizzare il "waitpid"... ma qui lo dico e qui lo nego! ho molta 
confusione in testa, devo ammetterlo! :P


 SIGPIPE?!? boh... gran confusione in testa!!!)
Premessa: ogni processo, tra le infinite proprieta', ha in PID del
processo leader del gruppo (pgrp), il PID del processo leader
di sessione (session)
Allora, setsid() produce i seguenti effetti:
(ho recuperato questo spezzone di sorgente dalla macchina che sto
usando, ./kernel/sys.c, che credo sia proprio quello che ci interessa: )
asmlinkage long sys_setsid(void)
{
        struct task_struct * p;
        int err = -EPERM;
// se il processo e' leader di gruppo di processi, e' un errore:
        read_lock(&tasklist_lock);
        for_each_task(p) {
                if (p->pgrp == current->pid)
                        goto out;
        }
// il processo si scollega dalla sessione corrente e ne crea una
// nuova diventando nuovo session leader; inoltre, il processo si
// scollega dal gruppo di processi e crea un nuovo gruppo di processi:
        current->leader = 1;
        current->session = current->pgrp = current->pid;
// il terminale di controllo /dev/tty diventa nullo:
        current->tty = NULL;
        current->tty_old_pgrp = 0;
        err = current->pgrp;
out:
        read_unlock(&tasklist_lock);
        return err;
}
Effetti pratici in soldoni e considerazioni varie (in ordine sparso):
- quando in bash fai una pipe "ls | grep pippo" ti crea un nuovo gruppo
di processi (ls e grep) e se premi CTRL-C bash sa' a chi deve mandare
il SIGINT, e cioe' al gruppo di processi in foreground (stty -a ti da'
tutte le combinazioni di tasti predisposte);
- il processo non riceve piu' eventuali segnali inviati al gruppo di
processi di cui faceva parte (killpg()) perche' ora appartiene a un
nuovo gruppo (ma chi si prende la briga di fare questo? bho!);
- se il processo muore, non invia segnali ad un eventuale padre che e'
in attesa su waitpid() (ci interessa poco: i padre avvia il demone e
quant'altro, poi esce e il demone-figlio finisce in adozione a init);
- i processi appartenenti alla stessa sessione (corrispondente a un
terminale) sono gli unici che ti presenta ps se lo dai senza parametri
(quindi, il nostro demone senza setsid() vi apparirebbe): questo si'
che e' essere ordinati!
- se il terminale che controlla la sessione viene chiuso, il terminale
invia il SIGHUP a bash (cioe' al leader di sessione), e questo a sua
volta lo invia ai gruppi di processi (in realta' la cosa e' un po' piu'
intricata, v. man bash alla voce SIGHUP e huponexit, per cui le versioni
recenti di bash>=2 per default non lo fanno), ma il nostro demone che ha
fatto setsid() ovviamente non lo riceve perche' e' in un'altra sessione;
- osservazione: vi sarete accordi che da qualche tempo il comando
nohup e' stato messo da parte, ed e' diventato piu' facile mettere in
background i processi e chiudere il terminale o l'xterm senza lagne;
- altri fenomeni che non so o non mi ricordo (credo se sul solito APUE
ci sia una discussione piu' dettagliata e sicuramente meno buggata di
questa).
Morale: esiste sia la funzione setsid() da chiamare in C, sia il comando
setsid da invocare da shell: usiamolo per i nostri demoni bash! (se ci
ricordiamo... ;-).


 risorse senza utilizzare il "waitpid"...
sgnaups. Serve a sbloccare la shell che ha avviato il demone, se è 
stato avviato con attesa (senza il "&" dopo). Non ha nessun altro 
effetto
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!

 effetto
Bene, grazie mille per la lezione.
Penso che ne ho ancora di lavoro da fare. Intanto spero che il collega 
qui abbia finito di stamparmi l'Advanced Linux Programming, che terro' 
sul comodino accanto al letto assieme al Vangelo ;b


Vi ringrazio per aver dato vita alla discussione ma il mio problema rimane.
Vorrei fare uno script in BASH che gira sul client che mi deve controllare
ogni x minuti chi e' connesso e mandare il segnale al server per gestire la
connessione .
Voi parlate di inetd o crontab, ma come lo gestisco con inted? e crontab non
mi permette di eseguirlo ogni 2 minuti (forse sbaglio).
Grazie a tutti comunque.

mi permette di eseguirlo ogni 2 minuti (forse sbaglio).
crontab ti permette di eseguirlo ogni due miniuti cosi':
	*/2 * * * *  /path/verso/il/tuo/script
c'e' l'esempio su    
	man 5 crontab
Ciao,
luigi

Grazie Luigi,
come al solito la risposta si trova (non sempre) nel manuale.
Avevo visto solo gli esempi della distribuzione.
P.S.: il tuo nome non mi e' nuovo, collabori con qualche rivista?
Grazie mille.