What is the best way to daemonize a Racket program on linux?

148 views
Skip to first unread message

Brian Adkins

unread,
Nov 28, 2018, 9:56:25 PM11/28/18
to Racket Users
I briefly looked at the daemonize package on Ubuntu linux, but couldn't get it to work properly. I found the following Rosetta Code page:


So, I just tried the code in that example, and it seems to work fine:

(module+ main
         ((get-ffi-obj 'daemon #f (_fun _int _int -> _int)) 0 0)
         (serve/servlet
          dispatcher
          #:log-file "hello.log"
          #:stateless? #t
          #:port 6995
          #:command-line? #t
          #:file-not-found-responder not-found
          #:launch-browser? #f
          #:servlet-regexp #rx""))

I'm just wondering if there is a better way to accomplish this since it feels a bit kludgy to me.

Thanks,
Brian

Alex Harsanyi

unread,
Nov 28, 2018, 10:45:59 PM11/28/18
to Racket Users

If your Linux installation has systemd, you can create a service file for your application -- this way, systemd will manage the application as a server or daemon.  Systemd will even redirect stderr messages to the system log.

Alex.

Tom Gillespie

unread,
Nov 29, 2018, 2:29:15 AM11/29/18
to Racket Users
If you're not into systemd https://gist.github.com/tgbugs/c2990382b3fdfef86a2a3a1bc0516099 is an example of an openrc init script that I use to daemonize a servlet (running behind nginx) which is an echo server that responds with the ip of the requester and that is initialized like this:
(serve/servlet main
                 #:port 4000
                 #:servlet-path server-base-path
                 #:server-root-path "/dev/null"
                 #:servlet-regexp #rx""
                 #:servlet-responder responder  ; prevent stack trace from leaking
                 #:file-not-found-responder 404-responder
                 #:stateless? #t
                 #:banner? #f
                 #:launch-browser? #f
                 #:command-line? #t)

Tony Garnock-Jones

unread,
Nov 29, 2018, 5:54:42 AM11/29/18
to Racket Users
IMO using daemon(3) is not a great idea. Instead, I like to use djb's daemontools https://cr.yp.to/daemontools.html to supervise my processes. For example, see the `README` and the `run` script in https://github.com/tonyg/racket-reloadable-example.

Tony

Brian Adkins

unread,
Nov 29, 2018, 10:17:38 AM11/29/18
to Racket Users
I'm running Ubuntu 18.04 LTS, so I do have systemd. Just to clarify, are you stating that systemd will take a program designed to run as a foreground process and run it in the background automatically? I was planning on using monit to monitor/restart/etc. a set of Racket processes, but maybe systemd will do everything I need such as restarting one if it crashes.

Brian Adkins

unread,
Nov 29, 2018, 10:19:17 AM11/29/18
to Racket Users
Just out of curiosity, why do you feel using daemon(3) is not a great idea? I'm not disagreeing, just curious about your reasons.

Alex Harsanyi

unread,
Nov 29, 2018, 5:09:06 PM11/29/18
to Racket Users


On Thursday, November 29, 2018 at 11:17:38 PM UTC+8, Brian Adkins wrote:
I'm running Ubuntu 18.04 LTS, so I do have systemd. Just to clarify, are you stating that systemd will take a program designed to run as a foreground process and run it in the background automatically?

Yes.

Philip McGrath

unread,
Nov 29, 2018, 5:17:38 PM11/29/18
to Alex Harsanyi, racket...@googlegroups.com
To give you an example, here's a very basic systemd file that I use to run a Racket web server:

/etc/systemd/system/ricoeur-portal.service
[Unit]
Description=Digital Ricoeur portal web server

[Service]
User=ricoeurd
Group=ricoeurd
AmbientCapabilities=CAP_NET_BIND_SERVICE
WorkingDirectory=/home/ubuntu/ricoeur-portal/
ExecStart=/usr/local/bin/ricoeur-portal --production

[Install]
WantedBy=multi-user.target

It's particularly nice from a security perspective that `CAP_NET_BIND_SERVICE` makes it easy to run as a user with minimal privileges and still be able to bind to ports 80 and 443.

-Philip


--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brian Adkins

unread,
Nov 29, 2018, 5:22:49 PM11/29/18
to Racket Users
Thanks. I think that's the approach I'll take. I don't think I'll need to use monit at all then. I will need to start N Racket processes though. I found this article that may work for me:


I don't think I'll try the SO_REUSEPORT idea at this point, so I'll need each of the N Racket servers to listen on a different port and have nginx reverse proxy to them.

I think by having systemd manage the N processes separately, I can get auto-restart etc. for free w/o having to code up a master Racket process supervising N worker processes.

Philip McGrath

unread,
Nov 29, 2018, 5:38:24 PM11/29/18
to Brian Adkins, racket...@googlegroups.com
That is probably what I would do, including using a systemd "instantiated service" to start N instances.

I think it would be great for the Racket web server to come with a parallelism story built in (rather than just concurrency), because I generally think internalizing extra-linguistic context is a good thing, but I think it makes complete sense to just get something running for now with systemd. That recent discussion does make it seem like adding parallelism to the Racket web server might be less daunting to implement than I previously thought, though.

-Philip

Brian Adkins

unread,
Nov 29, 2018, 10:05:41 PM11/29/18
to Racket Users
I really appreciate all the help I've received on this thread! The Racket community has been fantastic.

I have my proof-of-concept working for the web infrastructure - no need for a Unicorn/Puma-like app, no need for monit, no need to daemonize - just systemd to manage N Racket processes, and nginx in front to reverse proxy to the Racket workers.

I ended up with this systemd service file:

--- snip ---
[Unit]
Description=Racket hello world %i

[Service]
WorkingDirectory=/home/deploy/appname/current/
ExecStart=/usr/local/bin/racket /home/deploy/appname/current/hello.rkt %i
Restart=always

[Install]
WantedBy=multi-user.target
--- snip ---

Enable 2 workers:  sudo systemctl enable hello@{1..2}
Start them: sudo systemctl start hello\@{1..2}
Check status:  sudo systemctl status hello\@{1..2}

They auto start at boot time, and they auto restart if killed or they crash.

I hacked up a quick test using a command line argument to specify the port and log file (I know there are more elegant solutions, but I was in a hurry to verify it).  It's possible that using a single log file for all the workers will "just work", but I wasn't sure, so I use one log file per process for now. I suppose there are pros/cons to each approach.

(module+ main
    (define instance-id (string->number (vector-ref (current-command-line-arguments) 0)))
    (define port (+ 8000 instance-id))
    (serve/servlet
          dispatcher
          #:log-file (format "hello~a.log" instance-id)
          #:stateless? #t
          #:port port
          #:command-line? #t
          #:file-not-found-responder not-found
          #:launch-browser? #f
          #:servlet-regexp #rx""))

nginx config includes:

--- snip ---
...
  upstream racket {
    least_conn;
    server localhost:8001;
    server localhost:8002;
  }
...
proxy_pass http://racket;
--- snip ---

Now I can get on to the fun part of porting my Ruby/Rails app, and then extending it.


On Thursday, November 29, 2018 at 5:17:38 PM UTC-5, Philip McGrath wrote:

hashim muqtadir

unread,
Nov 30, 2018, 6:16:08 AM11/30/18
to Racket Users
I've found monit to work alongside systemd services pretty neatly. As in, I have monit monitoring my web server, which is running using systemd, and monit sends me emails if it's not working or something.

George Neuner

unread,
Dec 1, 2018, 6:12:52 PM12/1/18
to racket...@googlegroups.com
daemon(3) is not guaranteed to keep background processes running after
the the user logs off.

If you need the process to keep running - or to start automatically at
boot - you really need to use a systemd [preferably] or init script.
Unfortunately either of these options require root access - which can
be a problem with some cloud VMs.

George

Tony Garnock-Jones

unread,
Dec 2, 2018, 8:20:57 AM12/2/18
to racket...@googlegroups.com
I tried to reply to Brian's question earlier but google-groups seems to have eaten it *eyeroll*. Here's what I wrote:

[In reply to being asked why I think using daemon(3) isn't great]
Mostly that it's a function of the context, not the program, whether it is to be treated as a daemon or not. But there's also a bunch of stuff to do with whether the process is/should be a session leader or not, which is again something the program itself shouldn't be making decisions about. djb writes a bit about this topic here: https://cr.yp.to/daemontools/faq/create.html#fghack . The systemd people even seem to agree (calling a non-backgrounding daemon a "new-style daemon"), at least as far as non-backgrounding goes: http://0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons

Cheers,
  Tony


--
You received this message because you are subscribed to a topic in the Google Groups "Racket Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/racket-users/_4QYrxcWrQw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to racket-users...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--

Tony Garnock-Jones

unread,
Dec 2, 2018, 1:47:56 PM12/2/18
to lojic...@gmail.com, racket...@googlegroups.com
Mostly that it's a function of the context, not the program, whether it is to be treated as a daemon or not. But there's also a bunch of stuff to do with whether the process is/should be a session leader or not, which is again something the program itself shouldn't be making decisions about. djb writes a bit about this topic here: https://cr.yp.to/daemontools/faq/create.html#fghack . The systemd people even seem to agree (calling a non-backgrounding daemon a "new-style daemon"), at least as far as non-backgrounding goes: http://0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons


--
You received this message because you are subscribed to a topic in the Google Groups "Racket Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/racket-users/_4QYrxcWrQw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to racket-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages