Kicking off User Daemons at Startup on Linux

There are many times I find myself using a GNU/Linux machine to run a process 24/7. Often times, I don't want or can't get root on the machine where I'm running this process, however. In this article, I'll give you some tips and tricks for running daemons at startup under GNU/Linux without any sort of special user privileges.

The Standard Daemon Method

If you just want to run a Linux command or daemon at startup, there are typically a couple of ways to accomplish this.

One is to go the full-blown SysV init route, which typically involves having scripts and symbolic links in /etc/rc.d/ and its subdirectories. Most daemons on mainstream GNU/Linux distributions start using this methodology. If you've ever used the service command or messed around with runlevels and so forth, you've probably experienced this method before.

The other option is using /etc/rc.local, which is a special shell script that tends to be run last during the startup process. Sometimes, things you want to do just once at boot can be placed here.

However, both of these methods assume that you have root access. Additionally, most of the time you're going to have to take steps to ensure that you drop root privileges before running the daemon. Sometimes, you can't get (or don't want) root.

Most of these methods also assume that you never need to interact directly with the process once it is running. Usually daemons ignore stdin and redirect stdout to some log file, but sometimes you might want to be able to monitor or send commands directly to a running daemon process. It would be nice to be able to have a daemon running in the foreground, but attach and detach from it at will.

In the rest of this article, I'll cover how I approached these problems and solved them with a bit of command-line-fu.

Running Stuff at Startup Using... Cron?

Any true *nix hacker knows of cron, and you can separate the noobs from the pros by how well they know crontab syntax by heart. (For the record, I have to look it up. I'll leave my geek card by the door...)

For the uninitiated, cron is a daemon that runs programs at set times or on set intervals. It's really useful for cleanup or backup tasks that need to be run periodically. Each user has a crontab file that lists the tasks they would like run, and on what interval. The interval is listed first, in a special format. The command comes second. If this all seems confusing or tricky, or you just feel like you need more help with crontabs, the man page is pretty good.

One trick that I was unaware of is some "special" intervals. These are extensions, so there's a chance that (although they are common) not every GNU/Linux box will support them. Most of these are just shorthand for common timing intervals, like @hourly or @midnight. However, there's one unique interval that will help us solve our current problem, @reboot.

@reboot is the key to running something as a user every time the machine starts up. Just log in as the desired user, edit your crontab with crontab -e and add a line like:

[bash] @reboot $HOME/bin/startup.sh` [/bash]

Save the crontab, and with any luck you're good to go.

Note When writing the script that cron will be executing (ie, ~/bin/startup.sh in this example), make sure you start them with a shebang line, like # !/bin/bash - cron doesn't run with the same environment as your typical user.

Some Useful Extensions to This Idea

Great, so now we can run a script at startup that runs whatever user daemon we want without root access, using a tool that is commonly installed on GNU/Linux boxes by default. But, we can do more if we spend a bit more time on this.

Sometimes, you're going to want to run a daemon in the foreground, so that you can send commands to it and view its output directly on the terminal. A game server is a good example for this one. For these kind of daemons, screen is our best friend.

screen is an application that allows you to turn your SSH session into a persistent terminal. You can run commands and then detach from the screen before you log off, and then log in later and resume the screen session you were running before. If you've never used it before, it's super powerful and useful, and you really should have it in your toolkit. I'll leave the man page right here.

You can launch a screen session interactively, but with some screenrc love, you can also launch one directly into the background and have it run commands you specify.

Note If screen isn't installed on your machine, you will probably need to be root to install it, with a command like sudo apt-get install screen. If you can't get root or convince your administrator to help, you could try to build a local version installed in your home directory or grab a precompiled binary, but that's outside the scope of this guide.

Once the screen session is running, you can attach to it by SSH'ing in and using the screen -RD command. When you're done and want to send it back into the background, just type Ctrl-a d (Hold Ctrl, press a, press d, release Ctrl) to detach.

Putting it Together: A Practical Example

Let's assemble the pieces here and build a set of scripts that launches a foreground daemon in a screen session, under a user account, without needing to be root.

First, a screenrc file that launches our daemon (in this case, the ~/scripts/run-daemon.sh script is the thing we want to launch foreground in the screen session)

[bash title="~/scripts/run-daemon.screenrc"] autodetach on screen -t some_title -L $HOME/scripts/run-daemon.sh detach [/bash]

Note screen can run multiple things in a single session. Just add more "screen" lines to your screenrc. When you attach to the session, you can use Ctrl-a n and Ctrl-a p to switch between the terminals.


Next, let's look at the script that kicks off the screen session using our screenrc from above:

[bash title="~/scripts/startup.sh"]

!/bin/bash

Get to the directory where this shell script lives

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd $DIR

screen -c run-daemon.screenrc [/bash]


Lastly, the crontab line that kicks this whole thing off:

[bash title="crontab"] @reboot $HOME/scripts/startup.sh [/bash]

That's all there is to it, just a few lines of script and you're good to go.