Mosquitto_sub and mosquitto_pub not available to shell_command?

I’ve created a shell_command that executes a script.

The script starts properly, but it turns out that mosquitto_sub and mosquitto_pub are not available in the shell_command container.

From the debug log:

/usr/bin/mosquitto_pub: No such file or directory
can't execute 'mosquitto_sub': No such file or directory

Any ideas?

Well the ssh & web terminal addon you can install the mosquito tools package or there are HA services you can use. This is just the way it is when you run HA OS.

Wouldn’t it be more “native” to install the MQTT integration and use service mqtt.publish to publish an sensors to subscribe?

Yes, I agree it would be more native. My problem is that the native MQTT integration is not very flexible when I want to submit a command and then check for the status (and resubmit if it fails).

With a bash script it’s easier to loop.

The frustrating thing is that when you login using port 2222, the script works perfect as both command are available. But it seems that shell_command executes directly in HASSOS and it doesn’t have both commands available

Port 2222 access:

Linux a0d7b954-ssh 4.19.127-v8 #1 SMP PREEMPT Mon Oct 12 08:05:33 UTC 2020 aarch64 Linux

Port 22222 access:

Linux homeassistant 4.19.127-v8 #1 SMP PREEMPT Mon Oct 12 08:05:33 UTC 2020 aarch64 HassOS

Yes Ha OS doesn’t have the package as I said.
In what way do you find the HA Broker unreliable? It never misses a beat here for me and I publish to it from a couple of other systems…
The sssh addon maybe includes pub/sub commands now so you don’t have to publish - not sure.

Depending on what you are trying to do you can for instance write to a sensor directly using a token so maybe that is a solution but the HA container doesn’t have mosquito tools…

Sorry for not being clear. It’s not the broker that is not reliable, but the MQTT client not always handles my requests properly. While I do agree it’s a client issue, I’m trying to work around it.

Just wondering, it there a way that shell commands are executed in a different context, like for instance in the ssh addon context?

You could use docker exec to execute a command in the ssh addon container BUT ha os probably doesn’t include docker exec…

I have had these kinds of issues before as well and sometimes you can work around them by using other supported commands but unlikely in this case.

That was actually a good thought, but unfortunately the docker command isn’t available.

It looks like the shell_command is running inside some other container as I see

.dockerenv

in the root while executing a shell_command

It will be running inside the home assistant container. If you run Portainer and execute the script in a console (of the container) you will see what commands are available.

Like I said before, you might be able to achieve what you want some other way… what exactly are you using this for? You could for example use a HA long lived token depending on exactly what you are trying to do. For example I was using an MQTT via mosquitto_pub and then a Mqtt sensor but I could switch to use a rest sensor with a long lived token to directly write to a sensor instead. There’s often multiple ways to skin a cat and end up with the same result but we need more info to see if this or something else is possible…

Thanks for pointing me to the rigth container, I was struggling there.

What I’m trying to do is to send a command to a BLE radiator valve. This TRV is (using BLE) controlled by an ESP32 running tasmota (which is the prox running MQTT).

As BLE is not the most reliable protocol it might need several attempts before the message gets through (and to get an answer).

My logic:

  • Send the command using mosquitto_pub
  • Verify that the message has been received by the BLE driver on the ESP32 using mosquitto_sub (and retry if required)
  • Wait for the answer using mosquitto_sub and retry in case the message got lost

This process works well on a regular Linux host and also when using the ssh login (in HA). So maybe I need to run some commands remotely using ssh, but obviously I need to figure out how persistent ssh keys are inside the container.

So why not try the mosquito services in HA?
Nothing will be persistent in a container - that’s not how containers work. Have you checked a console in the SSH & Web Terminal addon? You could probable use pub/sub in there? But I would definitely look at using the services instead…

I have automations in lace, but they lack reliability as I have not found an easy way to implement the try mechanism.

Example:

  • alias: “Sync EQ3 states on start-up - ESP32-1”
    initial_state: true
    trigger:
    platform: homeassistant
    event: start
    action:
    • service: mqtt.publish
      data:
      topic: “cmnd/ESP32-1/EQ3/001A2216A458/state”
      payload: “”
    • delay: 00:00:30
    • service: mqtt.publish
      data:
      topic: “cmnd/ESP32-1/EQ3/001A2217044B/state”
      payload: “”
  1. There is no feedback mechanism, so I don’t know if the publish has indeed been processed.
  2. The ESP can only handle one command at a time, so with above approach I “hope” that it takes less than 30 seconds to process the request. Most of the times it’s less than 5 seconds, but there are cases that it can take easily 45 seconds (or fails)

With my shell script I could easily submit, monitor, and optionally resubmit when required. (And, once a request has been processed, submit the next request without waiting the full 30 seconds.)

And yes, I’m working with the developer of the BLE component in Tasmota to make the handling internal to the ESP32 more robust, but I don’t want to put all my eggs in one basket.

Hope this explains.

1 Like

Quick update.

Looks like I’ve found a solution:
I use a wrapper script that is called with the required script as a parameter
The wrapper script executes in ha os and submits the required script using ssh in hassioaddons/ssh

Would you please post your solution for reference?

Hi,

Sorry for answering late. I’m no longer using this solution but more than happy to post my scripts.

