I ran Oddmuse 6 for a while now from a little shell script. It set up the environment variables, it checked whether the process was already running, it used `nohup` to run `perl6 service.p6`, it saved the PID in a file, and so on. But it didn’t use `cro run`. And I still don’t know how to do it.
I would like to use `cro run` because I feel that’s what I need to do in the future when I run multiple sites in parallel. So let’s try this:
#!/bin/bash export ODDMUSE_MENU="Home, Changes, About" export ODDMUSE_QUESTION="Name a colour of the rainbow." export ODDMUSE_ANSWER="red, orange, yellow, green, blue, indigo, violet" export ODDMUSE_SECRET="rainbow-unicorn" export ODDMUSE_HOST="next.oddmuse.org" export ODDMUSE_PORT=20000 cd $HOME/oddmuse6 cro run
This script doesn’t work. All I see is this:
▶ Starting oddmuse6 (oddmuse6) 🔌 Endpoint HTTP will be at http://localhost:20000/ ♻ Restarting oddmuse6 (oddmuse6) ♻ Restarting oddmuse6 (oddmuse6) ♻ Restarting oddmuse6 (oddmuse6) ♻ Restarting oddmuse6 (oddmuse6) ♻ Restarting oddmuse6 (oddmuse6)
If I replace `cro run` with `perl6 service.p6`, it works.
So now I’m back to this:
#!/bin/bash export ODDMUSE_MENU="Home, Changes, About" export ODDMUSE_QUESTION="Name a colour of the rainbow." export ODDMUSE_ANSWER="red, orange, yellow, green, blue, indigo, violet" export ODDMUSE_SECRET="rainbow-unicorn" export ODDMUSE_HOST="next.oddmuse.org" export ODDMUSE_PORT=20000 cd $HOME/oddmuse6 test -f pid && kill $(cat pid) perl6 service.p6 & echo $! > pid
Any ideas?
The `service.p6` file is simple:
use Cro::HTTP::Log::File; use Cro::HTTP::Server; use Oddmuse::Routes; my $logs = open 'access.log'.IO, :w; my $errors = open 'error.log'.IO, :w; my Cro::Service $http = Cro::HTTP::Server.new( http => <1.1>, host => %*ENV<ODDMUSE_HOST> || die("Missing ODDMUSE_HOST in environment"), port => %*ENV<ODDMUSE_PORT> || die("Missing ODDMUSE_PORT in environment"), application => routes(), after => [Cro::HTTP::Log::File.new(logs => $logs, errors => $errors)] ); $http.start; $logs.say: "Listening at http://%*ENV<ODDMUSE_HOST>:%*ENV<ODDMUSE_PORT>"; react { whenever signal(SIGINT) { $logs.say: "Shutting down..."; $http.stop; done; } whenever signal(SIGHUP) { $logs.say: "Ignoring SIGHUP..."; } }
`Oddmuse::Routes` is available from the Oddmuse 6 repo.
Hm, what could be the problem? Let’s look at the files:
total 80 drwxr-xr-x 6 alex alex 4096 Oct 21 11:40 . drwxr-xr-x 57 alex alex 4096 Oct 21 11:57 .. -rw-r--r-- 1 alex alex 205 Oct 7 18:42 .cro.yml~ -rw-r--r-- 1 alex alex 479 Oct 7 19:23 .cro.yml -rw-r--r-- 1 alex alex 10 Oct 7 18:42 .dockerignore -rw-r--r-- 1 alex alex 52 Oct 7 18:42 .gitignore -rw-r--r-- 1 alex alex 221 Oct 7 18:42 Dockerfile -rw-r--r-- 1 alex alex 471 Oct 7 18:42 META6.json -rw-r--r-- 1 alex alex 473 Oct 7 18:42 README.md -rw-r--r-- 1 alex alex 43 Oct 21 11:49 access.log drwxr-xr-x 2 alex alex 4096 Oct 17 10:59 css -rw-r--r-- 1 alex alex 0 Oct 21 11:49 error.log drwxr-xr-x 3 alex alex 4096 Oct 7 19:24 lib -rw------- 1 alex alex 445 Oct 21 11:46 nohup.out -rw-r--r-- 1 alex alex 6 Oct 21 11:49 pid -rwxr-xr-x 1 alex alex 149 Oct 15 10:43 run.sh~ -rwxr-xr-x 1 alex alex 318 Oct 15 10:46 run.sh -rw-r--r-- 1 alex alex 683 Oct 21 11:19 service.p6~ -rw-r--r-- 1 alex alex 779 Oct 21 11:49 service.p6 drwxr-xr-x 2 alex alex 4096 Oct 10 20:40 templates drwxr-xr-x 4 alex alex 4096 Oct 11 08:32 wiki
`error.log` and `access.log` are the obvious culprits! Changes in the log file will case `cro` to restart. So what I’m going to do is move the log files intoa `logs` subdirectory and add that to the `ignore` section in `.cro.yml`.
OK, so that works. I still feel strange using `nohup`, though.
Shell script:
#!/bin/bash export ODDMUSE_MENU="Home, Changes, About" export ODDMUSE_QUESTION="Name a colour of the rainbow." export ODDMUSE_ANSWER="red, orange, yellow, green, blue, indigo, violet" export ODDMUSE_SECRET="rainbow-unicorn" export ODDMUSE_HOST="next.oddmuse.org" export ODDMUSE_PORT=20000 cd $HOME/oddmuse6 # test -f pid && kill $(cat pid) # perl6 service.p6 & # echo $! > pid nohup cro run &
Service:
use Cro::HTTP::Log::File; use Cro::HTTP::Server; use Oddmuse::Routes; my $logs = open 'logs/access.log'.IO, :w; my $errors = open 'logs/error.log'.IO, :w; my Cro::Service $http = Cro::HTTP::Server.new( http => <1.1>, host => %*ENV<ODDMUSE_HOST> || die("Missing ODDMUSE_HOST in environment"), port => %*ENV<ODDMUSE_PORT> || die("Missing ODDMUSE_PORT in environment"), application => routes(), after => [Cro::HTTP::Log::File.new(logs => $logs, errors => $errors)] ); $http.start; $logs.say: "Listening at http://%*ENV<ODDMUSE_HOST>:%*ENV<ODDMUSE_PORT>"; react { whenever signal(SIGINT) { $logs.say: "Shutting down..."; $http.stop; done; } whenever signal(SIGHUP) { $logs.say: "Ignoring SIGHUP..."; } }
Me ignoring `SIGHUP` in the service now has no effect because `cro` doesn’t ignore `SIGHUP` which is why the `nohup` wrapper is needed.
OK, so now my shell script starts `nohup cro run &` because `cro` doesn’t daemonize itself. I guess I still find that surprising. And I wonder about the trade-offs. So the benefit is automatic restarts? I also see now that using `cro` run gives me two `moar` processes (one runs `cro`, the other runs my process, `moar` being the virtual machine this Perl 6 runs on).
If there’s nothing else that I’m missing, perhaps running the service using perl6 directly instead of via `cro` isn’t such a bad idea after all. I think I’ll do that.
#Oddmuse 6 #Perl 6 #Cro
(Please contact me if you want to remove your comment.)
⁂
As a user I’m expecting a working systemd file provided. Systemd can solve some of these problems and more.
– AlexDaniel 2018-10-22 12:29 UTC
---
If you have more information for what you’d need, I’d love to hear it. Sadly, the only `systemd` thing I ever did was my backup solution...
– Alex Schroeder 2018-10-22 12:35 UTC
---
Thanks for pointing me at this gist.
NoNewPrivileges=yes ProtectSystem=strict ProtectHome=read-only ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes RestrictRealtime=yes PrivateTmp=yes PrivateDevices=yes PrivateUsers=yes
Other things you mentioned in IRC:
MemoryMax and TasksMax should be used. Restart=always and RestartSec=2 is fine. Watchdog needs to be implemented.
– Alex Schroeder 2018-10-22 12:47 UTC