Shell command templating not working

Hi,
I am trying to send the value of my temperature sensor via a shell command. This is my configuration:

shell_command:
  temperature: echo 'temp={{ states("sensor.0x00158d0003f118bb_temperature") }}' | nc -u -w1 192.168.1.30 3000

When I run this command, nothing happens. Nothing shows up in the log (even on INFO level). Yet when I remove the template with a random number or string, the message gets sent.

Any tips on what I am doing wrong?

The example in the docs surrounds the shell command with single quotes, ie ’ ’

Did you read the part in the doc about templates running in a more secure environment and not being able to pipe commands etc.?

1 Like

That too! I would write a bash script to do the dirty work, then run your script via shell_command.

1 Like

You could probably call a script and add your temperature as an argument:

shell_command:
  temperature: './forward_temp.sh {{ states("sensor.0x00158d0003f118bb_temperature") }}'

Your shell script would look something similar to this:

echo "temp=$1" | nc -u -w1 192.168.1.30 3000

for those unfamiliar with Linux. You need to add executable permission too.
This can be done with the command: chmod 777 ./forward_temp.sh.

2 Likes

Thanks! I implemented the script. The script works without templating. When I added the template though, things stopped working. Now I am getting an error:

2019-12-13 11:13:09 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection.1821160752] [Errno 8] Exec format error: '/config/forward_temperature.sh'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 133, in handle_call_service
    connection.context(msg),
  File "/usr/src/homeassistant/homeassistant/core.py", line 1235, in async_call
    await asyncio.shield(self._execute_service(handler, service_call))
  File "/usr/src/homeassistant/homeassistant/core.py", line 1260, in _execute_service
    await handler.func(service_call)
  File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 78, in async_service_handler
    process = await create_process
  File "/usr/local/lib/python3.7/asyncio/subprocess.py", line 217, in create_subprocess_exec
    stderr=stderr, **kwds)
  File "/usr/local/lib/python3.7/asyncio/base_events.py", line 1529, in subprocess_exec
    bufsize, **kwargs)
  File "/usr/local/lib/python3.7/asyncio/unix_events.py", line 190, in _make_subprocess_transport
    **kwargs)
  File "/usr/local/lib/python3.7/asyncio/base_subprocess.py", line 37, in __init__
    stderr=stderr, bufsize=bufsize, **kwargs)
  File "/usr/local/lib/python3.7/asyncio/unix_events.py", line 775, in _start
    universal_newlines=False, bufsize=bufsize, **kwargs)
  File "/usr/local/lib/python3.7/subprocess.py", line 800, in __init__
    restore_signals, start_new_session)
  File "/usr/local/lib/python3.7/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: '/config/forward_temperature.sh'

Maybe try something as proposed here: Templates in shell commands

i use this shell_command to start dockers from HA. note the Input_select

restart_docker: 'curl http://127.0.0.1:8126/container/{{states.input_select.restart_docker.state}}/restart'

But you are not using any pipe in your command and the docs say that piping is not possible in combination with templates.

I assure you this works for me. ony way for you to know is to try.

I belive you that this works no worries :wink: but your command has no pipe | in it, but the one from OP has.
From the docs:

The commands can be dynamic, using templates to insert values for arguments. When using templates, shell_command runs in a more secure environment which doesn’t allow any shell helpers like automatically expanding the home dir ~ or using pipe symbols to run multiple commands. Similarly, only content after the first space can be generated by a template. This means the command name itself cannot be generated by a template, but it must be literally provided.

indeed struggled with this too before, piping is not possible in shell!

It is but not in combination in templates as far as I know.

Perhaps there is a way to use nc without a pipe? I am not familiar enough with nc.

The thought of doing anything useful in a shell without a pipe fills me with dread.

Best to call a bash / py script instead with a variable… Then in your script you do what you want, your NC stuff for example

Yes, as suggested above!

Hi!
Sorry I’m late to the party, but you just have to add the shebang line to your script. It would look like this:

#!/bin/sh
echo "temp=$1" | nc -u -w1 192.168.1.30 3000
1 Like