Don't use forever.
It's dead easy. As you've already observed, forever is unnecessary here as runit already is a service manager, and is already starting and restarting your program.
As you've also already observed, there are a few rules for what run programs must do. They must not fork and exit the main program. The runit service manager, like most daemontools-family service managers (there being a whole family of softwares that all work like this), expects that the process running the run program is the dæmon. Not its parent. Not a brief fly-by-night that forks and exits. But the actual dæmon itself.
a simple run program
There are various scripting languages that make writing such run programs a doddle. Laurent Bercot's execline is one. My nosh program is another. Presuming that bin/www is the actual executable program for your dæmon, a nosh run script would look something like:
#!/bin/nosh
fdmove -c 2 1
chdir /src
bin/www
An execline script is similarly brief. But the shell script isn't that much longer. If your run program is a shell script, the thing to remember is to overlay the shell program with your dæmon program in the same process. The shell command for doing this is exec and a shell script thus looks something like:
#!/bin/sh -e
exec 2>&1
cd /src
exec bin/www
I strongly recommend that, if your program does not require superuser privileges, you execute it via the chpst program (and its -u option), so that it starts as a non-privileged user — for best results, one that is dedicated to this service.
Several people have collected and published suites of run programs, over the years, and most of the run programs are that short and simple. Since you have runit, you can start with Gerrit Pape's own collection of run programs.
starting and stopping dæmons
When it comes to starting and stopping the service, again most daemontools-family service managers need to be told to stop auto-restarting the service. They all come with a tool to do this. You just need to use it in your clean-shutdown script.
- runit has the
sv program: sv down /etc/service/MyApp
- s6 has the
s6-svc program: s6-svc -d /etc/service/MyApp
- perp has the
perpctl program: perpctl d /etc/service/MyApp
- daemontools has the
svc program: svc -d /etc/service/MyApp
- daemontools-encore has the
svc program: svc -d /etc/service/MyApp
- nosh has the
service-control program: service-control --down /etc/service/MyApp which is also aliased as svc: svc -d /etc/service/MyApp
I said that it was a family of toolsets. In fact, under the covers all of these tools are speaking mostly the same protocol.
This brings me to a larger point. All of these toolsets are not exclusive. Just because you have runit, that doesn't stop you from using execline if you want to. Or you can run a nosh script under s6's service manager.
logging
You've tried to write log files with forever. Again, don't use forever. This isn't the right way to go about logging with runit. Redirecting standard output and error directly to files makes your logs impossible to rotate, size-cap, and otherwise control without drastic interference in your dæmon's operation.
daemontools-family service managers all do logging by having the output of one main service connected, through an ordinary pipe, to the input of another log service. This pipe is set up by the service manager. You don't do it yourself.
The log service is another service. It runs one of the many available tools that simply read from their standard input and write to a strictly size-capped, automatically cycled, on-demand rotateable, set of log files in a log directory.
These programs are multilog,multilog, s6-log, tinylog, cyclog, and svlogd which latter is the one that you'll find that comes in the toolkit with runit.
In fact, you might find that whoever set up /etc/service/MyApp has already set up a log service in /etc/service/MyApp/log . If not, a log service script is dead simple:
#!/bin/sh -e
exec chpst -uMyApp-log svlogd -t ./main
Just create a user account named MyApp-log, mkdir /etc/service/MyApp/log/main, chown MyApp-log /etc/service/MyApp/log/main and you are away. (Note that main can be a symbolic link to somewhere else where you make the directory instead. You don't have to put logs under /etc with runit. I put my log directories under /var/log/sv.)
You do nothing at all to your main service to cycle and size-cap logs. The cycling and size-capping happens independently, in the log service process.
Further reading