Shell_command comment lancer un processus sur une machine distante en YAML (tuto)

Bonjour à tous.
Comment exécuter un programme sur une machine distante, en YAML ?
HASS a la possibilité d’écrire des ordres en ligne de commande. Ces possibilités sont assez réduites, et on ne peut pas les étendre en rajoutant des fonctionnalités (packages).
SSH est cependant présent dans l’installation standard de HASS. On peut se connecter à une autre machine par SSH et y lancer des programmes. Le problème, c’est que dans l’utilisation standard de SSH, il faut entrer le mot de passe de la machine cible, ce que ne sait pas faire YAML (pas d interaction en shell_command).
SSH peut cependant se connecter à une machine cible SANS mot de passe, à condition que celle ci possède une clef de reconnaissance.
C’est le but ici : se connecter en YAML à une machine cible, sans interaction (sans demande de mot de passe).
Dans cet exemple j’utilise lm-sensors, un package installé sur la cible (ha@192.168.xxx.yyy ), qui permet de lire les capteurs hardware de la machine, avec l’ordre sensors.
Si on fait directement sensors dans un terminal de HASS on a une erreur, HASS ne connaît pas sensors.
Si on passe par ssh : ssh ha@192.168.xxx.yyy 'sensors' ça marche, mais après demande du mot de passe.
Pour contourner cela on utilise l’option –i de ssh. Cela indique à ssh quelle clef utiliser pour se connecter.
Pour pouvoir utiliser une clef, il faut en générer 2 ! Une publique et une privée. La clef publique (id_rsa.pub ) doit etre transmise à la machine cible, pour que ssh puisse la valider avec la clef privée conservée par la machine appelante.
La particularité de HASS, c’est que son organisation de répertoire est très contrainte, seuls sont partagés avec les autres conteneurs /config & /share, et ce sont les seuls à ne pas être effacés après une mise à jour. Il faut donc conserver ces clefs quelque part dans /config/.
J’ai choisi de les mettre dans /config/_ssh/ (_ssh et non pas .ssh pour les différencier).
Avant de commencer, il faut un terminal dans HASS, il FAUT utiliser SSH & WEB TERMINAL (SWT) ET DESACTIVER LE MODE PROTECTION.
Donc pas l add-on « officiel » mais celui de la communauté, qui possède plus de fonctions.

Cette partie se déroule donc dans SWT :
Création de /config/_ssh/ : mkdir ~/config/_ssh
Création des clefs : ssh-keygen -t rsa répondre /config/_ssh/id_rsa pour le chemin et ENTER aux autres questions ( ! attention à la syntaxe !)
Sur la machine cible (toujours sur SWT, par ssh avec le mot de passe):
! Attention vérifiez AVANT sur la cible si il n’existe pas par hasard d’autres clefs déjà enregistrées. Une nouvelle génération reconstruit des clefs différentes !
Création du répertoire : ssh ha@192.168.xxx.yyy mkdir .ssh
Copie de la clef : cat /config/_ssh/id_rsa.pub | ssh ha@192.168.xxx.yyy 'cat >> .ssh/authorized_keys'
Test en direct (SWT) : ssh ha@192.168.xxx.yyy -i /config/_ssh/id_rsa 'sensors'
Si ici ça fonctionne (en principe SANS mot de passe), c’est bon signe.

MAIS les fonctions natives shell de HASS, NE SONT PAS LES MEMES que celles disponibles dans les différents addons (et différentes selon les addons). Autrement dit ce qui fonctionne dans un terminal, peut ne pas fonctionner en YAML
La particularité de SWT est de pouvoir se mettre exactement à la place de HASS, avec : docker exec -it homeassistant bash
Donc dans SWT :
docker exec -it homeassistant bash
bash-5.1# ssh ha@192.168.xxx.yyy -i /config/_ssh/id_rsa 'sensors'
Notons le changement de prompt.
Pour sortir: exit.
Si ça fonctionne ici on peut passer au YAML.

On crée une shell_command :

shell_command:
  test_ssh: ssh ha@192.168.xxx.yyy  -i /config/_ssh/id_rsa "sensors" > /config/test_de_sensors.txt

! IL FAUT REBOOTER HA POUR QUE LA COMMANDE SOIT VISIBLE !
Puis dans DEVELOPPER TOOLS > SERVICE > on tape la commande de test : test_ssh
& bouton valider ( ! CE BOUTON MONTRE TOUJOURS OK MEME EN CAS D ERREUR !)
Si tout c’est bien passé on a un nouveau fichier : test_de_sensors.txt dans /config/.

Voilà, si ça peut aider…
@golfvert Merci

PS ATTENTION vous allez bricoler un serveur, ne vous lancez la dedans que si vous savez ce que vous faites, et que vous vous sentez capables de réparer en cas de problèmes !
PS1 Attention à la syntaxe !
PS2 pour ces tests j’utilise DEBIAN + HA SUPERVISED et en réalité la machine distante (cible) est la même machine physique, mais avec un autre utilisateur.

2 « J'aime »

Merci @paya_ha pour ce tuto, j’utilise aussi cette méthode pour exécuter des commandes de mon serveur HA vers un autre raspberry pi.

De rien, je demande souvent de l’aide…
…quand je peux en donner, c’est normal.

Bonjour,
Je me permets d’ajouter la solution que j’utilise basée sur la même technique.
Exemple d’automatisation afin de redémarrer un service sur une machine distante

A titre d’exemple :

HAos est installé sur une machine dédiée (Raspberry pi 5)

Weewx (logiciel météo) est installé sur une machine dédiée (Odroid xu4 – Debian 13) afin de récupérer les données d’une station météo Bresser 5en1 et de les transmettre à HAos par mqtt.

