discuss: Thread: Linux Daemon HOWTO


[<<] [<] Page 1 of 1 [>] [>>]
Subject: Linux Daemon HOWTO
From: Devin Watson ####@####.####
Date: 18 May 2004 22:56:24 -0000
Message-Id: <1084920957.23696.19.camel@PVR>

	Everyone - 

	I've written a somewhat short but informative introduction into writing
daemons in Linux. I noticed that this isn't really out there right now,
and I thought I'd at least try my hand at writing this.

	The SGML (LinuxDoc) file can be found at:

	http://www.linuxprofilm.com/articles/linux-daemon-howto.sgml

	I've also got HTML and PDF versions there:

	http://www.linuxprofilm.com/articles/linux-daemon-howto.html
	http://www.linuxprofilm.com/articles/linux-daemon-howto.pdf

	I'd like any suggestions and feedback on this.

	-Devin Watson

Subject: Re: Linux Daemon HOWTO
From: Charles Curley ####@####.####
Date: 18 May 2004 23:45:40 -0000
Message-Id: <20040518234534.GB20761@charlescurley.com>

On Tue, May 18, 2004 at 06:55:57PM -0400, Devin Watson wrote:
> 	Everyone - 
> 
> 	I've written a somewhat short but informative introduction into writing
> daemons in Linux. I noticed that this isn't really out there right now,
> and I thought I'd at least try my hand at writing this.
> 
> 	The SGML (LinuxDoc) file can be found at:
> 
> 	http://www.linuxprofilm.com/articles/linux-daemon-howto.sgml
> 
> 	I've also got HTML and PDF versions there:
> 
> 	http://www.linuxprofilm.com/articles/linux-daemon-howto.html
> 	http://www.linuxprofilm.com/articles/linux-daemon-howto.pdf
> 
> 	I'd like any suggestions and feedback on this.

Don't forget to add a copyright statement and license, both for the
LDP's protection and for your own.

It's been a while since I engaged in daemonology :-), but shouldn't
this:

        /* Open any logs here */
        
        /* Change the current working directory */
        if ((chdir("/")) < 0) {
                exit(EXIT_FAILURE);
        }

be:

        /* Open any logs here */
        
        /* Change the current working directory */
        if ((chdir("/")) < 0) {
   		/* Log failure, then close logs */


		exit(EXIT_FAILURE);
        }

You should probably log the failure so that the user knows she doesn't
have a necessary directory. In that case, if you are handling your
log files yourself, you have to close them gracefully before you exit
so that the last few entries are preserved.

Also, I doubt you want a daemon to run in /.

I'm not sure how you open log files in daemons in Linux, but shouldn't
you set umask before you open a log file?

These are nit picks. The code you have shows how to do it. As this is
an instructional article, the code should not get loaded down with
error checking to the point that it obscures your main point. You
might suggest ways to tighten up the code at the end.

I like it. It's short, sweet and to the point. The user can go from
there. Well done.

-- 

Charles Curley                  /"\    ASCII Ribbon Campaign
Looking for fine software       \ /    Respect for open standards
and/or writing?                  X     No HTML/RTF in email
http://www.charlescurley.com    / \    No M$ Word docs in email

Key fingerprint = CE5C 6645 A45A 64E4 94C0  809C FFF6 4C48 4ECD DFDB

--> -->
 
 
<type 'exceptions.IOError'>
Python 2.5.2: /usr/bin/python
Sat Jul 6 03:36:13 2024

A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.

 /opt/ezmlm-browse-0.20/<string> in ()
 /opt/ezmlm-browse-0.20/main.py in main()
  424 
  425         if path is not None:
  426                 main_path(path)
  427         else:
  428                 main_form()
global main_form = <function main_form at 0x9332c6c>
 /opt/ezmlm-browse-0.20/main.py in main_form()
  378         except ImportError:
  379                 die(ctxt, "Invalid command")
  380         module.do(ctxt)
  381 
  382 def main():
