python supervisord program dependency
Question:
I have [program:A]
, [program:B]
in my supervisord.conf
B
depend A
, means:
A
should start before B
.
How to ensure this by supervisor?
Answers:
supervisord
does not directly support dependencies. Your options instead are:
-
Use priorities. Set priority
for A
to a low value and it’ll be started before B
, and shut down after B
. The default value for priority
is 999
.
If you put the two programs into one group as well, that’d let you start and stop them in tandem, with the priorities regulating their start and stop order.
-
Write an event listener that listens for PROCESS_STATE
STARTING
-to-RUNNING
transition and STOPPING
events for A
, then instruct supervisord
to start and stop B
according to those events. Have A
autostart, but disable autostarting for B
, so that the event handler controls it.
If you want to take a shortcut, and skip reading the documentation about event listeners and skip modifying your programs so they understand events, then:
Instead of starting program B
(which depends on A
) directly, you could start a Bash script that sleeps until A
has been started, and then starts B
. For example, if you have a PostgreSQL database and a server that shouldn’t start before PostgreSQL:
[program:server]
autorestart=true
command=/.../start-server.sh
[program:postgres]
user=postgres
autorestart=true
command=/usr/lib/postgresql/9.3/bin/postgres ...
And then inside start-server.sh
:
#!/bin/bash
# Wait until PostgreSQL started and listens on port 5432.
while [ -z "`netstat -tln | grep 5432`" ]; do
echo 'Waiting for PostgreSQL to start ...'
sleep 1
done
echo 'PostgreSQL started.'
# Start server.
echo 'Starting server...'
/.../really-start-the-server
this is a great solution for me!
A workaround that I have used is to set autostart=false
on the
processes, then create a bootstrap script with autostart=true
and
autorestart=false
(a one-shot). The bootstrap can be a shell script
that calls supervisorctl start
for each process. supervisorctl start
will block until a process has started successfully.
One solution is to use supervisorctl: set autostart to false for program B, and in the program launched by A, write supervisorctl start B
.
Example:
supervisor.cfg
:
[supervisord]
nodaemon=false
pidfile=/tmp/supervisor.pid
logfile=/logs/supervisor.log
[unix_http_server]
file=/var/run/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
[program:A]
command=do_a
[program:B]
command=do_b
autostart=false
The do_a
program contains:
#!/bin/bash
#do things
supervisorctl start B
TBH it is the solution suggested by @drrzmr but I did not understand it at the time.
I have [program:A]
, [program:B]
in my supervisord.conf
B
depend A
, means:
A
should start before B
.
How to ensure this by supervisor?
supervisord
does not directly support dependencies. Your options instead are:
-
Use priorities. Set
priority
forA
to a low value and it’ll be started beforeB
, and shut down afterB
. The default value forpriority
is999
.If you put the two programs into one group as well, that’d let you start and stop them in tandem, with the priorities regulating their start and stop order.
-
Write an event listener that listens for
PROCESS_STATE
STARTING
-to-RUNNING
transition andSTOPPING
events forA
, then instructsupervisord
to start and stopB
according to those events. HaveA
autostart, but disable autostarting forB
, so that the event handler controls it.
If you want to take a shortcut, and skip reading the documentation about event listeners and skip modifying your programs so they understand events, then:
Instead of starting program B
(which depends on A
) directly, you could start a Bash script that sleeps until A
has been started, and then starts B
. For example, if you have a PostgreSQL database and a server that shouldn’t start before PostgreSQL:
[program:server]
autorestart=true
command=/.../start-server.sh
[program:postgres]
user=postgres
autorestart=true
command=/usr/lib/postgresql/9.3/bin/postgres ...
And then inside start-server.sh
:
#!/bin/bash
# Wait until PostgreSQL started and listens on port 5432.
while [ -z "`netstat -tln | grep 5432`" ]; do
echo 'Waiting for PostgreSQL to start ...'
sleep 1
done
echo 'PostgreSQL started.'
# Start server.
echo 'Starting server...'
/.../really-start-the-server
this is a great solution for me!
A workaround that I have used is to set
autostart=false
on the
processes, then create a bootstrap script withautostart=true
and
autorestart=false
(a one-shot). The bootstrap can be a shell script
that callssupervisorctl start
for each process.supervisorctl start
will block until a process has started successfully.
One solution is to use supervisorctl: set autostart to false for program B, and in the program launched by A, write supervisorctl start B
.
Example:
supervisor.cfg
:
[supervisord]
nodaemon=false
pidfile=/tmp/supervisor.pid
logfile=/logs/supervisor.log
[unix_http_server]
file=/var/run/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
[program:A]
command=do_a
[program:B]
command=do_b
autostart=false
The do_a
program contains:
#!/bin/bash
#do things
supervisorctl start B
TBH it is the solution suggested by @drrzmr but I did not understand it at the time.