daemon vraag

Pagina: 1
Acties:
  • 105 views sinds 30-01-2008
  • Reageer

  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
Ik ben een daemon aan het schrijven en vraag me af hoe je een daemon netjes afsluit. Op dit moment stuur ik gewoon een kill signaal. De daemon sluit dan af, maar laat de pid file staan. Is het de bedoeling dat de daemon zelf zijn pidfile verwijderd of is dat de verantwoordelijkheid van bijv. een initscript?
Ik heb o.a. deze howto gelezen maar ben het antwoord op mijn vraag niet tegen gekomen.

  • moto-moi
  • Registratie: Juli 2001
  • Laatst online: 09-06-2011

moto-moi

Ja, ik haat jou ook :w

Ik denk dat deze link over het catchen van signals wel handig zal zijn ? :P

God, root, what is difference? | Talga Vassternich | IBM zuigt


  • RagaBaSH
  • Registratie: Januari 2001
  • Laatst online: 27-11-2025

RagaBaSH

Huttenbouwer

lijkt me dat je in je deamon zelf een "exit()" procedure wil hebben.
in deze procedure zorg je dat alle taken die nog gepland staan afgehandeld worden (evt. met een timeout voor rogue processes), dat alle logs keurig bijgewerkt en gesloten worden, pid-file opruimen,dan met exit() sluit je de deamon zelf af.
Aanroepen met "deamon --close" of "deamon stop" misschien?

kill is over het algmeen dat je deamon niet goed functioneerd, vergelijk het met een grafisch programma zonder "exit" of "close" knop. dan moet je dus altijd het main process killen via een taskmanager of CLI.. ofwel. niet wenselijk.

BTW, lijkt me meer een programming vraag aangezien het om de C code gaat, niet zo zeer om linux-specifieke problemen. (dat jij in je code de pidfile niet opruimt.... sja... )

[ Voor 7% gewijzigd door RagaBaSH op 20-12-2005 10:32 ]

Zes pallets, een paar vierkante kilometer dekzeil en een zooi verroeste spijkers is geen troep. Dat is een hut in ontkenningsfase.


  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
OK bedankt. De oplossing van RagaBaSH lijkt me het elegantst. Het gaat trouwens niet om C code, maar om python.

  • psyBSD
  • Registratie: April 2004
  • Laatst online: 02-01-2021

psyBSD

Hates 0x00 bytes

Laat je programma gewoon netjes exitten als je SIG_TERM krijgt. Daar istie voor bedoeld.

In je signal-handler laat je die deamon dan alles opruimen voordat hij afsluit.

[ Voor 33% gewijzigd door psyBSD op 20-12-2005 11:25 ]

| Olympus OM-D EM10 mk2 | m.Zuiko 14-42mm f/3.5-5.6EZ | m.Zuiko 40-150mm f/4-5.6 R | m.Zuiko 60mm f/2.8 | 2x Godox v860 | Godox X1 |


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 08-02 12:49

Robtimus

me Robtimus no like you

IMHO moet degene die de pid file aanmaakt hem ook weer opruimen. Dat hoeft dus niet per se je programma zijn, dat kan ook je script zijn.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Boudewijn
  • Registratie: Februari 2004
  • Niet online

Boudewijn

omdat het kan

IceManX schreef op dinsdag 20 december 2005 @ 13:34:
IMHO moet degene die de pid file aanmaakt hem ook weer opruimen. Dat hoeft dus niet per se je programma zijn, dat kan ook je script zijn.
eensch


mooi link trouwens moto :)

[ Voor 6% gewijzigd door Boudewijn op 20-12-2005 15:29 ]

Zaram module kopen voor je glasvezelaansluiting?


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

RagaBaSH schreef op dinsdag 20 december 2005 @ 10:31:
kill is over het algmeen dat je deamon niet goed functioneerd, vergelijk het met een grafisch programma zonder "exit" of "close" knop. dan moet je dus altijd het main process killen via een taskmanager of CLI.. ofwel. niet wenselijk.
kill wordt ook gebruikt voor de normale gang van zaken hoor:
SIGHUP -> herlees configuratiebestand
SIGTERM -> sluit netjes af
SIGKILL -> die bastard die >:)

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • RagaBaSH
  • Registratie: Januari 2001
  • Laatst online: 27-11-2025

RagaBaSH

Huttenbouwer

@kenneth:

tuurlijk, maar de deamon moet alsnog die signalen netjes afvangen (zoals moto-moi al voorstelde), ik bedoelde meer dat als ik een deamon gebruik die ik perse moet killen met `kill` er meestal geen andere oplossing voor is, het is nou eenmaal niet de meest gebruikersvriendelijke optie. (doe er dan tenminste een scriptje ala apachectl bij)

Zes pallets, een paar vierkante kilometer dekzeil en een zooi verroeste spijkers is geen troep. Dat is een hut in ontkenningsfase.


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Vind ik ook, het is echter wel gebruikelijk. Hoewel de start-stop-scripts op verschillende platformen inmiddels gemeengoed zijn.