module = <module 'commands.showthread' from '/opt/ezmlm-browse-0.20/commands/showthread.pyc'>, module.do = <function do at 0x933b844>, global ctxt = {'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}
 /opt/ezmlm-browse-0.20/commands/showthread.py in do(ctxt={'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'})
    9         ctxt.update(ezmlm.thread(ctxt[THREADID]))
   10         header(ctxt, 'Thread: ' + ctxt[SUBJECT], 'showthread')
   11         do_list(ctxt, 'msgs', ctxt[MSGSPERPAGE], ctxt[MESSAGES],
   12                         lambda:sub_showmsg(ctxt, ctxt[MSGNUM]))
   13         footer(ctxt)
global sub_showmsg = <function sub_showmsg at 0x93321ec>, ctxt = {'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, global MSGNUM = 'msgnum'
 /opt/ezmlm-browse-0.20/globalfns.py in do_list(ctxt={'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, name='msgs', perpage=10, values=[{'author': u'Devin Watson', 'authorid': 'hpddcdpgimaaaodmebkg', 'date': '18 May 2004 22:56:24 -0000', 'month': 200405, 'msgnum': 7301, 'subject': u'Linux Daemon HOWTO', 'threadid': 'pabfjdhhafocknlohihp', 'timestamp': 1084920984.0}, {'author': u'Charles Curley', 'authorid': 'fbacfjfdkmpbdhgmbbhp', 'date': '18 May 2004 23:45:40 -0000', 'month': 200405, 'msgnum': 7302, 'subject': u'Re: Linux Daemon HOWTO', 'threadid': 'pabfjdhhafocknlohihp', 'timestamp': 1084923940.0}, {'author': u'Colin Watson', 'authorid': 'apcdgkbgafajaibhibkf', 'date': '19 May 2004 16:37:20 -0000', 'month': 200405, 'msgnum': 7306, 'subject': u'Re: Linux Daemon HOWTO', 'threadid': 'pabfjdhhafocknlohihp', 'timestamp': 1084984640.0}, {'author': u'Devin Watson', 'authorid': 'hpddcdpgimaaaodmebkg', 'date': '19 May 2004 22:30:19 -0000', 'month': 200405, 'msgnum': 7307, 'subject': u'Re: Linux Daemon HOWTO', 'threadid': 'pabfjdhhafocknlohihp', 'timestamp': 1085005819.0}, {'author': u'Devin Watson', 'authorid': 'hpddcdpgimaaaodmebkg', 'date': '19 May 2004 23:24:19 -0000', 'month': 200405, 'msgnum': 7308, 'subject': u'Re: Linux Daemon HOWTO', 'threadid': 'pabfjdhhafocknlohihp', 'timestamp': 1085009059.0}], peritem=<function <lambda> at 0x933b9cc>)
  128                 write(template % ctxt)
  129                 if peritem:
  130                         peritem()
  131                 ctxt[ROW] += 1
  132 
peritem = <function <lambda> at 0x933b9cc>
 /opt/ezmlm-browse-0.20/commands/showthread.py in ()
    9         ctxt.update(ezmlm.thread(ctxt[THREADID]))
   10         header(ctxt, 'Thread: ' + ctxt[SUBJECT], 'showthread')
   11         do_list(ctxt, 'msgs', ctxt[MSGSPERPAGE], ctxt[MESSAGES],
   12                         lambda:sub_showmsg(ctxt, ctxt[MSGNUM]))
   13         footer(ctxt)
global sub_showmsg = <function sub_showmsg at 0x93321ec>, ctxt = {'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, global MSGNUM = 'msgnum'
 /opt/ezmlm-browse-0.20/globalfns.py in sub_showmsg(ctxt={'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, msgnum=7302)
  229         format_timestamp(ctxt, ctxt)
  230         write(html('msg-header') % ctxt)
  231         rec_showpart(ctxt, msg, 0)
  232         write(html('msg-footer') % ctxt)
  233         ctxt.pop()
global rec_showpart = <function rec_showpart at 0x93321b4>, ctxt = {'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, msg = <email.message.Message instance at 0x9390ecc>
 /opt/ezmlm-browse-0.20/globalfns.py in rec_showpart(ctxt={'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, part=<email.message.Message instance at 0x9390ecc>, partnum=1)
  205                 else:
  206                         for p in part.get_payload():
  207                                 partnum = rec_showpart(ctxt, p, partnum+1)
  208         else:
  209                 write(html('msg-sep') % ctxt)
partnum = 1, global rec_showpart = <function rec_showpart at 0x93321b4>, ctxt = {'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, p = <email.message.Message instance at 0x93970cc>
 /opt/ezmlm-browse-0.20/globalfns.py in rec_showpart(ctxt={'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, part=<email.message.Message instance at 0x93970cc>, partnum=2)
  208         else:
  209                 write(html('msg-sep') % ctxt)
  210                 sub_showpart(ctxt, part)
  211         return partnum
  212 
global sub_showpart = <function sub_showpart at 0x9332144>, ctxt = {'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, part = <email.message.Message instance at 0x93970cc>
 /opt/ezmlm-browse-0.20/globalfns.py in sub_showpart(ctxt={'HTTP_X_FORWARDED_SERVER': 'glitch', 'HTTP_REFE...HTTP_ACCEPT_ENCODING': 'gzip, br, zstd, deflate'}, part=<email.message.Message instance at 0x93970cc>)
  164         type = ctxt[TYPE] = part.get_content_type()
  165         ctxt[FILENAME] = part.get_filename()
  166         template = html('msg-' + type.replace('/', '-'))
  167         if not template:
  168                 template = html('msg-' + type[:type.find('/')])
global template = <function template at 0x932ae9c>, global html = <function html at 0x932aed4>, type = 'application/pgp-signature', type.replace = <built-in method replace of str object at 0x9399020>
 /opt/ezmlm-browse-0.20/globalfns.py in html(name='msg-application-pgp-signature')
   40 
   41 def html(name):
   42         return template(name + '.html')
   43 
   44 def xml(name):
global template = <function template at 0x932ae9c>, name = 'msg-application-pgp-signature'
 /opt/ezmlm-browse-0.20/globalfns.py in template(filename='msg-application-pgp-signature.html')
   31         except IOError:
   32                 if not _template_zipfile:
   33                         _template_zipfile = zipfile.ZipFile(sys.argv[0])
   34                 try:
   35                         f = _template_zipfile.open(n).read()
global _template_zipfile = None, global zipfile = <module 'zipfile' from '/usr/lib/python2.5/zipfile.pyc'>, zipfile.ZipFile = <class zipfile.ZipFile at 0x92c3a7c>, global sys = <module 'sys' (built-in)>, sys.argv = ['-c', '/opt/ezmlm-browse-0.20']
 /usr/lib/python2.5/zipfile.py in __init__(self=<zipfile.ZipFile instance at 0x9390e4c>, file='-c', mode='r', compression=0, allowZip64=False)
  337             self.filename = file
  338             modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
  339             self.fp = open(file, modeDict[mode])
  340         else:
  341             self._filePassed = 1
self = <zipfile.ZipFile instance at 0x9390e4c>, self.fp = None, builtin open = <built-in function open>, file = '-c', modeDict = {'a': 'r+b', 'r': 'rb', 'w': 'wb'}, mode = 'r'

<type 'exceptions.IOError'>: [Errno 2] No such file or directory: '-c'
      args = (2, 'No such file or directory')
      errno = 2
      filename = '-c'
      message = ''
      strerror = 'No such file or directory'