Hi,
I want my environment variable to be dynamic, which means - the expression which is used to get it would be recalculated each time supervisor tries to spawn the process.
What I have tried:
environment=ETCD_HOST=$(ifconfig eth1 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')
But it doesn't work. Restart ends up with:

What can I do here? How to make it dynamic?
Any thoughts?
Regards,
supervisord is not a shell, so it doesn't know how to evaluate the shell expression that you tried to put into the environment= line. The solution is to use a shell evaluate the expression.
Before supervisord starts
You can set up the environment in the init script that starts supervisord:
export ETCD_HOST=$(ifconfig eth1 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')
supervisord -c /path/to/supervisord.conf
The shell will set ETCD_HOST in the environment which supervisord will inherit. That environment variable will then be available to all supervisord subprocesses.
Per-program basis
If you have a program that runs the command foo:
[program:foo]
command=foo
You can create a shell script start-foo.sh:
#!/bin/bash
export ETCD_HOST=$(ifconfig eth1 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')
exec foo
In supervisord.conf, start the shell script instead of foo:
[program:your-program]
command = start-foo.sh
Hi @mnaberez,
Thanks for the explanation and answer.
In my case I found this as solution:
[program:etcd-browser]
command=/bin/bash -c \"ETCD_HOST=\$(ifconfig eth1 | grep 'inet addr:' | cut -d: -f2 | awk '{ print \$1}') node server.js\"
However, I think it would be cool, and have some logic behind, if supervisor would evaluate the expressions from the environment configuration option. Before running the command.
Currently it's expected that we store only strings there, but I think it's still logical to store the expressions and it could be considered as feature.
Regards, thanks for the software!
In my case I found this as solution:
[program:etcd-browser] command=/bin/bash -c \"ETCD_HOST=\$(ifconfig eth1 | grep 'inet addr:' | cut -d: -f2 | awk '{ print \$1}') node server.js\"
This is fine also, but you should use exec like the second example above.
Change node server.js to exec node server.js. Using exec will cause bash to replace itself with node. After the command is run, supervisord will have one child node.
Without exec, supervisord will have a child bash, and bash will have a child node. You can see this with pstree. This is undesirable because if bash alone receives SIGKILL (e.g. if killasgroup=false) then it will orphan node.
@mnaberez
Thanks!
@mnaberez
Thanks a bunch.
I am trying to spawn a number of processes, and trying to use sched_setaffinity to bind each process to a single CPU core.
The result config looks like this:
[program:my_program]
command=/bin/sh -c 'exec taskset -c $((%(process_num)d %% $(nproc))) /path/bin/my_program'
The result exactly as I planned. Each process spawned by supervisor with %(process_num)d will be bind to a dedicated CPU processor core. taskset+supervisor FTW!
I literally just lost an hour or two figuring out that supervisor doesn't reload environment variables when restarting process, they are only loaded once on start up of supervisord. The workaround I had to come to was the following:
command=/bin/bash -c 'some-command --derp $(cat ~/somevalue)'
Where I simply wanted:
command=some-command --derp %(ENV_SOMEVALUE)s
Perhaps an option to allow for reloading of environment variables per [program] block or reload on supervisorctl update this behaviour feels terrible. I wish I could understand the reasoning behind it...
Most helpful comment
This is fine also, but you should use
execlike the second example above.Change
node server.jstoexec node server.js. Usingexecwill causebashto replace itself withnode. After the command is run,supervisordwill have one childnode.Without
exec,supervisordwill have a childbash, andbashwill have a childnode. You can see this withpstree. This is undesirable because ifbashalone receivesSIGKILL(e.g. ifkillasgroup=false) then it will orphannode.