78

I have a script, which runs my PHP script each X times:

#!/bin/bash
while true; do
/usr/bin/php -f ./my-script.php
echo "Waiting..."
sleep 3
done

How can I start it as daemon?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Sergey B.
  • 969
  • 1
  • 7
  • 12

5 Answers5

183

To run it as a full daemon from a shell, you'll need to use setsid and redirect its output. You can redirect the output to a logfile, or to /dev/null to discard it. Assuming your script is called myscript.sh, use the following command:

setsid myscript.sh >/dev/null 2>&1 < /dev/null &

This will completely detach the process from your current shell (stdin, stdout and stderr). If you want to keep the output in a logfile, replace the first /dev/null with your /path/to/logfile.

You have to redirect the output, otherwise it will not run as a true daemon (it will depend on your shell to read and write output).

micromoses
  • 6,747
  • 2
  • 20
  • 29
  • 11
    how do I kill it then? – Rho Phi Aug 18 '15 at 08:18
  • 11
    You'll have to find it's pid and send it a signal. Here's an UNSAFE example for linux systems: `kill $(ps -fade | grep myscript.sh | grep -v grep | awk '{print $2}')`. This will kill all processes which contain "myscript.sh" in their name or parameters so it's not very safe to use, but you can tweak it to suite your needs. – micromoses Aug 19 '15 at 14:10
  • 3
    Thank you, this is helpful! Can you please explain what `2>&1 < /dev/null` is doing? – Daniel Patrick May 09 '16 at 13:15
  • 17
    @DanielPatrick in bash (and most other shells) this is stdin/stderr/stdout redirection. The `> /dev/null` (same as `1>/dev/null`) redirects stdout (which is file descriptor 1) to /dev/null. The `2>&1` means redirect all stderr (file descriptor 2) to file descriptor 1, which is already redirected to /dev/null. The ` – micromoses May 09 '16 at 13:17
  • Very helpful, was familiar with redirection but not with the file descriptors. Thank you! – Daniel Patrick May 09 '16 at 13:28
  • (in BASH) find it with $ pgrep -l – AAAfarmclub Feb 18 '17 at 23:12
  • (in BASH) kill it with $ pkill – AAAfarmclub Feb 18 '17 at 23:13
  • So far this is the only one that works for me! Thank you very much. – Student Aug 15 '19 at 20:47
44

A Daemon is just program that runs as a background process, rather than being under the direct control of an interactive user...

[The below bash code is for Debian systems - Ubuntu, Linux Mint distros and so on]

The simple way:

The simple way would be to edit your /etc/rc.local file and then just have your script run from there (i.e. everytime you boot up the system):

sudo nano /etc/rc.local

Add the following and save:

#For a BASH script
/bin/sh TheNameOfYourScript.sh > /dev/null &

The better way to do this would be to create a Daemon via Upstart:

sudo nano /etc/init/TheNameOfYourDaemon.conf

add the following:

description "My Daemon Job"
author "Your Name"
start on runlevel [2345]    

pre-start script
  echo "[`date`] My Daemon Starting" >> /var/log/TheNameOfYourDaemonJobLog.log
end script

exec /bin/sh TheNameOfYourScript.sh > /dev/null &

Save this.

Confirm that it looks ok:

init-checkconf /etc/init/TheNameOfYourDaemon.conf

Now reboot the machine:

sudo reboot

Now when you boot up your system, you can see the log file stating that your Daemon is running:

cat  /var/log/TheNameOfYourDaemonJobLog.log

• Now you may start/stop/restart/get the status of your Daemon via:

restart: this will stop, then start a service

sudo service TheNameOfYourDaemonrestart restart

start: this will start a service, if it's not running

sudo service TheNameOfYourDaemonstart start

stop: this will stop a service, if it's running

sudo service TheNameOfYourDaemonstop stop

status: this will display the status of a service

sudo service TheNameOfYourDaemonstatus status
CMP
  • 1,170
  • 12
  • 11
  • 5
    You should really indicate the distro this is for, because these commands and paths are not correct on all distros. – SgtPooki Oct 07 '15 at 19:04
  • 1
    Good point sgtPooki. I added a caveat explaining that my example refers to Ubuntu / Mint distributions etc. Thanks for you comment. – CMP May 14 '16 at 13:54
  • Could someone do a systemd add-on to this answer? :) – Mitja Dec 18 '17 at 10:07
  • Note that Upstart is deprecated. Ubuntu moved to systemd. – Pin May 11 '19 at 11:33
15

You can go to /etc/init.d/ - you will see a daemon template called skeleton.

You can duplicate it and then enter your script under the start function.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Refael
  • 1,252
  • 9
  • 10
  • 3
    you may also consider running the script in background by adding '&' at the end or running it with nohup. – LMC Oct 07 '13 at 21:30
  • @LuisMuñoz how can I make it run in the background automatically. for instance when you issue /etc/init.d/mysql start, the daemon starts and runs in the background by default. – David Okwii Apr 01 '16 at 08:31
  • @DavidOkwii put your code in a function and run it in the background. Check my answer added to this question. – LMC Apr 01 '16 at 18:58
2

Another cool trick is to run functions or subshells in background, not always feasible though

name(){
  echo "Do something"
  sleep 1
}

# put a function in the background
name &
#Example taken from here
#https://bash.cyberciti.biz/guide/Putting_functions_in_background

Running a subshell in the background

(echo "started"; sleep 15; echo "stopped") &
LMC
  • 10,453
  • 2
  • 27
  • 52
0

Some commentors already stated that answers to your question will not work for all distributions. Since you did not include CentOS in the question but only in the tags, I'd like to post here the topics one has to understand in order to have a control over his/her proceeding regardless of the distribution:

  1. what is the init daemon (optional)
  2. what is the inittab file (/etc/inittab)
  3. what does the inittab file do in your distro (e.g. does it actually run all scripts in /etc/init.d ?)

For your problem, one could start the script on sysinit by adding this line in /etc/inittab and make it respawn in case it terminates:

# start and respawn after termination
ttyS0::respawn:/bin/sh /path/to/my_script.sh

The script has to be made executable in advance of course:

chmod +x /path/to/my_script.sh

Hope this helps

Niko
  • 642
  • 6
  • 12