Skip to content

Instantly share code, notes, and snippets.

@naholyr
Created December 13, 2012 09:39
Show Gist options
  • Save naholyr/4275302 to your computer and use it in GitHub Desktop.
Save naholyr/4275302 to your computer and use it in GitHub Desktop.
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
@fengye
Copy link

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

@kiselev-dv
Copy link

@vladistan
Copy link

@manohargorantla
Copy link

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...

@x13machine
Copy link

@ceyes
Copy link

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
Copy link

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
}

@salodev
Copy link

salodev commented Aug 20, 2017

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

@Globik
Copy link

Globik commented Sep 11, 2017

Your $PIDNAME variable is also undefined???

@deseven
Copy link

deseven commented Nov 20, 2017

kinda retartet

@naholyr
Copy link
Author

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.

@deseven
Copy link

deseven commented Dec 18, 2017

It was a joke and it was based on a couple of things:

  1. Your typo in line 61, which literally says "retart".
  2. There are also incorrect variables usage (PIDFILE vs PIDNAME).
  3. There is no status functionality.
  4. Many people commented on all those issues, but you decided to do nothing.

All in all - this is a really bad example of SysV Init script. I hope i made myself clear and sorry if this offended you.

@nitzanav
Copy link

@deseven you are retarded

@deseven
Copy link

deseven commented Jan 29, 2018

@nitzanav ¯\_(ツ)_/¯

@satish-cevp
Copy link

Failed to stop testservice.service: Unit testservice.service not loaded.

can someone suggest what this error for.
I took service.sh file and copied into /etc/init.d/testservice
i edited the to testservice in service.sh

@fabm22
Copy link

fabm22 commented May 24, 2018

Hey guys, hey guys, did you see there was a typo ?????? retart ok ? hein ? ok ? did you see that ?

@jserpapinto
Copy link

jserpapinto commented May 28, 2018

@deseven do you have a better script template? please share if you do..

@deseven
Copy link

deseven commented Jul 4, 2018

@johnyserpa this one looks fine for me.

@Nindouja
Copy link

For running smth in the background (like runing a nohup java -jar ... commandyou'll have to add the usual & at the end of the actual command run which is su -c "$CMD" $RUNAS > "$PIDFILE". It is useless and certainly not work to add the & at the end of the SCRIPT variable.

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