Skip to content

Commit 4e3f12e

Browse files
committed
Correct environment= docs, add test for actual behavior
It was observed in Supervisor#550 that when environment= is set in the [supervisord] section of the config file, that the environment of the supervisord process itself was never actually changed. This was contrary to the documentation, which said it would be. It has been this way for a very long time (always?). Now the documentation has been corrected to indicate that environment= in the [supervisord] section will be inherited by all subprocesses, but will not actually change the environment of supervisord itself. This may actually be safer, as changing some environment variables such as PYTHONPATH could unexpectedly affect the execution of supervisord (unsure). Closes Supervisor#550
1 parent 0c66c0c commit 4e3f12e

File tree

8 files changed

+41
-15
lines changed

8 files changed

+41
-15
lines changed

docs/configuration.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,8 @@ follows.
445445
``environment``
446446

447447
A list of key/value pairs in the form ``KEY="val",KEY2="val2"`` that
448-
will be placed in the :program:`supervisord` process' environment
449-
(and as a result in all of its child process' environments). This
448+
will be placed in the environment of all child processes. This does
449+
not change the environment of :program:`supervisord` itself. This
450450
option can include the value ``%(here)s``, which expands to the
451451
directory in which the supervisord configuration file was found.
452452
Values containing non-alphanumeric characters should be quoted

supervisor/options.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ class ServerOptions(Options):
406406
passwdfile = None
407407
nodaemon = None
408408
silent = None
409-
environment = None
410409
httpservers = ()
411410
unlink_pidfile = False
412411
unlink_socketfiles = False
@@ -1584,9 +1583,6 @@ def readfd(self, fd):
15841583
data = b''
15851584
return data
15861585

1587-
def process_environment(self):
1588-
os.environ.update(self.environment or {})
1589-
15901586
def chdir(self, dir):
15911587
os.chdir(dir)
15921588

supervisor/supervisord.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ def run(self):
8484
try:
8585
for config in self.options.process_group_configs:
8686
self.add_process_group(config)
87-
self.options.process_environment()
8887
self.options.openhttpservers(self)
8988
self.options.setsignals()
9089
if (not self.options.nodaemon) and self.options.first:

supervisor/tests/base.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ def __init__(self):
7777
self.setuid_msg = None
7878
self.privsdropped = None
7979
self.logs_reopened = False
80-
self.environment_processed = False
8180
self.write_accept = None
8281
self.tempfile_name = '/foo/bar'
8382
self.removed = []
@@ -232,9 +231,6 @@ def readfd(self, fd):
232231
def reopenlogs(self):
233232
self.logs_reopened = True
234233

235-
def process_environment(self):
236-
self.environment_processed = True
237-
238234
def mktempfile(self, prefix, suffix, dir):
239235
return self.tempfile_name
240236

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[supervisord]
2+
loglevel=info ; log level; default info; others: debug,warn,trace
3+
logfile=/tmp/issue-550.log ; main log file; default $CWD/supervisord.log
4+
pidfile=/tmp/issue-550.pid ; supervisord pidfile; default supervisord.pid
5+
nodaemon=true ; start in foreground if true; default false
6+
environment=THIS_SHOULD=BE_IN_CHILD_ENV
7+
8+
[rpcinterface:supervisor]
9+
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
10+
11+
[unix_http_server]
12+
file=/tmp/issue-550.sock ; the path to the socket file
13+
14+
[supervisorctl]
15+
serverurl=unix:///tmp/issue-550.sock ; use a unix:// URL for a unix socket
16+
17+
[program:print_env]
18+
command=python %(here)s/print_env.py
19+
startsecs=0
20+
startretries=0
21+
autorestart=false
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!<<PYTHON>>
2+
import os
3+
4+
for k, v in os.environ.items():
5+
print("%s=%s" % (k,v))

supervisor/tests/test_end_to_end.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@
2020

2121
class EndToEndTests(BaseTestCase):
2222

23+
def test_issue_550(self):
24+
filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-550.conf')
25+
args = ['-m', 'supervisor.supervisord', '-c', filename]
26+
supervisord = pexpect.spawn(sys.executable, args, encoding='utf-8')
27+
self.addCleanup(supervisord.kill, signal.SIGINT)
28+
supervisord.expect_exact('success: print_env entered RUNNING state')
29+
30+
args = ['-m', 'supervisor.supervisorctl', '-c', filename, 'tail -100000', 'print_env']
31+
supervisorctl = pexpect.spawn(sys.executable, args, encoding='utf-8')
32+
self.addCleanup(supervisorctl.kill, signal.SIGINT)
33+
supervisorctl.expect_exact("THIS_SHOULD=BE_IN_CHILD_ENV")
34+
supervisorctl.expect(pexpect.EOF)
35+
2336
def test_issue_565(self):
2437
filename = pkg_resources.resource_filename(__name__, 'fixtures/issue-565.conf')
2538
args = ['-m', 'supervisor.supervisord', '-c', filename]

supervisor/tests/test_supervisord.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ def test_main_first(self):
132132
options.first = True
133133
supervisord = self._makeOne(options)
134134
supervisord.main()
135-
self.assertEqual(options.environment_processed, True)
136135
self.assertEqual(options.fds_cleaned_up, False)
137136
self.assertEqual(options.rlimits_set, True)
138137
self.assertEqual(options.parse_criticals, ['setuid_called'])
@@ -142,7 +141,6 @@ def test_main_first(self):
142141
self.assertEqual(len(supervisord.process_groups), 1)
143142
self.assertEqual(supervisord.process_groups['foo'].config.options,
144143
options)
145-
self.assertEqual(options.environment_processed, True)
146144
self.assertEqual(options.httpservers_opened, True)
147145
self.assertEqual(options.signals_set, True)
148146
self.assertEqual(options.daemonized, True)
@@ -158,7 +156,6 @@ def test_main_notfirst(self):
158156
options.first = False
159157
supervisord = self._makeOne(options)
160158
supervisord.main()
161-
self.assertEqual(options.environment_processed, True)
162159
self.assertEqual(options.fds_cleaned_up, True)
163160
self.assertFalse(hasattr(options, 'rlimits_set'))
164161
self.assertEqual(options.parse_criticals, ['setuid_called'])
@@ -168,7 +165,6 @@ def test_main_notfirst(self):
168165
self.assertEqual(len(supervisord.process_groups), 1)
169166
self.assertEqual(supervisord.process_groups['foo'].config.options,
170167
options)
171-
self.assertEqual(options.environment_processed, True)
172168
self.assertEqual(options.httpservers_opened, True)
173169
self.assertEqual(options.signals_set, True)
174170
self.assertEqual(options.daemonized, False)

0 commit comments

Comments
 (0)