How do I create a service for a shell script so I can start and stop it like a daemon?

I’m using CentOS 7 what my aim is to create a cron for every five seconds but as I researched we can use cron only for a minute so what I am doing now is I have created a shell file.
hit.sh

while sleep 5; do curl http://localhost/test.php; done

but I have hit it manually through right clicking it.

What I want is to create a service for that file so that i can start and stop it automatically.

I found the script to create a service

#!/bin/bash
# chkconfig: 2345 20 80
# description: Description comes here....

# Source function library.
. /etc/init.d/functions

start() {
    # code to start app comes here 
    # example: daemon program_name &
}

stop() {
    # code to stop app comes here 
    # example: killproc program_name
}

case "$1" in 
    start)
       start
       ;;
    stop)
       stop
       ;;
    restart)
       stop
       start
       ;;
    status)
       # code to check status of app comes here 
       # example: status program_name
       ;;
    *)
       echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0

But I don’t know what to write in start or stop methods I tried placing the same content of hit.sh in start(){} but it gave error for } in stop method.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Users trying to run a script as a daemon on a modern system should be using systemd:

[Unit]
Description=hit service
After=network-online.target

[Service]
ExecStart=/path/to/hit.sh

[Install]
WantedBy=multi-user.target

Save this as /etc/systemd/system/hit.service, and then you will be able to start/stop/enable/disable it with systemctl start hit, etc.

Old answer from 2015:

If you’d like to reuse your code sample, it could look something like:

#!/bin/bash

case "$1" in 
start)
   /path/to/hit.sh &
   echo $!>/var/run/hit.pid
   ;;
stop)
   kill `cat /var/run/hit.pid`
   rm /var/run/hit.pid
   ;;
restart)
   $0 stop
   $0 start
   ;;
status)
   if [ -e /var/run/hit.pid ]; then
      echo hit.sh is running, pid=`cat /var/run/hit.pid`
   else
      echo hit.sh is NOT running
      exit 1
   fi
   ;;
*)
   echo "Usage: $0 {start|stop|status|restart}"
esac

exit 0

Naturally, the script you want to be executed as a service should go to e.g. /usr/local/bin/hit.sh, and the above code should go to /etc/init.d/hitservice.

For each runlevel which needs this service running, you will need to create a respective symlink. For example, a symlink named /etc/init.d/rc5.d/S99hitservice will start the service for runlevel 5. Of course, you can still start and stop it manually via service hitservice start/service hitservice stop

Method 2

I believe CentOS 7 and above uses systemd. If that is the case for your system, try the following:

  1. Place the script commands you wish to run in /usr/bin/myscript.
  2. Remember to make the script executable with chmod +x.
  3. Create the following file:

/etc/systemd/system/my.service

[Unit]
Description=My Script

[Service]
Type=forking
ExecStart=/usr/bin/myscript

[Install]
WantedBy=multi-user.target
  1. Reload all systemd service files: systemctl daemon-reload
  2. Check that it is working by starting the service with systemctl start my.

Bonus:

For testing the systemd service, it is possible to launch a tmux environment with two window panes, where the top window monitors the output from the script (stdout and stderr) and the bottom window can be used for restarting services. This requires tmux to be installed, then simply:

tmux new-session ; select-layout even-horizontal ; split-window -v journalctl -o cat <a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5974742a30373a3c6419">[email protected]</a>$(date +%s) -f -u my ; rotate-window ; set -g status-bg colour0 ; set -g status-fg colour9 ; attach

Then restart the service with:

systemctl restart my

Exit tmux with ctrl-d and then ctrl-c.

Once you’re happy with the script and service file, change

Type=forking

into

Type=simple

Done.

Method 3

This is my script as a service:

[Unit]
Description=To change In test buffer
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/test.sh
TimeoutStartSec=0

[Install]
WantedBy=default.target

Method 4

Take a look at fpm. It is a tool that will create init scripts for you. Works on many platforms (systemd, upstart, ect..)

https://github.com/jordansissel/fpm

Method 5

The below code block can be very helpful to convert the linux scripts into service

  1. Login into the server with root access
  2. Create the following systemd unit file for the required service & change permissions per below
touch /lib/systemd/system/test.service
chmod 664 /lib/systemd/system/test.service
  1. Add the following content into the systemd unit file to define the service
[Unit]
Description=Test Service
After=network.target
 
[Service]
Type=forking
User=#username
PIDFile=#test.pid_path
ExecStart=#startup_script_path
ExecStop=#shutdown_script_path
 
[Install]
WantedBy=multi-user.target
  1. Enable it as a service
systemctl daemon-reload
systemctl enable test.service
  1. Use below commands to start, stop, status & restart
systemctl start test.service
systemctl stop test.service
systemctl status test.service
systemctl restart test.service

Method 6

See Bash Service Manager project: https://github.com/reduardo7/bash-service-manager

Implementation example

#!/usr/bin/env bash

export PID_FILE_PATH="/tmp/my-service.pid"
export LOG_FILE_PATH="/tmp/my-service.log"
export LOG_ERROR_FILE_PATH="/tmp/my-service.error.log"

. ./services.sh

run-script() {
  local action="$1" # Action

  while true; do
    echo "@@@ Running action '${action}'"
    echo foo
    echo bar >&2

    [ "$action" = "run" ] && return 0
    sleep 5
    [ "$action" = "debug" ] && exit 25
  done
}

before-start() {
  local action="$1" # Action

  echo "* Starting with $action"
}

after-finish() {
  local action="$1" # Action
  local serviceExitCode=$2 # Service exit code

  echo "* Finish with $action. Exit code: $serviceExitCode"
}

action="$1"
serviceName="Example Service"

serviceMenu "$action" "$serviceName" run-script "$workDir" before-start after-finish

Usage example

$ ./example-service
# Actions: [start|stop|restart|status|run|debug|tail(-[log|error])]

$ ./example-service start
# Starting Example Service service...

$ ./example-service status
# Serive Example Service is runnig with PID 5599

$ ./example-service stop
# Stopping Example Service...

$ ./example-service status
# Service Example Service is not running


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x