Note: This is not a simple cut’n paste job, you will need to expand this yourself.

#!/bin/bash 
#
# wrapper.sh
# execute a command/script in hassioaddons/ssh
# 02/2021 - YJB - Initial version
# shell_command:
#   wrapper: /config/wrapper.sh {{script}}
#    script: /config/shell_scripts/single_command.sh <VAR1> <VAR2> <VAR3> <VAR4>
# Prep work
# a. Generate keys in the correct container
# b. copy cp -p /root/.ssh/id_rsa* /config/shell_scripts
# c. copy id_rsa.pub in the /data/.ssh/authorized_keys (on the ssh host)
#    cat /root/config/shell_scripts/id_rsa.pub >> /data/.ssh/authorized_keys
#

# ssh port 
port=2222

initialize()
 {
  # copy private key back to the container
  [ ! -d /root/.ssh ] && mkdir /root/.ssh 
  cp -p /config/shell_scripts/id_rsa /root/.ssh
  ip_address=`ifconfig eth0 |grep "inet addr" |awk -F: '{print $2}' |awk '{print $1}'`
 }

#########
# MAIN
#########

COMMAND=${1}
PARAMETERS="${2} ${3} ${4} ${5}"

DATE=`date '+%d%m%y %H:%M:%S'`
# echo "${DATE} ${COMMAND} ${PARAMETERS}" >> /config/shell_scripts/wrapper.log
echo "${DATE} ${COMMAND} ${PARAMETERS}" > /tmp/wrapper.$$


initialize

SECONDS=0
# ssh ${ip_address} -p 2222 ${COMMAND} ${PARAMETERS} >> /config/shell_scripts/wrapper.log 2>&1
ssh -o "StrictHostKeyChecking no"  ${ip_address} -p 2222 ${COMMAND} ${PARAMETERS} >> /tmp/wrapper.$$ 2>&1
DATE_E=`date '+%d%m%y %H:%M:%S'`
echo -e "${DATE_E} ${SECONDS} ${2} ${3}\n" >> /tmp/wrapper.$$

cat /tmp/wrapper.$$ >> /config/shell_scripts/wrapper.log
rm /tmp/wrapper.$$
#!/bin/bash 
#
# single_command.sh
# 01/2021 - YJB - Initial version
#


# Leave mqtt variables empty when not required
MQTT_HOST=ip_address
MQTT_PORT=1883
MQTT_USER=username
MQTT_PASSWORD=secret_password
RETRIES=3
# Change to 1 for verbose output
DEBUG=0
MOSQUITTOPUB=/usr/bin/mosquitto_pub
MOSQUITTOSUB=/usr/bin/mosquitto_sub


[ ! -z ${MQTT_HOST} ] && MQTT_HOST="-h ${MQTT_HOST}"
[ ! -z ${MQTT_PORT} ] && MQTT_PORT="-p ${MQTT_PORT}"
[ ! -z ${MQTT_USER} ] && MQTT_USER="-u ${MQTT_USER}"
[ ! -z ${MQTT_PASSWORD} ] && MQTT_PASSWORD="-P ${MQTT_PASSWORD}"

if [ ! -x ${MOSQUITTOPUB} -o ! -x ${MOSQUITTOSUB} ] 
then
    echo -e "\nFailed to find ${MOSQUITTOPUB} and/or ${MOSQUITTOSUB},\nplease check the location and correct."
    echo -e "Aborting..\n"
    exit 1
fi

#### MAIN
# here the code that you actually want to execute

Have fun!

Hello All, for anyone still interested in this topic, if you look at this post: " https://community.home-assistant.io/t/https-community-home-assistant-io-t-mosquitto-sub-and-mosquitto-pub-not-available-to-shell-command-275409/367432/4?u=jeanrocco " you will find how I was able, with @YJB 's help, to use shell_command in a Docker Hassio system to access mosquitto_pub which runs in @frenck “ssh terminal” addon.
jrb.

@jeanrocco Page does not exist anymore or is private… Can you share what you have done ? Thank you so much…

It was indeed a private message:

Thank’s a lot @YJB , with your help I was finally able to get it working… also, the ssh that runs in shell_command needs to be told to use it’s own host id_rsa private key, which I copied in /config/ssh/id_rsa … (error 255 otherwise). So without having to use your wrapper it now works fine like this:

shell_command:
lampe_labo_on: ‘ssh -i /config/ssh/id_rsa -o StrictHostKeyChecking=accept-new -p 15022 [email protected] /usr/bin/mosquitto_pub -h 192.168.1.50 -u myname -P mypass -t cmnd/sonoff9/power -m on’

pheeww ! what a mouthfullllll ! … why all this trouble ? = I’ve been running a standard Hassio on 192.168.1.50 (APU2E4) for years now, for my switches and whatnot’s, and I didn’t want to mess with it, it works right ? . I recently installed Hassio on another separate inexpensive APU2E4 at 192.168.1.35, to implement the addon Rhasspy voice command system, as a master and 3 satellites on Raspberry Pi zero w with the seed https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT.html . This all worked great until @frenck sadly removed his nice and easy service: hassio.addon_stdin …
Thank’s for your help !
jrb

1 Like