autopoweroff.sh

Introduction

Origine du script

L'objectif de ce script est d'éteindre automatiquement une passerelle ADSL lorsque personne ne l'utilise. Ceci pour économiser de l'énergie ou encore pour éviter le bruit de la passerelle la nuit.

Note de compatibilité

Comme je travaille sous OpenBSD, je préfère préciser que ce script est probablement compatible avec tous les UNIX pas trop exotiques. En effet, il n'utilise pas de commandes spécifiques GNU/Linux comme seq qui permet de sortir une séquence de nombres et qui est souvent utilisé avec les boucles for (la commande seqUsage: seq [OPTION]... DERNIER
ou: seq [OPTION]... PERMIER DERNIER
ou: seq [OPTION]... PREMIER INCRÉMENT DERNIER
Afficher les nombres du PREMIER jusqu'au DERNIER,
selon le PAS d'incrémentation.
fait partie du package GNU shellutils). Du coup, le code est parfois un peu tiré par les cheveux. Cela dit, rien ne vous empêche de modifier un peu le code pour en simplifier la structure.

Par contre je ne garantis pas que certaines structures comme l'utilisation de parenthèses au lieu de crochets dans les tests des structures conditionnelles ne pose pas quelques problèmes sous GNU/Linux (Je n'ai pas de machine sous la main pour m'en assurer).

Le shell utilisé pour ce script est tout simplement sh.

Pré-requis

Pour mettre en oeuvre ce script, vous devez disposer d'une passerelle ADSL tournant sous UNIX et d'un réseau local dont les adresses IP sont constantes (idéalement, un serveur DHCP tournant sur la passerelle allouant une adresse IP fixe en fonction de l'adresse MAC de la machine demandeuse). Il est en effet nécessaire de connaître les adresses IP des machines utilisant la passerelle.

Fonctionnement du script

Exécuté sur une passerelle internet personnelle, le script, dont l'exécution est automatisée par cron, vérifie périodiquement si les machines qui font partie du réseau local la passerelle offre l'accès à Internet avec des commandes pingUsage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
[-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
[-M mtu discovery hint] [-S sndbuf]
[-T timestamp option] [-Q tos] [hop1 ...] destination

Send ICMP ECHO_REQUEST to network hosts
. Si aucune des machines ne répond, alors le script lance l'extinction de la passerelle avec la commande shutdownUsage: shutdown [-akrhHPfnc] [-t secs] time [warning message]
Bring the system down
. Le script laissera donc la passerelle allumée si l'une des machines ayant une IP fixe est allumée, et ne tiendra pas compte d'éventuelles machines inconnues dont l'IP est allouée dynamiquement.

#!/bin/sh

# initial client status ##########################################

pcone=0
pctwo=0

echo "testoff log file : " >> /tmp/autopoweroff.log
date >> /tmp/autopoweroff.log

# test if clients are awake ######################################

if ping -c 1 192.168.1.2 | grep -E "round-trip min/avg/max" > /dev/null ; then
 pcone=1
 echo "pcone is up" >> /tmp/autopoweroff.log
fi

if ping -c 1 192.168.1.3 | grep -E "round-trip min/avg/max" > /dev/null ; then
 pctwo=1
 echo "pctwo is up" >> /tmp/autopoweroff.log
fi

# set action depending on the result of the test ################

echo $pcone
echo $pctwo

sleeping=$(($pcone+$pctwo))

case $sleeping in
0)
  echo "nobody using the gateway, shutting down..." >> /tmp/autopoweroff.log

  /bin/sh /root/scripts/sendreport.sh

  shutdown -hp now ;;
*)
  echo "someone is using the gateway, aborting..." >> /tmp/autopoweroff.log
  echo $sleeping >> /tmp/autopoweroff.log

esac

Améliorations

Eviter l'extinction de la passerelle si quelqu'un y est connecté

A l'usage de ce script, on se rend vite compte qu'il est assez ennuyeux lorsqu'on travaille directement sur la passerelle. En effet, si aucun autre PC n'est allumé, le script ordonnera l'extinction de la passerelle sans vous demander votre avis et sans vous laisser le temps de sauvegarder votre travail. La modification présentée ici permet de tester si quelqu'un est connecté à l'aide de la commande whoUsage: who [OPTION]... [ FICHIER | ARG1 ARG2]
Show who is logged on
.

