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
How to Save Output of "Watch" to File
How to Sort Files Numerically from Linux Command Line
Linux Bash: Move Multiple Different Files into Same Directory
How to List the Contents of a Package Using Yum
Attaching and Mounting Existing Ebs Volume to Ec2 Instance Filesystem Issue
Run Bash Commands from Txt File
Differencebetween Clock_Monotonic & Clock_Monotonic_Raw
Cmake_Prefix_Path Doesn't Help Cmake in Finding Qt5
How to Extract Numbers from a String
Why Is It That Utf-8 Encoding Is Used When Interacting with a Unix/Linux Environment
How to Cut First Column (Variable Length) of a String in Shell
Selecting the Right Linux I/O Scheduler for a Host Equipped with Nvme Ssd
Using Assertion in the Linux Kernel
How to Calculate an Md5 Checksum of a Directory
How to Create Threads Without System Calls in Linux X86 Gas Assembly
Using Putty to Scp from Windows to Linux