├── screenshots ├── service-create.png ├── service-files.png └── service-uninstall.png ├── LICENSE ├── service.sh ├── new-service.sh └── readme.md /screenshots/service-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyhasany/sysvinit-service-generator/HEAD/screenshots/service-create.png -------------------------------------------------------------------------------- /screenshots/service-files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyhasany/sysvinit-service-generator/HEAD/screenshots/service-files.png -------------------------------------------------------------------------------- /screenshots/service-uninstall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyhasany/sysvinit-service-generator/HEAD/screenshots/service-uninstall.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Michał Rowicki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: 4 | # Required-Start: $local_fs $network $named $time $syslog 5 | # Required-Stop: $local_fs $network $named $time $syslog 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # Description: 9 | ### END INIT INFO 10 | 11 | SCRIPT="" 12 | RUNAS= 13 | 14 | PIDFILE=/var/run/.pid 15 | LOGFILE=/var/log/.log 16 | 17 | start() { 18 | if [ -f $PIDFILE ] && [ -s $PIDFILE ] && kill -0 $(cat $PIDFILE); then 19 | echo 'Service already running' >&2 20 | return 1 21 | fi 22 | echo 'Starting service…' >&2 23 | local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!" 24 | su -c "$CMD" $RUNAS > "$PIDFILE" 25 | # Try with this command line instead of above if not workable 26 | # su -s /bin/sh $RUNAS -c "$CMD" > "$PIDFILE" 27 | 28 | sleep 2 29 | PID=$(cat $PIDFILE) 30 | if pgrep -u $RUNAS -f $NAME > /dev/null 31 | then 32 | echo "$NAME is now running, the PID is $PID" 33 | else 34 | echo '' 35 | echo "Error! Could not start $NAME!" 36 | fi 37 | } 38 | 39 | stop() { 40 | if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then 41 | echo 'Service not running' >&2 42 | return 1 43 | fi 44 | echo 'Stopping service…' >&2 45 | kill -15 $(cat "$PIDFILE") && rm -f "$PIDFILE" 46 | echo 'Service stopped' >&2 47 | } 48 | 49 | uninstall() { 50 | echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] " 51 | local SURE 52 | read SURE 53 | if [ "$SURE" = "yes" ]; then 54 | stop 55 | rm -f "$PIDFILE" 56 | echo "Notice: log file was not removed: $LOGFILE" >&2 57 | update-rc.d -f $NAME remove 58 | rm -fv "$0" 59 | else 60 | echo "Abort!" 61 | fi 62 | } 63 | 64 | status() { 65 | printf "%-50s" "Checking ..." 66 | if [ -f $PIDFILE ] && [ -s $PIDFILE ]; then 67 | PID=$(cat $PIDFILE) 68 | if [ -z "$(ps axf | grep ${PID} | grep -v grep)" ]; then 69 | printf "%s\n" "The process appears to be dead but pidfile still exists" 70 | else 71 | echo "Running, the PID is $PID" 72 | fi 73 | else 74 | printf "%s\n" "Service not running" 75 | fi 76 | } 77 | 78 | 79 | case "$1" in 80 | start) 81 | start 82 | ;; 83 | stop) 84 | stop 85 | ;; 86 | status) 87 | status 88 | ;; 89 | uninstall) 90 | uninstall 91 | ;; 92 | restart) 93 | stop 94 | start 95 | ;; 96 | *) 97 | echo "Usage: $0 {start|stop|status|restart|uninstall}" 98 | esac 99 | -------------------------------------------------------------------------------- /new-service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SERVICE_FILE=$(tempfile) 4 | 5 | if [ ! -e service.sh ]; then 6 | echo "--- Download template ---" 7 | echo "I'll now download the service.sh, because is is not downloaded." 8 | echo "..." 9 | wget -q https://raw.githubusercontent.com/wyhasany/sample-service-script/master/service.sh 10 | if [ "$?" != 0 ]; then 11 | echo "I could not download the template!" 12 | echo "You should now download the service.sh file manualy. Run therefore:" 13 | echo "wget https://raw.githubusercontent.com/wyhasany/sample-service-script/master/service.sh" 14 | exit 1 15 | else 16 | echo "I donloaded the tmplate sucessfully" 17 | echo "" 18 | fi 19 | fi 20 | 21 | 22 | echo "--- Copy template ---" 23 | cp service.sh "$SERVICE_FILE" 24 | chmod +x "$SERVICE_FILE" 25 | echo "" 26 | 27 | echo "--- Customize ---" 28 | echo "I'll now ask you some information to customize script" 29 | echo "Press Ctrl+C anytime to abort." 30 | echo "Empty values are not accepted." 31 | echo "" 32 | 33 | prompt_token() { 34 | local VAL="" 35 | if [ "$3" = "" ]; then 36 | while [ "$VAL" = "" ]; do 37 | echo -n "${2:-$1} : " 38 | read VAL 39 | if [ "$VAL" = "" ]; then 40 | echo "Please provide a value" 41 | fi 42 | done 43 | else 44 | VAL=${@:3:($#-2)} 45 | fi 46 | VAL=$(printf '%s' "$VAL") 47 | eval $1=$VAL 48 | local rstr=$(printf '%q' "$VAL") 49 | rstr=$(echo $rstr | sed -e 's/[\/&]/\\&/g') # escape search string for sed http://stackoverflow.com/questions/407523/escape-a-string-for-a-sed-replace-pattern 50 | sed -i "s/<$1>/$rstr/g" $SERVICE_FILE 51 | } 52 | 53 | prompt_token 'NAME' 'Service name' $1 54 | if [ -f "/etc/init.d/$NAME" ]; then 55 | echo "Error: service '$NAME' already exists" 56 | exit 1 57 | fi 58 | 59 | prompt_token 'DESCRIPTION' ' Description' $2 60 | prompt_token 'COMMAND' ' Command' $3 61 | prompt_token 'USERNAME' ' User' $4 62 | if ! id -u "$USERNAME" &> /dev/null; then 63 | echo "Error: user '$USERNAME' not found" 64 | exit 1 65 | fi 66 | 67 | echo "" 68 | 69 | echo "--- Installation ---" 70 | if [ ! -w /etc/init.d ]; then 71 | echo "You didn't give me enough permissions to install service myself." 72 | echo "That's smart, always be really cautious with third-party shell scripts!" 73 | echo "You should now type those commands as superuser to install and run your service:" 74 | echo "" 75 | echo " mv \"$SERVICE_FILE\" \"/etc/init.d/$NAME\"" 76 | echo " touch \"/var/log/$NAME.log\" && chown \"$USERNAME\" \"/var/log/$NAME.log\"" 77 | echo " update-rc.d \"$NAME\" defaults" 78 | echo " service \"$NAME\" start" 79 | else 80 | echo "1. mv \"$SERVICE_FILE\" \"/etc/init.d/$NAME\"" 81 | mv -v "$SERVICE_FILE" "/etc/init.d/$NAME" 82 | echo "2. touch \"/var/log/$NAME.log\" && chown \"$USERNAME\" \"/var/log/$NAME.log\"" 83 | touch "/var/log/$NAME.log" && chown "$USERNAME" "/var/log/$NAME.log" 84 | echo "3. update-rc.d \"$NAME\" defaults" 85 | update-rc.d "$NAME" defaults 86 | echo "4. service \"$NAME\" start" 87 | service "$NAME" start 88 | fi 89 | 90 | echo "" 91 | echo "---Uninstall instructions ---" 92 | echo "The service can uninstall itself:" 93 | echo " service \"$NAME\" uninstall" 94 | echo "It will simply run update-rc.d -f \"$NAME\" remove && rm -f \"/etc/init.d/$NAME\"" 95 | echo "" 96 | echo "--- Terminated ---" 97 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Note: You can acheive the same thing that this project tries to acheive by using the MetaInit package in debian: 2 | (https://wiki.debian.org/MetaInit) 3 | 4 | # Sample service script for debianoids 5 | 6 | This script enables fast daemonization apps as a Linux services with SysVinit init system. 7 | 8 | Look at [LSB init scripts](http://wiki.debian.org/LSBInitScripts) for more information. 9 | 10 | Original script taken from from [naholyr's](https://github.com/naholyr) [gist](https://gist.github.com/naholyr/4275302) 11 | 12 | ## Usage 13 | 14 | Copy to `/etc/init.d`: 15 | 16 | ```sh 17 | # replace "$YOUR_SERVICE_NAME" with your service's name (whenever it's not enough obvious) 18 | cp "service.sh" "/etc/init.d/$YOUR_SERVICE_NAME" 19 | chmod +x /etc/init.d/$YOUR_SERVICE_NAME 20 | ``` 21 | 22 | Edit the script and replace following tokens: 23 | 24 | * `` = `$YOUR_SERVICE_NAME` 25 | * `` = Describe your service here (be concise) 26 | * Feel free to modify the LSB header, I've made default choices you may not agree with 27 | * `` = Command to start your server (for example `/home/myuser/.dropbox-dist/dropboxd`) 28 | * `` = Login of the system user the script should be run as (for example `myuser`) 29 | 30 | Start and test your service: 31 | 32 | ```sh 33 | service $YOUR_SERVICE_NAME start 34 | service $YOUR_SERVICE_NAME stop 35 | ``` 36 | 37 | Install service to be run at boot-time: 38 | 39 | ```sh 40 | update-rc.d $YOUR_SERVICE_NAME defaults 41 | ``` 42 | For rpm based distributions such as CentOS or Red Hat, you can use 43 | 44 | ```sh 45 | chkconfig $YOUR_SERVICE_NAME --add 46 | ``` 47 | If you want to see which runlevel your script will run in 48 | 49 | ```sh 50 | chkconfig $YOUR_SERVICE_NAME --list 51 | ``` 52 | 53 | Enjoy 54 | 55 | ## Uninstall 56 | 57 | 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. 58 | 59 | Don't want it? Remove lines 56-58 of the service's script. 60 | 61 | ## Logs? 62 | 63 | Your service will log its output to `/var/log/$NAME.log`. Don't forget to setup a logrotate :) 64 | 65 | ## I'm noob and/or lazy 66 | 67 | Yep, I'm lazy too. But still, I've written a script to automate this :) 68 | 69 | ```sh 70 | wget 'https://raw.githubusercontent.com/jasonblewis/sample-service-script/master/new-service.sh' && bash new-service.sh 71 | ``` 72 | 73 | In this script I will download `service.sh` into a `tempfile`, replace some tokens, and then show you commands you should run as superuser. 74 | 75 | If you feel confident enough with my script, you can `sudo` the script directly: 76 | 77 | ```sh 78 | wget 'https://raw.githubusercontent.com/jasonblewis/sample-service-script/master/new-service.sh' && sudo bash new-service.sh 79 | ``` 80 | 81 | Note: the cool hipsterish `curl $URL | bash` won't work here, I don't really want to check why. 82 | 83 | The script works offline so you can clone this repository then you can upload this script on your server and run it 84 | directly: 85 | 86 | ```sh 87 | sudo bash new-service.sh 88 | ``` 89 | 90 | The script also handle parameters as showed below: 91 | 92 | ```sh 93 | sudo bash new-service.sh "service_name" "description" "command to execute" "user which should run command" 94 | ``` 95 | 96 | ### Demo 97 | 98 | Creating the service: 99 | 100 | ![service-create](screenshots/service-create.png) 101 | 102 | Looking at service files (logs, pid): 103 | 104 | ![service-files](screenshots/service-files.png) 105 | 106 | Uninstalling service: 107 | 108 | ![service-uninstall](screenshots/service-uninstall.png) 109 | --------------------------------------------------------------------------------