Het is trouwens daemon, geen deamon ;)

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
OK. Inmiddels heb ik de daemon code uitgebruid. Als mijn daemon een SIGTERM krijgt (gebeurd met daemon> stop commando ;) ), sluit hij netjes af. Ik heb nog een vraag

Als ik op mijn eigen computer in een xterm onder mijn eigen account mijn daemon draai, werkt alles naar behoren. Maar op de computer waar het programma moet gaan draaien kan ik niet uitloggen nadat ik de daemon heb gestart in een ssh sessies. Volgens mij betekent dat de daemon niet los is van de (pseudo)terminal van de ssh sessie. Dat betekent, alweer volgnes mij, dat de setsid niet goed wordt uitgevoerd. Wat kan er hier aan de hand zijn?
Dit is de relevante python code van de daemon:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
try:
    pid = os.fork()
    if pid > 0:
        # exit first parent
        sys.exit(0)
except OSError, e:
    print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
    sys.exit(1)

# decouple from parent environment
os.chdir("/")   #don't prevent unmounting....
os.setsid()
os.umask(0)

# do second fork
try:
    pid = os.fork()
    if pid > 0:
        # exit from second parent, print eventual PID before
        #print "Daemon PID %d" % pid
        open(PIDFILE,'w').write("%d"%pid)
        sys.exit(0)
except OSError, e:
    print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
    sys.exit(1)
#change to data directory if needed
os.chdir(RUNDIR)
#close stdin
sys.stdin.close()
#redirect outputs to a logfile
sys.stdout = sys.stderr = Log(LOGFILE)
#ensure the that the daemon runs a normal user
os.setegid(GID)  #set group
os.seteuid(UID)  #set user


De output van ps ziet er zo uit:
29296 ? S 0:00 /usr/bin/python ./Daemon.py
Dat vraagteken suggereert weer dat mijn daemon toch geen (pseudo)terminal heeft. Wat kan dan door oorzaak zijn van het niet kunnen uitloggen? Gebrek aan permissies?

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
code:
2
3
4
5
    pid = os.fork()
    if pid > 0:
        # exit first parent
        sys.exit(0)
Ziet er nogal onnuttig uit?
edit:
Bedankt voor de uitleg Kenneth. :) Ben zelf gewend dat je fork doet en het kind iets laat doen, zoals bijvoorbeeld exec iets en de parent gewoon laat wachten of door laat gaan met iets anders. Ik dach niet aan terminal controle, ik dacht gewoon, 'hee, een nieuw proces en volgende regel een proces weghalen, das vreemd'. :P

[ Voor 57% gewijzigd door Voutloos op 23-12-2005 07:47 ]

{signature}


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Hij forkt, resultaat is identiek parent en child process, m.u.v. de return value van os.fork()
De parent krijgt de pid van de child terug, de child krijgt 0 terug.
Kortom, dat stuk code zorgt ervoor dat de parent stopt, en de daemon zelf verder gaat als child process., waardoor de gebruiker controle terug krijgt over de terminal.

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
edit:
Hier stond onzin, kenneth heeft gewoon gelijk

[ Voor 81% gewijzigd door Sir Isaac op 23-12-2005 01:08 ]


  • RagaBaSH
  • Registratie: Januari 2001
  • Laatst online: 27-11-2025

RagaBaSH

Huttenbouwer

ik mis in je code de check of je wel een goeie sid hebt gekregen:
C:
1
2
3
4
5
6
/* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                /* Log any failure here */
                exit(EXIT_FAILURE);
        }


deze haal ik direct uit je voorbeeld page, misschien dat je hem per abuis hebt overgeslagen.
waarom fork je 2x btw? 1x naar de background forken moet toch genoeg zijn?

als je goed je remote systeem wil emuleren kan je misschien proberen om een ssh connectie te maken naar je localhost en dan je daemon (@kenneth ;)) draaien, het kan zijn dat het een ssh-related probleem is.

Zes pallets, een paar vierkante kilometer dekzeil en een zooi verroeste spijkers is geen troep. Dat is een hut in ontkenningsfase.


  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
Ik heb voor mijn daemon wat python code van het net geplukt waarin setsid idd niet werd gecontroleerd. Dit blijkt inderdaad het punt te zijn waarop het fout gaat: setsid() geeft "None" as return. De terminal wordt idd dus niet losgelaten.

Mijn eerste gedachte was dat het aanroepen van setsid() aan root vvoorbehouden is, maar als ik mijn Daemon als root run, krijg ik hetzelfde resultaat. Waarom mislukt setsid() ?

Dat ik op de remote server niet kon uitloggen zonder mij daemon te killen kwam idd door de combinatie met ssh. Met een ssh naar mijn localhost kan ik ook niet uitloggen.

Twee keer forken wordt aangeraden omdat de daemon weer een controlling terminal krijgt als hij een pseudoterminal opent.

[ Voor 11% gewijzigd door Sir Isaac op 23-12-2005 15:20 ]


  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
