How 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!

based @koying solution .
Im running HA on docker (QNAP) .

I copy the remote_command_line custom_components/
I added below:

remote_command_line:
  fetch_ha_image:
    ssh_user: user
    command_timeout: 900
    command: >
        IMAGE=`docker inspect home-assistant | jq -r '.[0].Config.Image'`; docker pull -q ${IMAGE}

When execute I got

2022-11-03 09:44:47.129 ERROR (SyncWorker_6) [custom_components.remote_command_line] Command failed: ssh -4 -o ConnectTimeout=3 -o StrictHostKeyChecking=no -i /config/.ssh/id_rsa [email protected] 'IMAGE=`docker inspect home-assistant | jq -r ''.[0].Config.Image''`; docker pull -q ${IMAGE}'

I created ssh key between ha–> qnap
and place it in /share/mynap/HA/ssh/id_rsa
I did verify i’m able to execute script from the HA using:

my_test: ssh -i  /share/mynap/HA/ssh/id_rsa -o UserKnownHostsFile=/dev/null -o 'StrictHostKeyChecking=no' myuser@NAS '. /share/myqnap/HA/MyScripts/test.sh' 

So I edit the custom_components/remote_command_line /init
and place the parameter with hardcoded value in

ssh_command = f"ssh -4 -o ConnectTimeout=3 -o StrictHostKeyChecking=no /share/mynap/HA/ssh/id_rsa myuser@NAS '{escaped_command}'"

and it still through errors:

2022-11-03 10:14:01.563 ERROR (SyncWorker_3) [custom_components.remote_command_line] Command failed: ssh -4 -o ConnectTimeout=3 -o StrictHostKeyChecking=no /share/Avi/HA/ssh/id_rsa myuser@NAS 'IMAGE=`docker inspect home-assistant | jq -r ''.[0].Config.Image''`; docker pull -q ${IMAGE}'

Are you positive the host as seen by the container has that address?
If not, you might have to add ssh_host to the config.

Bottom-line: If it works with myuser@NAS, you probably should use that rather than [email protected]

I run this comand and it works perfectly under windows :

curl -g --anyauth –u “xxxx:xxxxx” “http://192.168.0.165/cgi-bin/configManager.cgi?action=setConfig&Encode[0].ExtraFormat[1].Video.Compression=H.264

But when I try it as a shell command it does nothing…

shell_command:
cocina_c: ‘curl -g --anyauth –u “xxxxx:xxxxxx” “http://192.168.0.165/cgi-bin/configManager.cgi?action=setConfig&Encode[0].ExtraFormat[1].Video.Compression=H.264”’

Can anyone help me?