Which PID belongs into the systemd PIDFile section when creating a shell script daemon?
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
I've created a shell script daemon, based on the code of this answer. I've written a systemd service file with the following contents:
[Unit]
Description=My Daemon
After=network.target
[Service]
Type=forking
PIDFile=/run/daemon.pid
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
Just before the while loop starts, I'm creating a PID file (it is going to be created by the daemon, not by the child, or the parent, because they don't come to this point): echo $$ > /run/daemon.pid;
. It works fine, but each time I call systemctl status daemon.service
, I get the following warning:
daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
If I insert the PID creaton statement echo $$ > /run/daemon.pid;
at the very beginning of the script (which will be used by the children and parent, too), I get the following warning:
daemon.service: PID 30631 read from file /run/daemon.pid does not exist or is a zombie.
What would be the best approach for creating the PID file without getting any warning messages by systemd?
systemd process daemon
add a comment |Â
up vote
1
down vote
favorite
I've created a shell script daemon, based on the code of this answer. I've written a systemd service file with the following contents:
[Unit]
Description=My Daemon
After=network.target
[Service]
Type=forking
PIDFile=/run/daemon.pid
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
Just before the while loop starts, I'm creating a PID file (it is going to be created by the daemon, not by the child, or the parent, because they don't come to this point): echo $$ > /run/daemon.pid;
. It works fine, but each time I call systemctl status daemon.service
, I get the following warning:
daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
If I insert the PID creaton statement echo $$ > /run/daemon.pid;
at the very beginning of the script (which will be used by the children and parent, too), I get the following warning:
daemon.service: PID 30631 read from file /run/daemon.pid does not exist or is a zombie.
What would be the best approach for creating the PID file without getting any warning messages by systemd?
systemd process daemon
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I've created a shell script daemon, based on the code of this answer. I've written a systemd service file with the following contents:
[Unit]
Description=My Daemon
After=network.target
[Service]
Type=forking
PIDFile=/run/daemon.pid
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
Just before the while loop starts, I'm creating a PID file (it is going to be created by the daemon, not by the child, or the parent, because they don't come to this point): echo $$ > /run/daemon.pid;
. It works fine, but each time I call systemctl status daemon.service
, I get the following warning:
daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
If I insert the PID creaton statement echo $$ > /run/daemon.pid;
at the very beginning of the script (which will be used by the children and parent, too), I get the following warning:
daemon.service: PID 30631 read from file /run/daemon.pid does not exist or is a zombie.
What would be the best approach for creating the PID file without getting any warning messages by systemd?
systemd process daemon
I've created a shell script daemon, based on the code of this answer. I've written a systemd service file with the following contents:
[Unit]
Description=My Daemon
After=network.target
[Service]
Type=forking
PIDFile=/run/daemon.pid
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
Just before the while loop starts, I'm creating a PID file (it is going to be created by the daemon, not by the child, or the parent, because they don't come to this point): echo $$ > /run/daemon.pid;
. It works fine, but each time I call systemctl status daemon.service
, I get the following warning:
daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
If I insert the PID creaton statement echo $$ > /run/daemon.pid;
at the very beginning of the script (which will be used by the children and parent, too), I get the following warning:
daemon.service: PID 30631 read from file /run/daemon.pid does not exist or is a zombie.
What would be the best approach for creating the PID file without getting any warning messages by systemd?
systemd process daemon
asked Aug 3 at 12:53
chevallier
800116
800116
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
1
down vote
So the problem you're seeing here is because when Type=forking
is in use, then the pid file must be created (with the correct pid) before the parent process exits.
If you create the pidfile from the child, then it will race with the exit of the parent and in some (many?) cases will cause the first error you're seeing.
If you create the pidfile writing $$
to it before you start the child, then it will have the pid of the parent, which will have exited, so you'll see the other error.
One way to do this correctly is to write the pidfile from the parent, just before exiting. In that case, write $!
(and not $$
), which returns the pid of the last process spawned in background.
For example:
#!/bin/bash
# Run the following code in background:
(
while keep_running; do
do_something
done
) &
# Write pid of the child to the pidfile:
echo "$!" >/run/daemon.pid
exit
This should work correctly... HOWEVER, there's a much better way to accomplish this! Read on...
Actually, the whole point of systemd is to daemonize processes and run them in background for you... By trying to do that yourself, you're just preventing systemd from doing it for you. Which is making your life much harder at the same time...
Instead of using Type=forking
, simply write your shell script to run in foreground and set up the service to use Type=simple
. You don't need any pidfiles then.
Update your /root/bin/daemon.sh
to simply do this:
#!/bin/bash
# Run the following code in foreground:
while keep_running; do
do_something
done
(NOTE: Perhaps daemon.sh
is not the best name for it at this point... Since that would imply it runs in background. Maybe name it something more appropriate, related to what it actually does.)
Then update the .service
file to use Type=simple
(which would actually be used by default here, so you could even omit it.)
[Service]
Type=simple
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
BTW, you can probably drop ExecStop=
, since killing the process with a signal is the default behavior as well...
systemd's Type=forking
is really there only for legacy programs that only work that way and can't be easily fixed to work in foreground... It's hacky and inefficient. The whole point of systemd (and some of its alternatives, predecessors) is to do the forking and daemonizing itself and let services just worry about doing what they need to do! :-)
I hope you find this helpful... And I really hope you choose to let systemd do the heavy lifting for you! It's much more efficient that way.
add a comment |Â
up vote
0
down vote
Ok, the error message daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
disappeared after I added the following statement to the service file:
ExecStartPost=/bin/sleep 2
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
So the problem you're seeing here is because when Type=forking
is in use, then the pid file must be created (with the correct pid) before the parent process exits.
If you create the pidfile from the child, then it will race with the exit of the parent and in some (many?) cases will cause the first error you're seeing.
If you create the pidfile writing $$
to it before you start the child, then it will have the pid of the parent, which will have exited, so you'll see the other error.
One way to do this correctly is to write the pidfile from the parent, just before exiting. In that case, write $!
(and not $$
), which returns the pid of the last process spawned in background.
For example:
#!/bin/bash
# Run the following code in background:
(
while keep_running; do
do_something
done
) &
# Write pid of the child to the pidfile:
echo "$!" >/run/daemon.pid
exit
This should work correctly... HOWEVER, there's a much better way to accomplish this! Read on...
Actually, the whole point of systemd is to daemonize processes and run them in background for you... By trying to do that yourself, you're just preventing systemd from doing it for you. Which is making your life much harder at the same time...
Instead of using Type=forking
, simply write your shell script to run in foreground and set up the service to use Type=simple
. You don't need any pidfiles then.
Update your /root/bin/daemon.sh
to simply do this:
#!/bin/bash
# Run the following code in foreground:
while keep_running; do
do_something
done
(NOTE: Perhaps daemon.sh
is not the best name for it at this point... Since that would imply it runs in background. Maybe name it something more appropriate, related to what it actually does.)
Then update the .service
file to use Type=simple
(which would actually be used by default here, so you could even omit it.)
[Service]
Type=simple
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
BTW, you can probably drop ExecStop=
, since killing the process with a signal is the default behavior as well...
systemd's Type=forking
is really there only for legacy programs that only work that way and can't be easily fixed to work in foreground... It's hacky and inefficient. The whole point of systemd (and some of its alternatives, predecessors) is to do the forking and daemonizing itself and let services just worry about doing what they need to do! :-)
I hope you find this helpful... And I really hope you choose to let systemd do the heavy lifting for you! It's much more efficient that way.
add a comment |Â
up vote
1
down vote
So the problem you're seeing here is because when Type=forking
is in use, then the pid file must be created (with the correct pid) before the parent process exits.
If you create the pidfile from the child, then it will race with the exit of the parent and in some (many?) cases will cause the first error you're seeing.
If you create the pidfile writing $$
to it before you start the child, then it will have the pid of the parent, which will have exited, so you'll see the other error.
One way to do this correctly is to write the pidfile from the parent, just before exiting. In that case, write $!
(and not $$
), which returns the pid of the last process spawned in background.
For example:
#!/bin/bash
# Run the following code in background:
(
while keep_running; do
do_something
done
) &
# Write pid of the child to the pidfile:
echo "$!" >/run/daemon.pid
exit
This should work correctly... HOWEVER, there's a much better way to accomplish this! Read on...
Actually, the whole point of systemd is to daemonize processes and run them in background for you... By trying to do that yourself, you're just preventing systemd from doing it for you. Which is making your life much harder at the same time...
Instead of using Type=forking
, simply write your shell script to run in foreground and set up the service to use Type=simple
. You don't need any pidfiles then.
Update your /root/bin/daemon.sh
to simply do this:
#!/bin/bash
# Run the following code in foreground:
while keep_running; do
do_something
done
(NOTE: Perhaps daemon.sh
is not the best name for it at this point... Since that would imply it runs in background. Maybe name it something more appropriate, related to what it actually does.)
Then update the .service
file to use Type=simple
(which would actually be used by default here, so you could even omit it.)
[Service]
Type=simple
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
BTW, you can probably drop ExecStop=
, since killing the process with a signal is the default behavior as well...
systemd's Type=forking
is really there only for legacy programs that only work that way and can't be easily fixed to work in foreground... It's hacky and inefficient. The whole point of systemd (and some of its alternatives, predecessors) is to do the forking and daemonizing itself and let services just worry about doing what they need to do! :-)
I hope you find this helpful... And I really hope you choose to let systemd do the heavy lifting for you! It's much more efficient that way.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
So the problem you're seeing here is because when Type=forking
is in use, then the pid file must be created (with the correct pid) before the parent process exits.
If you create the pidfile from the child, then it will race with the exit of the parent and in some (many?) cases will cause the first error you're seeing.
If you create the pidfile writing $$
to it before you start the child, then it will have the pid of the parent, which will have exited, so you'll see the other error.
One way to do this correctly is to write the pidfile from the parent, just before exiting. In that case, write $!
(and not $$
), which returns the pid of the last process spawned in background.
For example:
#!/bin/bash
# Run the following code in background:
(
while keep_running; do
do_something
done
) &
# Write pid of the child to the pidfile:
echo "$!" >/run/daemon.pid
exit
This should work correctly... HOWEVER, there's a much better way to accomplish this! Read on...
Actually, the whole point of systemd is to daemonize processes and run them in background for you... By trying to do that yourself, you're just preventing systemd from doing it for you. Which is making your life much harder at the same time...
Instead of using Type=forking
, simply write your shell script to run in foreground and set up the service to use Type=simple
. You don't need any pidfiles then.
Update your /root/bin/daemon.sh
to simply do this:
#!/bin/bash
# Run the following code in foreground:
while keep_running; do
do_something
done
(NOTE: Perhaps daemon.sh
is not the best name for it at this point... Since that would imply it runs in background. Maybe name it something more appropriate, related to what it actually does.)
Then update the .service
file to use Type=simple
(which would actually be used by default here, so you could even omit it.)
[Service]
Type=simple
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
BTW, you can probably drop ExecStop=
, since killing the process with a signal is the default behavior as well...
systemd's Type=forking
is really there only for legacy programs that only work that way and can't be easily fixed to work in foreground... It's hacky and inefficient. The whole point of systemd (and some of its alternatives, predecessors) is to do the forking and daemonizing itself and let services just worry about doing what they need to do! :-)
I hope you find this helpful... And I really hope you choose to let systemd do the heavy lifting for you! It's much more efficient that way.
So the problem you're seeing here is because when Type=forking
is in use, then the pid file must be created (with the correct pid) before the parent process exits.
If you create the pidfile from the child, then it will race with the exit of the parent and in some (many?) cases will cause the first error you're seeing.
If you create the pidfile writing $$
to it before you start the child, then it will have the pid of the parent, which will have exited, so you'll see the other error.
One way to do this correctly is to write the pidfile from the parent, just before exiting. In that case, write $!
(and not $$
), which returns the pid of the last process spawned in background.
For example:
#!/bin/bash
# Run the following code in background:
(
while keep_running; do
do_something
done
) &
# Write pid of the child to the pidfile:
echo "$!" >/run/daemon.pid
exit
This should work correctly... HOWEVER, there's a much better way to accomplish this! Read on...
Actually, the whole point of systemd is to daemonize processes and run them in background for you... By trying to do that yourself, you're just preventing systemd from doing it for you. Which is making your life much harder at the same time...
Instead of using Type=forking
, simply write your shell script to run in foreground and set up the service to use Type=simple
. You don't need any pidfiles then.
Update your /root/bin/daemon.sh
to simply do this:
#!/bin/bash
# Run the following code in foreground:
while keep_running; do
do_something
done
(NOTE: Perhaps daemon.sh
is not the best name for it at this point... Since that would imply it runs in background. Maybe name it something more appropriate, related to what it actually does.)
Then update the .service
file to use Type=simple
(which would actually be used by default here, so you could even omit it.)
[Service]
Type=simple
ExecStart=/root/bin/daemon.sh
ExecReload=/bin/kill -1 -- $MAINPID
ExecStop=/bin/kill -- $MAINPID
TimeoutStopSec=5
KillMode=process
BTW, you can probably drop ExecStop=
, since killing the process with a signal is the default behavior as well...
systemd's Type=forking
is really there only for legacy programs that only work that way and can't be easily fixed to work in foreground... It's hacky and inefficient. The whole point of systemd (and some of its alternatives, predecessors) is to do the forking and daemonizing itself and let services just worry about doing what they need to do! :-)
I hope you find this helpful... And I really hope you choose to let systemd do the heavy lifting for you! It's much more efficient that way.
answered Aug 4 at 4:28
Filipe Brandenburger
2,894417
2,894417
add a comment |Â
add a comment |Â
up vote
0
down vote
Ok, the error message daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
disappeared after I added the following statement to the service file:
ExecStartPost=/bin/sleep 2
add a comment |Â
up vote
0
down vote
Ok, the error message daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
disappeared after I added the following statement to the service file:
ExecStartPost=/bin/sleep 2
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Ok, the error message daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
disappeared after I added the following statement to the service file:
ExecStartPost=/bin/sleep 2
Ok, the error message daemon.service: PID file /run/daemon.pid not readable (yet?) after start: No such file or directory
disappeared after I added the following statement to the service file:
ExecStartPost=/bin/sleep 2
answered Aug 3 at 13:23
chevallier
800116
800116
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f460321%2fwhich-pid-belongs-into-the-systemd-pidfile-section-when-creating-a-shell-script%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password