setsid was het probleem niet, die returnt onder python altijd None, terwijl de process group id wel wordt aangepast.
Volgens de ssh faq zijn er 3 mogelijke oorzaken:
ssh hangs:
1 until it can be sure that command does not need more input.
2 until it can be sure that command does not produce more output.
3 until command exits because sshd needs to tell the exit status from command to ssh.

1 kan het niet zijn omdat de parent exit.
Om 2 en 3 af te vangen doe ik nu het volgende:
code:
1
2
3
sys.stdin.close()
sys.stdout.close()
sys.stderr.close()

Dat zou toch genoeg moeten zijn? Toch kan ik nog steeds niet uitloggen als ik met ssh ben ingelogd. Rara.

  • igmar
  • Registratie: April 2000
  • Laatst online: 31-01 23:50

igmar

ISO20022

En wat zegt lsof over de daemon ? Je kan dan nakijken of de daemon nog een terminal geopend heeft.

  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
Daar komt wel een aap uit de mouw:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
COMMAND  PID    USER   FD   TYPE DEVICE    SIZE   NODE NAME
python  9791 username  cwd    DIR    3,5    8192  80641 /tmp
python  9791 username  rtd    DIR    3,5    4096      2 /
python  9791 username  txt    REG    3,5  986924 452129 /usr/bin/python2.4
python  9791 username  mem    REG    0,0              0 [heap] (stat: No such fil e or directory)
python  9791 username  mem    REG    3,5   15780 388751 /usr/lib/python2.4/lib-dy nload/time.so
python  9791 username  mem    REG    3,5 1613376 524549 /usr/lib/locale/locale-ar chive
python  9791 username  mem    REG    3,5 1226096 392458 /lib/tls/i686/cmov/libc-2 .3.5.so
python  9791 username  mem    REG    3,5  136720 392461 /lib/tls/i686/cmov/libm-2 .3.5.so
python  9791 username  mem    REG    3,5    7696 392476 /lib/tls/i686/cmov/libuti l-2.3.5.so
python  9791 username  mem    REG    3,5    8252 392460 /lib/tls/i686/cmov/libdl- 2.3.5.so
python  9791 username  mem    REG    3,5   86676 392471 /lib/tls/i686/cmov/libpth read-2.3.5.so
python  9791 username  mem    REG    3,5   86596 392357 /lib/ld-2.3.5.so
python  9791 username    0u   CHR  136,2              4 /dev/pts/2
python  9791 username    1u   CHR  136,2              4 /dev/pts/2
python  9791 username    2u   CHR  136,2              4 /dev/pts/2

Volgens mijn betekenen die laatste drie regels dat stdin, stdout en stderr toch nog open zijn. De rest lijkt me wel OK. Wat voor reden zou er kunnen zijn dat de standaard file descriptors niet worden gesloten?

[ Voor 5% gewijzigd door Sir Isaac op 26-12-2005 13:05 ]


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

/dev/pts/2 is alleen stderr, je hebt dus alles geredirect naar stderr :?

D'oh! Niet meer posten tussen kerstdiner en kerstdessert in :+

[ Voor 37% gewijzigd door kenneth op 26-12-2005 23:59 ]

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • MikeN
  • Registratie: April 2001
  • Laatst online: 05-02 20:14
http://aspn.activestate.c...book/Python/Recipe/186101 fixte het bij mij :)

kenneth: /dev/pts/2 is gewoon de 3e pts, heeft niets met stderr te maken.

  • Sir Isaac
  • Registratie: September 2002
  • Laatst online: 21-05-2025
Bedankt, ik had deze methode net zelf gevonden in een ander PythonRecipe. Daarin stond alleen de reden hiervoor niet genoemd. Ik heb dit op python-list gevraagd. Het antwoord zal ik hier posten. In ieder geval werkt mijn daemon nu.

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 30-01 01:49

Sprite_tm

Semi-Chinees

Sir Isaac schreef op zondag 25 december 2005 @ 01:01:
Om 2 en 3 af te vangen doe ik nu het volgende:
code:
1
2
3
sys.stdin.close()
sys.stdout.close()
sys.stderr.close()
Wat in C meestal gebeurt is de stdin/out/err redirecten (door middel van open()/dup()) naar /dev/null. Op die manier gaat je programma niet meteen vreemd doen als er toevallig op de een of andere obscure manier toch nog naar stdin/out geschreven word (wat in jouw geval naar een gesloten file descriptor zou gaan, wat waarschijnlijk voor vreemde resultaten zou zorgen)

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


  • MikeN
  • Registratie: April 2001
  • Laatst online: 05-02 20:14
Mja, deze methode kan ook raar gaan doen als je Python C modules gebruikt en die toevallig naar stderr proberen te schrijven. Daarom staat hier in de comments ook dit stukje code:

Python:
1
2
3
4
5
sys.stdout.flush()
sys.stderr.flush()
os.dup2(out_log.fileno(), sys.stdout.fileno())
os.dup2(err_log.fileno(), sys.stderr.fileno())
os.dup2(dev_null.fileno(), sys.stdin.fileno())
Pagina: 1