51

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.

0

6 Answers 6

53

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

8
  • Does the file need a suffix like: hitservice.service? After this: Failed to start backupservice.service: Unit not found. On CentOS 7 so why is this suggested as answer
    – Pwnstar
    May 4, 2017 at 18:24
  • @Code.IT Note that the OP wanted a SystemV script, not a systemd script, thus no suffix is needed. You should be able to run old scripts with systemd just fine though. Have you tried systemctl enable hitservice? May 5, 2017 at 7:35
  • @DmitryGrigoryev: This script doesn't prevent multiple instances nor stop all multiple instances created, the pidfile stores only the last pid's spawned process.
    – Luciano
    Mar 14, 2018 at 17:36
  • What would be the proper way to pipe the stdout/stderr to /var/log? just hit.sh > /var/log/hit.log 2>&1 &?
    – E.S.
    Jun 5, 2020 at 0:22
  • 1
    @E.S. The proper way would be to use systemd's new-style daemons, which have STDOUT/STDERR connected to systemd-journald by default. For legacy SysV daemons redirection to a file could be good enough. Aug 11, 2021 at 13:14
39

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 --since=@$(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.

9
  • thanks for replying I tried you solution but the service is not starting can you look at my question I added the details
    – codegasmer
    Oct 15, 2015 at 6:34
  • I think it will work if your script doesn't fail, but returns error code 0.
    – Alexander
    Oct 8, 2016 at 12:48
  • 4
    Now I like systemd! Oct 19, 2016 at 13:35
  • 1
    The script can be placed anywhere, as long as the systemd service can access and execute it.
    – Alexander
    Oct 1, 2017 at 17:13
  • 4
    I wouldn't recommend Type=forking. Chances are the asker would need Type=simple but in general forking is not recommended: 0pointer.de/public/systemd-man/…. People have been taking their old init scripts and wrapping them in systemd so that the startup of their service goes systemd(init-script(service)). However systemd is a replacement for init scripts, so you should be calling the service directly with systemd so that it looks like systemd(service).
    – Centimane
    Jan 5, 2018 at 13:42
4

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
3

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

2

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
0

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .