Samedi 26 janvier 2019

NetworkManager-dispatcher

Prérequis : utiliser NetworkManager pour la gestion des connexions “réseau”

Certains services nécessitent d’avoir une connexion réseau pour démarrer. Selon votre besoin, vous pouvez utiliser le dispatcher de NetworkManager pour les lancer ou rajouter le service NetworkManager-wait-online.service qui permet d’attendre une connexion avant de poursuivre le démarrage.

Note : Le service NetworkManager-wait-online.service bloque le démarrage jusqu’à avoir une connexion ou pendant une temporisation de 30s.

Pour utiliser le dispatcher, il faut créer des scripts dans le répertoire /etc/NetworkManager/dispatcher.d, le fichier peut avoir un préfixe pour donner un ordre de lancement, exemple : 10-netfs, 20-ntpd
Le script en lui même prend 2 arguments, l’un pour le nom de l’interface, l’autre pour le statut, voici un exemple :

#!/bin/sh
INTERFACE=$1 # Le nom de l'interface
STATUS=$2 # Le statut

case "$STATUS" in
    'up') exec systemctl start [service];;
    'down') exec systemctl stop [service];;
esac

Afin que les scripts s’exécutent, il est nécessaire d’activer le dispatcher :

systemctl enable NetworkManager-dispatcher

Exemple A

Monter/démonter certains partages réseau automatiquement lorsque je change de réseau (par exemple, Homer/Office).

NetworkManager a une option intéressante pour exécuter des scripts après s’être connecté/déconnecté à un réseau, voir la page wiki d’Arch.

dispatcher.d exécute tous les fichiers du dossier dispatcher.d dans un ordre linéaire, et vous devez coder chaque script pour gérer l’interface, l’état de connexion et le réseau auquel vous vous connectez, donc au début tous les scripts ressemblent à ceci,

#!/bin/sh
### ONE OF OLD SCRIPT FORMAT

USER='username'
REMOTE='user@host:/remote/path'
LOCAL='/local/path'

interface=$1 status=$2
if [ "$CONNECTION_UUID" = "uuid" ]; then
  case $status in
    up)
      export SSH_AUTH_SOCK=$(find /tmp -maxdepth 1 -type s -user "$USER" -name 'ssh')
      su "$USER" -c "sshfs $REMOTE $LOCAL"
      ;;
    down)
      fusermount -u "$LOCAL"
      ;;
  esac
fi

Il fallait reproduire le modèle if/case pour chaque script à ajouter, alors on adopte une approche différente en ajoutant le fichier 88-MASTER-DISPATCHER dans le dossier dispatcher.d

#!/bin/bash

[[ -z ${CONNECTION_UUID} ]] && exit 0

DEVICE=${1}
STATE=${2}
CWD=$(dirname "$0")

LOG='/var/log/NetworkManager_dispatcher.d.log'

# DEBUG
echo "$(date +"%F %T") Called with ($*) and connection uuid is: ${CONNECTION_UUID}" >> ${LOG}

# Needed only if you need to display notification popups
#export DISPLAY=:0.0
#export $(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep session)/environ)

