Long, long ago when I was a student, I knew how to recognise a UNIX system. Sorry: overused in-joke. I’ve been brushing up on Linux (Ubuntu 14.04 on Azure) while doing some ops stuff involving a machine which, on startup, automatically runs a background process as a specific user. A few minutes of research revealed several ways to do this. Probably the technically rigorous option is a Linux service; I found a much easier option that works well for my purposes.
Our dev team has been building a service process (I’ll call it antelope) that must run in the background as user youjane. The user is important because the process may push changes to a cloud-hosted Git repo, and we want to distinguish automated commits from those made by a human. Also, antelope adheres to the 12 Factor App manifesto which, among other things, recommends configuration by environment variable; in our case there are two: FN, LN.
The manual way
This is easy enough to do by hand:
graham$ login youjane graham$ password: youjane$ export FN=wilde youjane$ export LN=beest youjane$ /opt/antelope/bin/antelope &
The trailing ampersand (&) tells Linux to run the process in the background. This works fine.
An automatic way
I don’t want to do this by hand every time one of our antelope machines starts up. To make the OS do it, I wrote a small script and edited system file /etc/rc.local to call the script. I’ve described my steps below.
Change to user root in order to modify system files:
$ sudo -i
The script file
Create a script file in a directory suitable for admin scripts:
# vi /usr/local/bin/run_antelope.sh
The sudo command lets you define environment variables in its argument list. I’ve included the full script below:
#!/bin/sh # sudo arguments: # "-b" run in the background # "-E" preserve the user's environment # "-u youjane" run as user "youjane" # Set environment variables: # FN=<value> # LN=<value> sudo -b -E -u youjane FN=wilde \ LN=beest \ /opt/antelope/bin/antelope
Save the file and close the editor. Adhering to the principle of least privilege, make it executable only for its owner (root):
# chmod u+x /usr/local/bin/run_antelope.sh
/etc/rc.local
To run shell script on start-up, edit the system file /etc/rc.local:
# vi /etc/rc.local
Add the line below (before the line with exit 0) to run the script:
/usr/local/bin/run_antelope.sh || exit 1 exit 0
If the script fails, || exit 1 is there to signal the failure to the init system.
Save the file and close the editor.
Now antelope will start automatically when Linux starts up.
Does it work?
So I could do some testing with antelope or check the log file. But wouldn’t it be cool just to look at the important bits of its process environment? It’s easy to do that with the /proc/<pid>/environ file.
To avoid corrupting my quick smoke test, I logged in as root (instead of youjane). In the interactive shell sequence below:
- Command xargs formats the contents of /proc/<pid>/environ to make it readable.
- Command $(pidof antelope) gets the ID of the running process.
- The output shows that antelope is running as youjane, and environment variables FN, LN are available and defined as expected.
# xargs --null --max-args=1 < /proc/$(pidof antelope)/environ UPSTART_INSTANCE= runlevel=2 UPSTART_JOB=rc TERM=linux PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin RUNLEVEL=2 PREVLEVEL=N UPSTART_EVENTS=runlevel PWD=/ previous=N LOGNAME=youjane USER=youjane USERNAME=youjane SUDO_COMMAND=/opt/antelope/bin/antelope SUDO_USER=root SUDO_UID=0 SUDO_GID=0 FN=wilde LN=beest
As always, comments are welcome.
References
- Environment variables of a running process on Unix?
- T H E /proc F I L E S Y S T E M
- Purpose and typical usage of /etc/rc.local
- Sudo Manual