How to run shell commands?

I want to run a shell command, especially to run ffmpeg. I noticed there is shell_command configuration for this but it’s just completely unusable since it has some fixed arbitrary timeout of 60 seconds. So what is actually the best way to run shell commands?

If you need the command to run indefinitely, it has to be damonized.

No I just need it to run for about 65 seconds, which is about the time it takes. Is there really no simple way in HA to to run shell commands?

Try to use a command line binary sensor. That one has a timeout option.
Just add && echo "ON" after the ffmpeg command to make the sensor happy.

Don’t ask me why there is not such option in shell_command :wink:

Nah, it will poll, so not a solution.
A command_line switch might do, though

The binary sensor will poll the command regularly, but I want to call the command on demand in an automation, so using this will not work.

I guess the only way is to write my own custom_component?

1 Like

Well, you just have to

  • copy “homeassistant/components/shell_command” from the source into your custom_component subdirectory
  • add a “version” tag to the manifest (mandatory for custom components)
  • increase the COMMAND_TIMEOUT

The custom version will override the core one.

1 Like

Did you try the work around mention in the thread I posted by adding the following to the script itself?

import os
import sys

os.fork() and sys.exit()

It seemed to work for others except for the erroneous error message it throws.

In actual shell script terms, it translates to

nohup ... &

But yeah, the problem with that is that the script returns immediately, so if you want to use the result of the ffmpeg just after, it will likely fail.

1 Like

Command Line has a timeout parameter :

Yes but command line sensor polls which is not what I want. But I tried to just duplicate the shell_command as custom_component with a modified timeout and it seems work well, so that is what I going to use instead.

Thanks a lot …search for hours with 'nohup sh" doesnt work!

Your solution is simple and can be undo, and stay after an update of HA

Hello my friend,

I am trying to replicate what you have commented in your post, but I am not succeeding.

I always get the same timeout error in the log and I can’t get my scripts to run completely.

Logger: homeassistant.components.shell_command
Source: components/shell_command/__init__.py:83
Integration: Shell Command (documentation, issues)
First occurred: 20:20:46 (1 occurrences)
Last logged: 20:20:46

Timed out running command: `bash /config/Shell_Scripts/camara_shell_scripts.sh {{ state_attr("camera.camara", "access_token") }} `, after: 60s
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/asyncio/subprocess.py", line 198, in communicate
    await self.wait()
  File "/usr/local/lib/python3.9/asyncio/subprocess.py", line 135, in wait
    return await self._transport._wait()
  File "/usr/local/lib/python3.9/asyncio/base_subprocess.py", line 235, in _wait
    return await waiter
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 490, in wait_for
    return fut.result()
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 83, in async_service_handler
    stdout_data, stderr_data = await asyncio.wait_for(
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 492, in wait_for
    raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError

I have copied the folder as you indicate, but I can’t get HA to recognize the new time values for shell_commands

Could you help me to try to solve it?

Well the way I did it, instead of trying to override shell_command and not being sure which version is used, which I think is what is happening here, I just duplicated the shell_command as x_shell_command.

So I copy all the files from the source shell_command like you did to this folder:

\homeassistant.local\config\custom_components\x_shell_command

Modify init.py line 16 and 18:

DOMAIN = "x_shell_command"

COMMAND_TIMEOUT = 300

Modify manifest.json:

{
  "domain": "x_shell_command",
  "name": "Shell Command (Extended)",
  "version": "1.0",
  "documentation": "https://www.home-assistant.io/integrations/shell_command",
  "codeowners": ["@home-assistant/core","@kristjanbjarni"],
  "iot_class": "local_push"
}

Add this to configuration.yaml (I am using ffmpeg change to your own script):

x_shell_command:
  ffmpeg_convert: 'ffmpeg -i {{ infile }} -v error -y {{ parameters}} {{ outfile }}'
2 Likes

The time out 60 sec was indeed introduced a year ago

You can run the shell command, so the that the command runs in background, then there is no need for custom component version

FWIW, I created a full replacement for the command-line sensor/service.

Besides allowing to set the timeout, it also allows to disable polling altogether, so relying on homeassistant.update_entity and eases a bit the hassle of using SSH to run the command on the host rather than inside the HA docker container.

I have been able to check how it is necessary to bypass this limitation, otherwise the script that I have generated will not complete.

After making the modification indicated by my colleague, I can now launch the complete script without problems.

Now it is! Perfect!

Thank you very much for your cooperation.

By any chance you don’t know how to send a CURL command from the Shell?

It is the only thing I need to implement in the script I have, that by CURL change the status of an input boolean to know that the script is completed and the automation goes to the next step.

Best.

P.D. Nothing, I’ve got it too, I’m going to implement it in the script and see if it all works.

Can you put it on HACS?

@koying This rocks mate! Thank you very much. Saved me a lot of struggle and wasted time.

I had the same problem, using your way also and succeeded.
So thank you for sharing!