Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Sample /etc/init.d script

Sample service script for debianoids

Look at LSB init scripts for more information.

Usage

Copy to /etc/init.d:

# replace "$YOUR_SERVICE_NAME" with your service's name (whenever it's not enough obvious)
cp "service.sh" "/etc/init.d/$YOUR_SERVICE_NAME"
chmod +x /etc/init.d/$YOUR_SERVICE_NAME

Edit the script and replace following tokens:

  • <NAME> = $YOUR_SERVICE_NAME
  • <DESCRIPTION> = Describe your service here (be concise)
  • Feel free to modify the LSB header, I've made default choices you may not agree with
  • <COMMAND> = Command to start your server (for example /home/myuser/.dropbox-dist/dropboxd)
  • <USER> = Login of the system user the script should be run as (for example myuser)

Start and test your service:

service $YOUR_SERVICE_NAME start
service $YOUR_SERVICE_NAME stop

Install service to be run at boot-time:

update-rc.d $YOUR_SERVICE_NAME defaults

Enjoy

Uninstall

The service can uninstall itself with service $NAME uninstall. Yes, that's very easy, therefore a bit dangerous. But as it's an auto-generated script, you can bring it back very easily. I use it for tests and often install/uninstall, that's why I've put that here.

Don't want it? Remove lines 56-58 of the service's script.

Logs?

Your service will log its output to /var/log/$NAME.log. Don't forget to setup a logrotate :)

I'm noob and/or lazy

Yep, I'm lazy too. But still, I've written a script to automate this :)

wget 'https://raw.github.com/gist/4275302/new-service.sh' && bash new-service.sh

In this script I will download service.sh into a tempfile, replace some tokens, and then show you commands you should run as superuser.

If you feel confident enough with my script, you can sudo the script directly:

wget 'https://raw.github.com/gist/4275302/new-service.sh' && sudo bash new-service.sh

Note: the cool hipsterish curl $URL | bash won't work here, I don't really want to check why.

Demo

Creating the service:

service-create

Looking at service files (logs, pid):

service-files

Uninstalling service:

service-uninstall

#!/bin/bash
SERVICE_FILE=$(tempfile)
echo "--- Download template ---"
wget -q -O "$SERVICE_FILE" 'https://raw.github.com/gist/4275302/service.sh'
chmod +x "$SERVICE_FILE"
echo ""
echo "--- Customize ---"
echo "I'll now ask you some information to customize script"
echo "Press Ctrl+C anytime to abort."
echo "Empty values are not accepted."
echo ""
prompt_token() {
local VAL=""
while [ "$VAL" = "" ]; do
echo -n "${2:-$1} : "
read VAL
if [ "$VAL" = "" ]; then
echo "Please provide a value"
fi
done
VAL=$(printf '%q' "$VAL")
eval $1=$VAL
sed -i "s/<$1>/$(printf '%q' "$VAL")/g" $SERVICE_FILE
}
prompt_token 'NAME' 'Service name'
if [ -f "/etc/init.d/$NAME" ]; then
echo "Error: service '$NAME' already exists"
exit 1
fi
prompt_token 'DESCRIPTION' ' Description'
prompt_token 'COMMAND' ' Command'
prompt_token 'USERNAME' ' User'
if ! id -u "$USERNAME" &> /dev/null; then
echo "Error: user '$USERNAME' not found"
exit 1
fi
echo ""
echo "--- Installation ---"
if [ ! -w /etc/init.d ]; then
echo "You don't gave me enough permissions to install service myself."
echo "That's smart, always be really cautious with third-party shell scripts!"
echo "You should now type those commands as superuser to install and run your service:"
echo ""
echo " mv \"$SERVICE_FILE\" \"/etc/init.d/$NAME\""
echo " touch \"/var/log/$NAME.log\" && chown \"$USERNAME\" \"/var/log/$NAME.log\""
echo " update-rc.d \"$NAME\" defaults"
echo " service \"$NAME\" start"
else
echo "1. mv \"$SERVICE_FILE\" \"/etc/init.d/$NAME\""
mv -v "$SERVICE_FILE" "/etc/init.d/$NAME"
echo "2. touch \"/var/log/$NAME.log\" && chown \"$USERNAME\" \"/var/log/$NAME.log\""
touch "/var/log/$NAME.log" && chown "$USERNAME" "/var/log/$NAME.log"
echo "3. update-rc.d \"$NAME\" defaults"
update-rc.d "$NAME" defaults
echo "4. service \"$NAME\" start"
service "$NAME" start
fi
echo ""
echo "---Uninstall instructions ---"
echo "The service can uninstall itself:"
echo " service \"$NAME\" uninstall"
echo "It will simply run update-rc.d -f \"$NAME\" remove && rm -f \"/etc/init.d/$NAME\""
echo ""
echo "--- Terminated ---"
#!/bin/sh
### BEGIN INIT INFO
# Provides: <NAME>
# Required-Start: $local_fs $network $named $time $syslog
# Required-Stop: $local_fs $network $named $time $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: <DESCRIPTION>
### END INIT INFO
SCRIPT=<COMMAND>
RUNAS=<USERNAME>
PIDFILE=/var/run/<NAME>.pid
LOGFILE=/var/log/<NAME>.log
start() {
if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then
echo 'Service already running' >&2
return 1
fi
echo 'Starting service…' >&2
local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
su -c "$CMD" $RUNAS > "$PIDFILE"
echo 'Service started' >&2
}
stop() {
if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
echo 'Service not running' >&2
return 1
fi
echo 'Stopping service…' >&2
kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE"
echo 'Service stopped' >&2
}
uninstall() {
echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
local SURE
read SURE
if [ "$SURE" = "yes" ]; then
stop
rm -f "$PIDFILE"
echo "Notice: log file is not be removed: '$LOGFILE'" >&2
update-rc.d -f <NAME> remove
rm -fv "$0"
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
uninstall)
uninstall
;;
retart)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart|uninstall}"
esac

