diff --git a/docs/configuration.rst b/docs/configuration.rst index 7c2c82dd9..ea8691387 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -561,9 +561,9 @@ where specified. The command that will be run when this program is started. The command can be either absolute (e.g. ``/path/to/programname``) or - relative (e.g. ``programname``). If it is relative, the - supervisord's environment ``$PATH`` will be searched for the - executable. Programs can accept arguments, e.g. ``/path/to/program + relative (e.g. ``programname``). If it is relative, the program's + directory and supervisord's environment ``$PATH`` will be searched for + the executable. Programs can accept arguments, e.g. ``/path/to/program foo bar``. The command line can use double quotes to group arguments with spaces in them to pass to the program, e.g. ``/path/to/program/name -p "foo bar"``. Note that the value of diff --git a/supervisor/process.py b/supervisor/process.py index 30573b07c..fab130e31 100644 --- a/supervisor/process.py +++ b/supervisor/process.py @@ -115,15 +115,18 @@ def get_execv_args(self): else: raise BadCommand("command is empty") - if "/" in program: + if os.path.isabs(program): filename = program try: st = self.config.options.stat(filename) except OSError: st = None - else: path = self.config.options.get_path() + # Search the root config directory of this program if it's set and is absolute. + if self.config.directory is not None and os.path.isabs(self.config.directory): + path.insert(0, self.config.directory) + found = None st = None for dir in path: diff --git a/supervisor/tests/test_process.py b/supervisor/tests/test_process.py index 74a7123aa..f0f8ab8c2 100644 --- a/supervisor/tests/test_process.py +++ b/supervisor/tests/test_process.py @@ -167,6 +167,49 @@ def test_get_execv_args_rel(self): self.assertEqual(args[0], '/bin/sh') self.assertEqual(args[1], ['sh', 'foo']) + def test_get_execv_args_rel_in_program_dir(self): + executable = 'sh foo' + directory = "/my/program/dir/" + program = os.path.join(directory, 'sh') + options = DummyOptions() + config = DummyPConfig(options, 'sh', executable, directory) + instance = self._makeOne(config) + def stat(filename): + if filename == program: + return True + else: + raise OSError + + config.options.stat = Mock(config.options.stat, side_effect=stat) + args = instance.get_execv_args() + self.assertEqual(len(args), 2) + self.assertEqual(args[0], program) + self.assertEqual(args[1], ['sh', 'foo']) + + def test_get_execv_args_rel_in_path(self): + executable = 'test_program foo' + directory = "/my/program/dir/" + program = os.path.join(directory, 'test_program') + options = DummyOptions() + config = DummyPConfig(options, 'test_program', executable) + instance = self._makeOne(config) + def stat(filename): + if filename == program: + return True + else: + raise OSError + + def get_path(): + return ["/usr/bin", directory] + + config.options.stat = Mock(config.options.stat, side_effect=stat) + config.options.get_path = Mock(config.options.get_path, side_effect=get_path) + + args = instance.get_execv_args() + self.assertEqual(len(args), 2) + self.assertEqual(args[0], program) + self.assertEqual(args[1], ['test_program', 'foo']) + def test_record_spawnerr(self): options = DummyOptions() config = DummyPConfig(options, 'test', '/test')