#!/bin/sh

# initial client status ##########################################

loggedin=0
pcone=0
pctwo=0

echo "testoff log file : " >> /tmp/autopoweroff.log
date >> /tmp/autopoweroff.log

# test if someone is logged in ###################################

# "t" will be present if anyone is logged in locally or remotely
# because it is the common letter of the pts or tty string :

if who | grep -E "t" > /dev/null ; then
  loggedin=1
  echo "someone is logged in" >> /tmp/autopoweroff.log
fi

# test if clients are awake ######################################

if ping -c 1 192.168.1.2 | grep -E "round-trip min/avg/max" > /dev/null ; then
 pcone=1
 echo "pcone is up" >> /tmp/autopoweroff.log
fi

if ping -c 1 192.168.1.3 | grep -E "round-trip min/avg/max" > /dev/null ; then
 pctwo=1
 echo "pctwo is up" >> /tmp/autopoweroff.log
fi

# set action depending on the result of the test ################

echo $loggedin
echo $pcone
echo $pctwo

sleeping=$(($pcone+$pctwo))

case $sleeping in
0)
  echo "nobody using the gateway, shutting down..." >> /tmp/autopoweroff.log

  /bin/sh /root/scripts/sendreport.sh

  shutdown -hp now ;;
*)
  echo "someone is using the gateway, aborting..." >> /tmp/autopoweroff.log
  echo $sleeping >> /tmp/autopoweroff.log

esac

Notez un comportement assez intéressant : le script fonctionne aussi si on se connecte à distance par ssh et détecte également les screen détachés, ce qui donne un bon moyen d'inhiber l'extinction de la passerelle si besoin sans laisser de session ouverte à distance.

Eviter l'extinction de la passerelle lorsqu'elle vient d'être allumée

Un autre désagrément qu'on remarque parfois, si le délai du cron est faible et que les ordinateurs clients pcone et pctwo n'ont pas le temps de démarrer avant l'exécution du script. Par conséquent la passerelle s'éteindra avant que vous n'ayez eu le temps de démarrer vos PC. La modification décrite ce-après permet de ne pas éteindre la passerelle si cele-ci a été allumée depuis moins de X minutes, grâce à la commande uptimeUsage: uptime [-V]
-V display version
Tell how long the system has been running
.

#!/bin/sh

# initial client status ##########################################

loggedin=0
pcone=0
pctwo=0

echo "testoff log file : " >> /tmp/autopoweroff.log
date >> /tmp/autopoweroff.log

# test if someone is logged in ###################################

# "t" will be present if anyone is logged in locally or remotely
# because it is the common letter of the pts or tty string :

if who | grep -E "t" > /dev/null ; then
  loggedin=1
  echo "someone is logged in" >> /tmp/autopoweroff.log
fi

# test if clients are awake ######################################

if ping -c 1 192.168.1.2 | grep -E "round-trip min/avg/max" > /dev/null ; then
 pcone=1
 echo "pcone is up" >> /tmp/autopoweroff.log
fi

if ping -c 1 192.168.1.3 | grep -E "round-trip min/avg/max" > /dev/null ; then
 pctwo=1
 echo "pctwo is up" >> /tmp/autopoweroff.log
fi

# set action depending on the result of the test ################

echo $loggedin
echo $pcone
echo $pctwo

sleeping=$(($pcone+$pctwo))

case $sleeping in
0)
  echo "nobody using the gateway, shutting down..." >> /tmp/autopoweroff.log

  /bin/sh /root/scripts/sendreport.sh

  shutdown -hp now ;;
*)
  echo "someone is using the gateway, aborting..." >> /tmp/autopoweroff.log
  echo $sleeping >> /tmp/autopoweroff.log

esac

Documentation sous licence GNU/Free Documentation Licence version 1.2
http://www.gnu.org/copyleft/fdl.html
Christophe Eyquem