Call to Daemon in a /Etc/Init.D Script Is Blocking, Not Running in Background

Call to daemon in a /etc/init.d script is blocking, not running in background

I finally re-wrote the start function in the bash init script, and I am not using daemon anymore.

start() {
echo -n "Starting $pname : "
#daemon ${exe} # Not working ...
if [ -s ${pidfile} ]; then
RETVAL=1
echo -n "Already running !" && warning
echo
else
nohup ${exe} >/dev/null 2>&1 &
RETVAL=$?
PID=$!
[ $RETVAL -eq 0 ] && touch ${lockfile} && success || failure
echo
echo $PID > ${pidfile}
fi
}

I check that the pid file is not existing already (if so, just write a warning). If not, I use

 nohup ${exe} >/dev/null 2>&1 &

to start the script.

I don't know if it is safe this way (?) but it works.

Start play2 application as a background task with daemon

Ok here is one solution after tips from favoretti:

#! /bin/sh

# description: Starts autocomplete play app using daemon
# 1. Go to $APPLICATION_PATH and prepare for dev by doing: play clean compile stage
# This will create a start script at target/start
# 2. Start the application by running this script
# created by: Jakob

. /etc/rc.d/init.d/functions

PLAY_HOME=/opt/play
PLAY=$PLAY_HOME/play
NAME=autocomplete
DESC="autocomplete application"

# Path to the JVM
JAVA_HOME=/usr/java/latest
export JAVA_HOME
export PATH=$PATH:$JAVA_HOME/bin

APPLICATION_PATH=/opt/playapps/autocomplete

DAEMON_OPTS="-Dconfig.file=/opt/playapps/autocomplete/conf/application-dev.conf"

start()
{
echo -n "Starting $DESC with: $APPLICATION_PATH/target/start $DAEMON_OPTS &"
$APPLICATION_PATH/target/start $DAEMON_OPTS &
}
stop()
{
echo -n $"Stopping $DESC:"
kill `cat $APPLICATION_PATH/RUNNING_PID`
}

case "$1" in
start)
start
;;
stop)
stop
;;
esac

exit $RETVAL

You will need to CTRL+D to get out of the console which isn't exactly what I had in mind. Maybe there is someone out there with a better solution?

Daemonized script fails to start (for Google App Engine)

There is more elegant way to create daemons in CentOS 7.

I see you are mixing classic(SysV) and new(systemd) approach for executing and managing daemons. The classic way, was to create script in /etc/init.d/ as You did, but I see you are using systemctl, which is a part of a systemd. I suggest creating daemon in systemd way.

Remove your script from /etc/init.d and create parserservices.service file in /etc/systemd/system directory, which looks like that:

[Unit]
Description=Parser Services
After=syslog.target

[Service]
ExecStart=/path/to/your/script/start_dev_server_centos.sh

[Install]
WantedBy=multi-user.target

Start it with

systemctl start parserservices

Check it's status with

systemctl status parserservices

If you want it to start at system startup then enable it with

systemctl enable parserservices

Execute systemctl daemon-reload every time you change the .service file.

Read more about daemons in systemd here

Running script constantly in background: daemon, lock file with crontab, or simply loop?

Let's assume you take the continuous loop route. You rejigger your program to be one infinite loop. You sleep for a certain amount of time, then wake up and process your database files, and then go back to sleep.

You now need a mechanism to make sure your program is still up and running. This could be done via something like inetd.

However, your program basically does a single task, and does that task repeatedly through the day. This is what crontab is for. The inetd mechanism is for servers that are waiting for a client, like https or sshd. In these cases, you need a mechanism to recreate the server process as soon as it dies.

One way you can improve your lockfile mechanism is to include the PID with it. For example, in your Perl script you do this:

open my $lock_file_fh, ">", LOCK_FILE_NAME;
say {$lock_file_fh} "$$";
close $lock_file_fh;

Now, if your crontab sees the lock file, it can test to see if that process ID is still running or not:

if [ -f $lock_file ]
then
pid=$(cat $lock_file)
if ! ps -p $pid
then
rm $lock_file
fi
restart_program
else
restart_program
fi

RedHat daemon function usage

To answer the question you guess that you have, is that --pidfile is used to check whether the daemon process is already running. On RHEL (and derivates) the daemon function won't write the pidfile.

In the case that the program stays in the foreground it has to be explicitly sent to the background by appending & to the command and the pid has to be fetched afterwards. $! is not usable when using daemon.

How to get PID of perl daemon in init script?

Thank you to the suggestions from zdim and Hakon. They are certainly workable, and got me on the right track, but ultimately I went a different route. Rather than relying on $!, I used ps and awk to get the PID, as follows:

DAEMON='/path/to/perl/script.pl'

start() {
$DAEMON > /dev/null 2>&1
PID=`ps aux | grep -v 'grep' | grep "$DAEMON" | awk '{print $2}'`
echo $PID > /var/run/mem-monitor.pid
}

This works and satisfies my OCD! Note the double quotes around "$DAEMON" in grep "$DAEMON".

Systemd + Sys V init.d script: start works, but stop does not

You'll notice the top of your script loads /lib/lsb/init-functions. You can read the code in there and the related code in /lib/lsb/init-functions.d to understand the related code you are pulling in.

A summary is that your script likely being converted to a systemd .service in the background and is subject to a whole host of documented incompatibilities with systemd

There is inherit extra complexity and potential problems when you ask systemd to emulate and support the file formats used by the legacy Upstart and sysVinit init systems.

Since you are writing new init script from scratch, consider writing a systemd .service file directly, removing all the additional complexity of involving additional init systems.

A minimal .service file to go in /etc/systemd/system/ could look like:

[Unit]
Description=Foo

[Service]
ExecStart=/usr/sbin/foo-daemon

[Install]
WantedBy=multi-user.target

More details in man systemd.service. Some additional learning now will save you some debugging later!

Printing the result of the script(running in background) on the terminal

system('chmod +x runme.tcl');
system('/runme.tcl 2>&1');

Run bash script as daemon

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



Related Topics



Leave a reply



Submit