# Daemonize like fetchmail

**URL:** <https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351>\
**Category:** Ruby\
**Created:** [January 5, 2006, 9:48pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351 "2006-01-05T21:48:40Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 5, 2006, 9:48pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/1 "2006-01-05T21:48:40Z")

</div>

Has anyone used the Daemons library ([http://daemons.rubyforge.org/](http://daemons.rubyforge.org/))  
extensively? I’m trying to do something that doesn’t appear covered by  
the examples, and I’m wondering if I need to reinvent the wheel.

What I’d like to do is to easily add functionality to my script similar  
to the way that fetchmail works, ie:

When starting the script with one command-line option (eg: --daemon), I  
daemonize it and start it running (saving the PID in a file).

When starting the script with another command-line option (eg: --stop),  
it finds the PID file and kills the instance.

In a sense, I’d like to combine the wrapper method given in the examples  
and the script it runs, but the wrapper example seems to absorb  
command-line options, and I want to call those functions from within  
Ruby instead.

Suggestions?

-Payton

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 5, 2006, 10:27pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/2 "2006-01-05T22:27:46Z")

</div>

On Fri, 6 Jan 2006, Payton S. wrote:

> When starting the script with another command-line option (eg: --stop), it  
> finds the PID file and kills the instance.
> 
> In a sense, I’d like to combine the wrapper method given in the examples and  
> the script it runs, but the wrapper example seems to absorb command-line  
> options, and I want to call those functions from within Ruby instead.
> 
> Suggestions?
> 
> -Payton

ruby queue and dirwatch both do this.

[http://codeforpeople.com/lib/ruby/dirwatch/](http://codeforpeople.com/lib/ruby/dirwatch/)  
[http://codeforpeople.com/lib/ruby/rq/](http://codeforpeople.com/lib/ruby/rq/)

atomic creation of files is trickier than one might imagine. is this on  
\*nix?  
is so checkout my lockfile class and posixlock. it’s very important to  
note  
that there is ONE atomic creation operator on \*nix and it is NOT open or  
mkdir - symlink is the one. ‘man lockfile’ might be illuminating.

cheers.

-a

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 10, 2006, 3:55pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/3 "2006-01-10T15:55:30Z")

</div>

Well, I did it myself anyway. Hope it’s useful:  
[http://rubyforge.org/projects/pidify/](http://rubyforge.org/projects/pidify/)

-Payton

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 10, 2006, 4:25pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/4 "2006-01-10T16:25:59Z")

</div>

On Tue, 10 Jan 2006, Payton S. wrote:

> Well, I did it myself anyway. Hope it’s useful:  
> [http://rubyforge.org/projects/pidify/](http://rubyforge.org/projects/pidify/)
> 
> -Payton

it does look useful. few comments/suggestions though

- since it’s \*nix specify anyhow you might want to use O\_EXCL when  
opening  
the file since otherwise there is a race condition to create the  
file

- on the same page using File#flock with File::LOCK\_EX when writing  
and  
File::LOCK\_SH for writing and reading (with File::LOCK\_NB of  
course) will  
avoid the race conditions and possibibity of reading a half-baked  
file

- escalation of signals with a pause between is useful for killing  
processes  
since many trap signit and most do not die immediately. something  
like

- the alive function above can be something like this

cheers.

## -a

# =============================================================================== | ara [dot] t [dot] howard [at] noaa [dot] gov | strong and healthy, | who thinks of sickness until it strikes like lightning? | preoccupied with the world, | who thinks of death, until it arrives like thunder? | – milarepa

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 10, 2006, 5:53pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/5 "2006-01-10T17:53:41Z")

</div>

Would this be correct usage of the file, then?

```
def pid
   dpid = nil
   File.open(pid_file, File::RDONLY) { |file| dpid = file.gets.chomp

```

if file.flock(File::LOCK\_SH|File::LOCK\_NB); file.flock(File::LOCK\_UN) }  
if pid\_exists?  
dpid.to\_i  
end

```
 def save_pid
   File.open(pid_file, File::CREAT|File::EXCL|File::WRONLY) { |file|

```

file.puts $$ if file.flock(File::LOCK\_EX); file.flock(File::LOCK\_UN) }  
end

-Payton

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 10, 2006, 6:26pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/6 "2006-01-10T18:26:53Z")

</div>

On Wed, 11 Jan 2006, Payton S. wrote:

> def save\_pid  
> File.open(pid\_file, File::CREAT|File::EXCL|File::WRONLY) { |file|  
> file.puts $$ if file.flock(File::LOCK\_EX); file.flock(File::LOCK\_UN) }  
> end

more or less. it can still get slippery though. consider:

def pid  
dpid = nil  
File.open(pid\_file, File::RDONLY) { |file| dpid = file.gets.chomp  
if file.flock(File::LOCK\_SH|File::LOCK\_NB); file.flock(File::LOCK\_UN) }  
if pid\_exists?  
dpid.to\_i  
end

```
   - if the file does not exists this returns nil.to_i, which is 0

   - races still exist:

       0) process a: reader opens existing pidfile

       1) process b: removes pidfile

       2) process a: read lock obtained, pid read

     this works because:

       harp:~ > irb
       irb(main):001:0> open('pid','w'){|f| f.write Process::pid}
       => 4
       irb(main):002:0> f = open 'pid'
       => #<File:pid>
       irb(main):003:0> File::unlink 'pid'
       => 1
       irb(main):004:0> File::exists? 'pid'
       => false
       irb(main):005:0> f.flock File::LOCK_SH|File::LOCK_NB
       => 0
       irb(main):006:0> f.read
       => "4000"

     i think this can be solved by only removing the file while 

```

holding a  
write lock.

def save\_pid  
File.open(pid\_file, File::CREAT|File::EXCL|File::WRONLY) do |file|  
file.puts $$ if file.flock(File::LOCK\_EX);  
file.flock(File::LOCK\_UN)  
end  
end

```
     - on some filesystems File::EXCL does not work. on those 

```

systems two  
process can succeed in opening the file for writing, waiting  
for the  
lock, and then writing the pid with the second clobbering the  
first.  
the open man page details this behaviour. the only solution  
is to  
use an operation which atomically creates a file. the only  
one i  
know of is ‘link’. i don’t think this is worth dealing with  
though  
since /var/run is probably on a fs for which File::EXCL  
works…

cheers.

-a

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 11, 2006, 2:03pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/7 "2006-01-11T14:03:04Z")

</div>

Payton S. wrote on 1/10/2006 9:53 AM:

> Well, I did it myself anyway. Hope it’s useful:  
> [http://rubyforge.org/projects/pidify/](http://rubyforge.org/projects/pidify/)

it certainly is 🙂

i was working on something similar, but decided to use your wheel  
instead of re-inventing my own.

---

<div class="post-metadata">

**Author:** ![Payton\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/74df32/32.png) [@Payton\_S](https://www.ruby-forum.com/u/Payton_S)\
**Post date:** [January 10, 2006, 6:42pm UTC](https://www.ruby-forum.com/t/daemonize-like-fetchmail/56351/8 "2006-01-10T18:42:04Z")

</div>

On Tue, Jan 10, 2006 at 11:53:08PM +0900, Payton S. wrote:

> Well, I did it myself anyway. Hope it’s useful:  
> [http://rubyforge.org/projects/pidify/](http://rubyforge.org/projects/pidify/)

Instead of putting this logic in (every) application, have you  
considered  
using daemontools? [http://cr.yp.to/daemontools.html](http://cr.yp.to/daemontools.html)

Personally, I think pid files are evil.