Problème : parfois suite au redémarrage de HAos, les données ne sont plus transmises.

Solution : redémarrer le service weewx sur la machine Odroid

But → améliorer cette solution :

Donc, réaliser une automatisation qui permet de redémarrer le service weewx lorsque l’état de l’entité « weewx température extérieure » passe à indisponible ou à inconnu.

Moyen :

Utiliser la commande ssh pour se connecter sans mot de passe à une machine extérieure (Odroid xu4) afin de redémarrer le service weewx en cas de défaillance.

Technique – mode d’emploi :
Le serveur SSH doit être installé sur la machine distante (Odroid dans l’exemple)
(Sur l’Odroid, vérifier : sudo systemctl status ssh)

Sur HAos ouvrir le terminal SSH.
J’utilise (pas obligatoire) de manière temporaire le programme mc (Midnight Commander).
Pour l’installer dans le terminal :

apk add mc

Créer dans « /config », le dossier « scripts » et le dossier « ssh » qui contiendra les 2 clés.
Dans le dossier « scripts », coller les 3 scripts bash suivants et les rendre exécutables :
« creation_keys.sh », « check-service.sh » et « restart_service_weewx_sur_odroid.sh »

1 – « creation_keys.sh » (création de 2 clés rsa sur la machine HAos et copie de la clé sur Odroid)
En premier lieu (via le terminal), exécuter ce fichier (normalement si tout va bien, une seule fois!)
Sur la machine Odroid, le fichier authorized_keys est créé (s’il n’existait pas) et contient la clé d’échange entre les 2 machines.
Sur Haos, les 2 clés sont alors présentes dans le dossier « /config/ssh »

2 – « check-service.sh » (permet de redémarrer le service weewx sur la machine Odroid en tant que root)

3 – « restart_service_weewx_sur_odroid.sh » (le script qui sera déclenché via la shell command présente dans configuration.yaml)

La connexion avec la machine Odroid est sans mot de passe car la commande ssh lit la clé dans le répertoire « /config/ssh » sur Haos

Via le terminal, exécuter ce fichier et vérifier le contenu des fichiers log.
Si tout va bien, on continue …

Ouvrir le fichier « configuration.yaml » en utilisant ‘File editor’ et ajouter la commande suivante :

shell_command:
  restart_service_weewx_sur_odroid: bash /config/scripts/restart_service_weewx_sur_odroid.sh

Enregistrer ce fichier et vérifier si le démarrage sera possible.
Si oui, alors redémarrer …

Après avoir redémarré HAos, on réalise la création de l’automatisation en utilisant l’éditeur visuel.
Le déclencheur est l’état de l’entité « weewx température extérieure »
L’état (n’importe lequel) passe à indisponible ou à inconnu
L’action est la commande shell définie dans configuration.yaml
« shell_command.restart_service_weewx_sur_odroid »

Enregistrer l’automatisation en lui donnant un nom (bien parlant).
Tester et vérifier les fichiers log en cas de problème(sur HAos et sur Odroid).

Le contenu des 3 fichiers bash dans /config/scripts sur HAos

« check-service.sh »

#!/bin/bash
# vérifier en lisant le contenu du fichier « /home/check-service.log » sur la machine distante
export LANG=fr_FR.UTF-8
SERVICE="weewx"
LOG_FILE="/home/check-service.log"
systemctl stop $SERVICE
if ! systemctl is-active --quiet $SERVICE; then
    echo "$(date): Le service $SERVICE est arrêté. Redémarrage du service maintenant." >> $LOG_FILE
    systemctl start $SERVICE
    if systemctl is-active --quiet $SERVICE; then
        echo "$(date): Le démarrage du service $SERVICE est un succès !" >> $LOG_FILE
    else
        echo "$(date): Erreur de démarrage du service $SERVICE." >> $LOG_FILE
    fi
    echo "=====================================================" >> $LOG_FILE
fi

==============================================================
« creation_keys.sh »

#!/bin/bash
ssh-keygen -q -t rsa -N '' -f /config/ssh/id_rsa <<<y 2>creation_key.log
ssh-copy-id -i /config/ssh/id_rsa 'root@<IP de la machine distante>'

===============================================================
« restart_service_weewx_sur_odroid.sh »

#!/bin/bash
# en cas de problème, lire le fichier « erreur_check-service.log »
cd /config/scripts
ssh -i /config/ssh/id_rsa -o StrictHostKeyChecking=no root@<IP de la machine distante> 'bash -s' < ./check-service.sh 2>erreur_check-service.log

Remarques :

Pour adapter à votre cas, changer le nom du service et introduire l’adresse IP de votre machine distante dans chacun des 3 scripts bash.
Vous pouvez éventuellement lancer un autre script sur la machine distante (autre qu’un service).
Il n’est pas alors nécessaire de le faire en tant que Root (choisir un autre utilisateur de la machine distante).
Sur la machine distante, consulter le fichier « root/.ssh/authorized_keys » pour visionner la clé d’échange entre les 2 machines.
Dans l’exemple, la machine distante est un Odroid mais cela devrait aussi fonctionner pour un Raspberry (Debian 13).

L’automatisation en yaml

alias: Restart service weewx sur Odroid
description: ""
triggers:
  - trigger: state
    entity_id:
      - sensor.weewx_temperature_exterieure
    to:
      - unknown
      - unavailable
    from: null
conditions: []
actions:
  - action: shell_command.restart_service_weewx_sur_odroid
    metadata: {}
    data: {}
mode: single

Ce sujet a été automatiquement fermé après 2 jours. Aucune réponse n’est permise dorénavant.