diff --git a/homeassistant/components/shell_command.py b/homeassistant/components/shell_command.py index ca33666d1f3..10a6c350b7c 100644 --- a/homeassistant/components/shell_command.py +++ b/homeassistant/components/shell_command.py @@ -68,8 +68,9 @@ def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: cmd, loop=hass.loop, stdin=None, - stdout=asyncio.subprocess.DEVNULL, - stderr=asyncio.subprocess.DEVNULL) + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) else: # Template used. Break into list and use create_subprocess_exec # (which uses shell=False) for security @@ -80,12 +81,19 @@ def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: *shlexed_cmd, loop=hass.loop, stdin=None, - stdout=asyncio.subprocess.DEVNULL, - stderr=asyncio.subprocess.DEVNULL) + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + ) process = yield from create_process - yield from process.communicate() + stdout_data, stderr_data = yield from process.communicate() + if stdout_data: + _LOGGER.debug("Stdout of command: `%s`, return code: %s:\n%s", + cmd, process.returncode, stdout_data) + if stderr_data: + _LOGGER.debug("Stderr of command: `%s`, return code: %s:\n%s", + cmd, process.returncode, stderr_data) if process.returncode != 0: _LOGGER.exception("Error running command: `%s`, return code: %s", cmd, process.returncode) diff --git a/tests/components/test_shell_command.py b/tests/components/test_shell_command.py index c7cef78a127..a1acffd62e5 100644 --- a/tests/components/test_shell_command.py +++ b/tests/components/test_shell_command.py @@ -148,3 +148,41 @@ class TestShellCommand(unittest.TestCase): self.assertEqual(1, mock_call.call_count) self.assertEqual(1, mock_error.call_count) self.assertFalse(os.path.isfile(path)) + + @patch('homeassistant.components.shell_command._LOGGER.debug') + def test_stdout_captured(self, mock_output): + """Test subprocess that has stdout.""" + test_phrase = "I have output" + self.assertTrue( + setup_component(self.hass, shell_command.DOMAIN, { + shell_command.DOMAIN: { + 'test_service': "echo {}".format(test_phrase) + } + })) + + self.hass.services.call('shell_command', 'test_service', + blocking=True) + + self.hass.block_till_done() + self.assertEqual(1, mock_output.call_count) + self.assertEqual(test_phrase.encode() + b'\n', + mock_output.call_args_list[0][0][-1]) + + @patch('homeassistant.components.shell_command._LOGGER.debug') + def test_stderr_captured(self, mock_output): + """Test subprocess that has stderr.""" + test_phrase = "I have error" + self.assertTrue( + setup_component(self.hass, shell_command.DOMAIN, { + shell_command.DOMAIN: { + 'test_service': ">&2 echo {}".format(test_phrase) + } + })) + + self.hass.services.call('shell_command', 'test_service', + blocking=True) + + self.hass.block_till_done() + self.assertEqual(1, mock_output.call_count) + self.assertEqual(test_phrase.encode() + b'\n', + mock_output.call_args_list[0][0][-1])