re5et commented Dec 18, 2013

retart

Type in service.sh:61: "retart" instead of "restart"

the script was not working because of a 404 on the service.sh so i forked it and made a proper repo out of it here:

https://github.com/jasonblewis/sample-service-script

mehikmat commented May 6, 2014

I think at line 45 there is little bit grammatical mistake.

log file is not be removed
but think either log file is not removed or log file should not be removed is correct.

A better way to do this is to use the MataInit package in debian: https://wiki.debian.org/MetaInit

t2d commented Nov 10, 2014

the links for wget are broken

vi commented Jan 17, 2015

Why service.sh is always downloaded instead of a here document inside of new-service.sh?

vi commented Jan 17, 2015

Maybe better to use sed s!<pattern>!user_input!g instead of s/.../.../g. The command can contain /.

vi commented Jan 17, 2015

The script also forgets to set the appropriate mode (chmod 755 /etc/init.d/..) for the service.

vanjor commented Feb 28, 2015

LOL.. spelling: retart=>restart

integrii commented Mar 3, 2015

This is great, but the links no longer work for github. Pull my fork! I fixed them!

License ?

s/if [ -f /var/run/$PIDNAME ] && kill -0 $(cat /var/run/$PIDNAME); then/if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE"); then/

fengye commented Dec 16, 2015

service.sh line 18 should be:

if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE"); then

Otherwise if I start my service multiple times, the script won't complain. And afterward if I stop the service, the system will complain about not finding the pid.

Since there's no pull request of gist, please download the updated shell script here:
https://gist.githubusercontent.com/fengye/3265b4463e14a569358e/raw/e6b414e10685d283167031538b06cc996f2e5e02/service.sh

Can we run the same service multiple times from different directory. Ex: myservice & myservice1 have to run same application from different directory... it is possible?
I have tried the same but either it executive same or get the error...
Please let me know the code for this...
Thanks in advance...

ceyes commented Apr 19, 2017

https://gist.github.com/naholyr/4275302#file-service-sh-L18 should be
if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE"); then

timjen3 commented Apr 29, 2017

I had a couple issues with the "start" function above on Ubuntu 16.04 LTS.

  1. For one it references a made up variable like @fengye mentioned above. His fix works for me:
    if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE"); then

  2. For me output of the script was going into the pid file and not the log file which prevented it from shutting down and also was dumb. Had to do this.
    su -c "$CMD" $RUNAS > "$LOGFILE"

  3. The trickiest issue I ran into was with writing the process id to the file. I think it may be because my script uses xonsh and there's a slight delay starting up. I'm not sure, but I found that I had to use the double ampersand here or the pid written to the file would be wrong.
    local CMD="$SCRIPT &> \"$LOGFILE\" && echo \$! > $PIDFILE"

Here's the whole function for convenience:

`start() {
  if [ -f "$PIDFILE" ] && kill -0 $(cat "$PIDFILE"); then
    echo 'Service already running' >&2
    return 1
  fi
  echo 'Starting service…' >&2
  local CMD="$SCRIPT &> \"$LOGFILE\" && echo \$! > $PIDFILE"
  su -c "$CMD" $RUNAS > "$LOGFILE"
  echo 'Service started' >&2
}

Congrats for your code!! To you and all involved on comments!
Was very helpful for my project!

Globik commented Sep 11, 2017

Your $PIDNAME variable is also undefined???

deseven commented Nov 20, 2017

kinda retartet

Owner

naholyr commented Nov 21, 2017

You meant "retarded" I guess. But this kind of comments usually goes with the awful writing too, no surprise ;)

Well it's been 5 years old now, and I think it's totally obsolete since systemd is the new thing (which has been a year or two now). I understand your disappointment if you did not consider this. For your future explorations, please remember to check the publication date of what you're reading, it may help you not being so disappointed that you need to compulsively add such comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment