Created:
16th February, 2008

User init scripts

While porting my Apache development server configuration over to Lighttpd I needed a script that would maintain Django FastCGI daemons even after a reboot of the host server. Even though I could have done this by just starting the daemons in an init script directly there where two problems with this approach:

  1. Running a web-server CGI script as root is massive security risk, and
  2. Users would require root access to restart the daemons if they made a change to the instance.

To get around these problems I wrote the following script that will automatically execute a script in the user’s home directory with their permissions on system boot. This also allows the user to manually restart the daemons at any time without being a security hazard if they require it, as well as not interfering with daemons of other users. The user init script itself should behave just like a normal one, meaning it should respect the “start”, “stop” and “restart” arguments and not require any user input to execute to completion.

By default the the script will search each subdirectory in /home/ non-recursively for a script called .init and then attempt to execute it as the user defined by the subdirectory’s name. I.e. the script /home/bob/.init will be executed as the “bob” user.

User init script launcher <Bash: /etc/init.d/userinit>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/sh

HOMEROOT="/home"
INITFILE=".init"

case "$1" in
start)
    echo -n "Starting user scripts..."

    for USER in `ls $HOMEROOT`; do
        [ -d $HOMEROOT/$USER ] && [ -f $HOMEROOT/$USER/$INITFILE ] && \
            sudo -u $USER $HOMEROOT/$USER/$INITFILE start >> /dev/null &
    done

    echo " Done"
    ;;
stop)
    echo -n "Stopping user scripts..."

    for USER in `ls $HOMEROOT`; do
        [ -d $HOMEROOT/$USER ] && [ -f $HOMEROOT/$USER/$INITFILE ] && \
            sudo -u $USER $HOMEROOT/$USER/$INITFILE stop >> /dev/null &
    done

    echo " Done"
    ;;
restart)
    echo -n "Restarting user scripts..."

    for USER in `ls $HOMEROOT`; do
        [ -d $HOMEROOT/$USER ] && [ -f $HOMEROOT/$USER/$INITFILE ] && \
            sudo -u $USER $HOMEROOT/$USER/$INITFILE restart >> /dev/null &
    done

    echo " Done"
    ;;
*)
    echo "Usage: $0 {start|stop|restart}"
    ;;
esac

Comments

24th December, 2008Kill Bill

Very nice! and thanks for sharing this.

However, a subdirectory under /home may not always be a user’s home directory. I personally would put other common data area in /home as well, for example /home/samba for samba sharing among multiple users, /home/webdav for a webdav share, /home/jailed/home/someuser as a chrooted user’s home directory, etc. In these cases, “samba”, “webdav” or “jailed” won’t be a valid system user. It is fair that you check both the existence of the subdrirectory and the .init file, which helps in this case. But it may be even better if you check the user credential (may be even login shell, etc) before the sudo command. I am thinking some test like this:

<Bash>
1
2
3
if [ -n "`grep $USER /etc/password`"]; then
  sudo -u $USER ...
fi

Just my 1-penny-worth opinion. Feel free to ignore.

Have your say

Markup

Because some people like to be stupid HTML is not allowed in comments, instead feel free to use the following:

  • __Bold__
  • ___Italic___
  • [Hyperlink](http://address.com)
  • [[quote source]]…[[/quote]]
  • [[code:language]]…[[/code]]

Unordered and ordered lists have each line prefixed by either a dash, asterisk, hash or a number. Your choice.

All comments are heavily moderated, if you are off-topic your comment will not be published (But I might reply by E-mail).

Be careful! Once posted you cannot edit your comment.