for FILE in ${CWD}/${CONNECTION_UUID}/${STATE}/*
do
  #DEBUG
  echo "$(date +"%F %T") Running ${FILE}" >> ${LOG}
  . "${FILE}"
done

NetworkManager passe 2 paramètres à chaque script qu’il exécute sous le répertoire dispatcher,

  • $1 == Nom de l’appareil, p. ex. eth0/enp0s25, tun0
  • $2 == L’état de la connexion, par ex. up/down, vpn-up

Ainsi, si nous nous sommes connectés au réseau domestique avec, le script “master” va lister tous les fichiers sous ${CONNECTION_UUUID}/up et les exécuter un par un.

La structure du dossier de dispatcher ressemble à ceci

# tree /etc/NetworkManager/dispatcher.d 

/etc/NetworkManager/dispatcher.d 
├── 4237f1af-15bf-46f7-a3a1-9a37c0d075de/
│   ├── down/
│   │   └── 00-umount-freenas-media*
│   └── up/
│       ├── 00-mount-freenas-media*
│       ├── 70-wifi-wired-exclusive.sh*
│       └── 99-set-display*
├── fdd94fcd-c801-401c-9caa-ebb21e10bc9e/
│   ├── down/
│   └── up/
│       └── 99-set-display*
...
├── Home -> 4237f1af-15bf-46f7-a3a1-9a37c0d075de/
├── Office -> fdd94fcd-c801-401c-9caa-ebb21e10bc9e/
...
└── 88-MASTER-DISPATCHER*
  • Décocher la case “Connexion automatique à ce réseau” pour chaque profil dans NetworkManager.
  • Vous devrez créer vous-même la hiérarchie des dossiers.
  • Les fichiers du dossier dispatcher sont marqués comme exécutables.

Exemple B

Créer le script de test qui doit être placé dans /etc/NetworkManager/dispatcher.d/ et devra être chmod 700 et chown root:root

sudo nano /etc/NetworkManager/dispatcher.d/20-yan-dispatch
#!/bin/bash

## Script NetworkManager Dispatcher pour démarrer/arrêter un tunnel SSH lorsqu'une interface up/down
## Ceci doit être placé dans /etc/NetworkManager/dispatcher.d/ et devra être chmod 700 et chown root:root

IF=$1
STATUS=$2

wait_for_process(){
    PNAME=$1
    PID=`pgrep $PNAME`
    while [ -z "$PID" ];do
        echo "NM ssh-tunnel: attendre 5 sec $1" | systemd-cat -t yan-dispatch -p info
        sleep 5;
        PID=`pgrep $PNAME`
    done
    logger "NM ssh-tunnel: $1 est en cours d'exécution" | systemd-cat -t yan-dispatch -p info
}

## Attendre que nm-applet démarre, sinon ce script s'exécutera dans la boîte de connexion et échouera, puisque l'utilisateur n'est pas connecté.
wait_for_process nm-applet

if [ "$IF" = "enp0s31f6" ]; then
  case "$2" in
    up)
      echo "NM ssh-tunnel up déclenchement" | systemd-cat -t yan-dispatch -p info
      #nohup su -c "ssh -fN -M -S ~/.ssh-tunnel -D local_port_number -p ssh_port_number user@hostname" your_user_here
      ;;
    down)
      echo "NM ssh-tunnel down déclenchement" | systemd-cat -t yan-dispatch -p info
      ## to check status of tunnel
      ## ssh -S ~/.ssh-tunnel -O check user@hostname
      #su -c "ssh -S ~/.ssh-tunnel -O exit user@hostname" your_user_here
      ;;
  esac
fi
sudo chown root:root /etc/NetworkManager/dispatcher.d/20-yan-dispatch
sudo chmod 700 /etc/NetworkManager/dispatcher.d/20-yan-dispatch

logger systemd

systemd-cat (systemd) est l’équivalent à logger (syslog-ng):

echo 'Bonjour' | systemd-cat

Dans un autre terminal exécuter journalctl -f :

janv. 26 16:32:37 yannick-pc cat[4211]: Bonjour

Les priorités sont spécifiées uniquement par l’option -p :

echo 'Bonjour' | systemd-cat -p info
echo 'Bonjour' | systemd-cat -p warning
echo 'Bonjour' | systemd-cat -p emerg

Warnings are bold, emergencies are bold and red. Scary stuff.
Les avertissements (info) sont en ‘normal’, les urgences (warning) sont en ‘gras’ , (emerg) en ‘gras’+’rouge’.

Vous pouvez également utiliser un ‘identifiant’ arbitraire, pour spécifier le nom de l’application. Ce sont comme les anciennes installations de syslog, mais vous n’êtes pas coincé avec des choses anciennes comme’lpr’‘uucp’‘nntp’‘ou le toujours descriptif’local0’ à’local7’.

echo 'Bonjour' | systemd-cat -t someapp -p emerg

Est connecté en tant que :

janv. 26 16:41:09 yannick-pc someapp[4352]: Bonjour

Très utile. Vous pouvez filtrer les messages de journal créés avec -t à l’aide de la commande suivante :

journalctl -t someapp 
-- Logs begin at Mon 2019-01-14 17:38:43 CET, end at Sat 2019-01-26 16:43:43 CET. --
janv. 26 16:41:09 yannick-pc someapp[4352]: Bonjour