Vous êtes sur la page 1sur 31

Titre_100scripts 30/07/04 10:24 Page 1

100
scripts
shell UNIX
Dave Taylor

Groupe Eyrolles, 2004 pour l’édition française,


ISBN : 2-212-11483-4.
5
Administration système :
gérer les utilisateurs

Aucun système d’exploitation sophistiqué, qu’il s’agisse de Windows, Mac OS, ou Unix, ne
peut fonctionner seul et sans intervention humaine. Si vous avez installé un système Unix
multi-utilisateur, une personne est nécessairement chargée de son administration. Vous
ignorez peut-être l’existence de ce technicien discret en coulisses ou bien vous occupez ce
rôle d’expert tout-puissant responsable du bon fonctionnement du système. Un environne-
ment mono-utilisateur, comme Linux ou Mac OS X, requiert également la présence d’un
administrateur, que vous en soyez conscient ou non.
Mais soyez rassuré, les scripts shell, des plus simples aux plus complexes, sont notamment
destinés à faciliter la vie des administrateurs système Unix. D’ailleurs, certaines commandes
Unix sont en réalité des scripts shell. La plupart des tâches les plus simples, par exemple
l’ajout d’un nouvel utilisateur, l’analyse de l’utilisation du disque, la gestion des fichiers de
l’utilisateur « invité » (guest) peuvent être traitées par des scripts relativement courts, qui ne
présentent aucune difficulté.
En effet, vous serez probablement surpris de constater que la plupart des scripts d’administra-
tion système ne dépassent pas les 20 ou 30 lignes. Une simple ligne de commande calcule ces
statistiques pour un répertoire :

$ wc -l $(file /usr/bin/* | grep "script" | grep -v perl | cut -d: -f1) | \


sort -n | head -15

3 /usr/bin/bdftops
3 /usr/bin/font2c
100 scripts shell Unix
118

3 /usr/bin/gsbj
3 /usr/bin/gsdj
3 /usr/bin/gsdj500
3 /usr/bin/gslj
3 /usr/bin/gslp
3 /usr/bin/gsnd
4 /usr/bin/4odb
4 /usr/bin/4xslt
4 /usr/bin/krdb
5 /usr/bin/4rdf
5 /usr/bin/4xupdate
6 /usr/bin/checkXML
6 /usr/bin/kdb2html

Aucun des 15 scripts les plus courts du répertoire /usr/bin/ ne compte plus de 6 lignes. Et
avec ses 14 lignes, le script /usr/bin/mute de Red Hat Linux 9.0 illustre parfaitement les
atouts d’un petit script shell d’un point de vue utilisateur :

#! /bin/sh
# $Aumix: aumix/src/mute,v 1.1 2002/03/19 01:09:18 trevor Exp $
# Copyright (c) 2001, Ben Ford et Trevor Johnson
#
# Exécutez ce script pour passer en mode silencieux, puis à nouveau
# pour sortir du mode silencieux.
# Note: il écrasera les sauvegardes de vos réglages.
#
volumes=$(aumix -vq |tr -d ,)
if [ $(echo $volumes | awk '{print $2}') -ne 0 -o \
$(echo $volumes | awk '{print $3}') -ne 0 ]; then
aumix -S -v 0
else
aumix -L > /dev/null
fi
Copyright © 2004 Groupe Eyrolles

À l’instar de mute, les scripts proposés dans ce chapitre sont courts, utiles et se chargent de
nombreuses tâches administratives : ils facilitent les sauvegardes du système, ils indiquent les
services du système activés par inetd et xinetd, ils fournissent une interface conviviale à la
commande date en vue de la modification de la date et de l’heure courantes, ainsi qu’un outil
fort pratique permettant de valider les fichiers crontab.
Administration système : gérer les utilisateurs
CHAPITRE 5
119

N°39 – Analyser l’utilisation du disque


Malgré l’arrivée sur le marché de disques excessivement volumineux, dont le prix ne cesse de
baisser, les administrateurs système semblent contraints de surveiller leur utilisation en
permanence afin d’éviter toute saturation du système de fichiers.
La technique de contrôle la plus fréquente consiste à examiner le répertoire /users ou /home à
l’aide de la commande du afin de déterminer l’espace occupé sur le disque par tous les sous-
répertoires de l’arborescence étudiée, et de distinguer les cinq ou dix utilisateurs les plus gour-
mands. Malheureusement, cette approche ne tient pas compte de l’espace occupé par les utili-
sateurs à d’autres emplacements du ou des disques durs. Par conséquent, si certains d’entre
eux stockent des archives complémentaires sur un autre disque, ou si des petits malins conser-
vent des MPEG dans un répertoire caché (dont le nom commence par un point) sous /tmp ou
dans un répertoire inutilisé et ouvert par erreur de la zone ftp, ils ne sont pas détectés par cette
technique. C’est pourquoi l’analyse de l’arborescence /home n’est pas toujours une méthode
idéale si vous disposez de répertoires utilisateur répartis sur plusieurs périphériques (ou
disques).
Dans ce genre de situation, il est préférable d’extraire tous les noms des utilisateurs du fichier
/etc/passwd, puis de rechercher sur tous les disques tous les fichiers possédés par chaque
compte. Le script suivant illustre ce cas de figure.

Le code
#!/bin/sh

# fquota - Outil d'analyse des quotas disque pour Unix.


# Suppose que tous les identifiants utilisateur sont >= UID 100.

MAXDISKUSAGE=20

for name in $(cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99{print $1}')
do
echo -n "L'utilisateur $name dépasse son quota disque. Espace occupé: "
# Vous devrez peut-être modifier la liste de répertoires suivante pour
Copyright © 2004 Groupe Eyrolles

# mieux refléter la situation sur votre disque. Changement le plus


# probable: remplacer /Users par /home
find / /usr /var /Users -user $name -xdev -type f -ls | \
awk '{ sum += $7} END{ print sum / (1024*1024) " Mo"}'

done | awk "\$9 > $MAXDISKUSAGE{ print \$0}"

exit 0
100 scripts shell Unix
120

Dans le détail
Par convention, les identifiants utilisateur numérotés de 1 à 99 correspondent aux démons du
système et aux tâches administratives. Ce sont les comptes utilisateur qui commencent à partir
de 100. Les administrateurs système Unix sont généralement rigoureux, c’est pourquoi ce
script ignore tous les comptes d’identifiant inférieurs à 100.
L’argument -xdev passé à la commande find évite de parcourir tous les systèmes de fichiers,
et notamment les zones système, les répertoires source en lecture seule, les périphériques
amovibles, le répertoire /proc des processus en cours d’utilisation (sur Linux), et divers autres
emplacements similaires.
De prime abord, ce script semble générer le message de dépassement de quota disque pour
tous les comptes sans exception. Mais en fait, l’instruction awk qui suit la boucle laisse passer
ce message uniquement pour les comptes qui occupent plus de MAXDISKUSAGE (méga-octets),
cette valeur étant prédéfinie.

Exécuter le script
Ce script ne prend aucun argument et doit être exécuté en tant que root si vous souhaitez
accéder à tous les répertoires et systèmes de fichiers. Pour cela, faites appel à la commande
sudo (tapez man sudo pour en savoir plus) qui vous permet d’exécuter une commande en tant
que root, puis de retrouver ensuite votre statut d’utilisateur non privilégié. Chaque fois que
vous souhaitez exécuter une commande administrative, vous devez taper sudo. En revanche,
si vous saisissez su - root, vous vous octroyez le statut root pour toutes les commandes qui
suivent jusqu’à ce que vous quittiez le sous-shell ainsi appelé. Attention cependant, il est très
facile de se laisser distraire, d’oublier qu’on est root et de taper une commande aux consé-
quences désastreuses.

INFO Vous devrez probablement modifier les répertoires listés dans la commande find pour qu’ils
correspondent aux répertoires associés sur votre disque dur.

Les résultats
La durée d’exécution de ce script est particulièrement longue puisque celui-ci parcourt les
Copyright © 2004 Groupe Eyrolles

systèmes de fichiers. Si votre système est volumineux, vous aurez largement le temps de
prendre une tasse de café, voire de dîner en tête-à-tête avec votre moitié pendant l’opération.
Pour vous remercier de votre patience, le système vous fournira les résultats suivants :

$ sudo fquota
L'utilisateur linda dépasse son quota disque. Espace occupé: 39.7 Mo
L'utilisateur taylor dépasse son quota disque. Espace occupé: 21799.4 Mo

Vous pouvez constater que taylor bat tous les records avec ses 21 giga-octets ! Ouh le vilain !
Administration système : gérer les utilisateurs
CHAPITRE 5
121

Pour aller plus loin


Pour être complet, un script de ce type doit disposer d’un système automatisé d’envoi de cour-
riers électroniques pour prévenir le sans-gêne qu’il abuse des ressources communes. Cette
amélioration est mise en place dans le cadre du script suivant.

N°40 – Signaler les utilisations excessives du disque


La plupart des administrateurs système recherchent systématiquement les solutions les plus
simples. Dans le cas des quotas de disque, il s’agit de compléter le script n°39, fquota, pour
lui apprendre à envoyer directement des courriers électroniques d’avertissement aux utilisa-
teurs trop gourmands en espace disque.

Le code
#!/bin/sh

# diskhogs - Outil d'analyse des quotas disque pour Unix.


# Suppose que tous les identifiants utilisateur sont >= UID 100.
# Envoie un courrier électronique à chaque utilisateur qui abuse
# et fait un rapport de cela à l'écran.

MAXDISKUSAGE=20
violators="/tmp/diskhogs0.$$"

trap "/bin/rm -f $violators" 0

for name in $(cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99{ print $1}')
do
echo -n "$name "
# Vous devrez peut-être modifier la liste de répertoires suivante pour
# mieux refléter la situation sur votre disque. Changement le plus
# probable: remplacer /Users par /home
find / /usr /var /Users -user $name -xdev -type f -ls | \
Copyright © 2004 Groupe Eyrolles

awk '{ sum += $7} END{ print sum / (1024*1024)}'

done | awk "\$2 > $MAXDISKUSAGE{ print \$0}" > $violators

if [ ! -s $violators ] ; then
echo "Aucun utilisateur ne dépasse le quota disque de ${MAXDISKUSAGE} Mo"
exit 0
fi
100 scripts shell Unix
122

while read account usage ; do

cat << EOF | fmt | mail -s "Avertissement: $account dépasse le quota" $account
Vous occupez ${usage}Mo d'espace disque, mais n'avez droit qu'à
${MAXDISKUSAGE}Mo. Cela signifie que vous devez soit effacer certains
fichiers, soit compacter des fichiers (voyez pour cela «gzip» et
«bzip2», programmes de compactage puissants et faciles à utiliser),
soit nous présenter une demande argumentée d'augmentation d'espace
disque.

Merci pour votre compréhension.

Dave Taylor @ x554


EOF

echo "Le compte $account occupe $usage Mo d'espace disque. Utilisateur averti."

done < $violators

exit 0

Remarquez l’utilisation de la commande fmt dans le tube de commandes appelant le courrier


électronique :

cat << EOF | fmt | mail -s "Avertissement: $account depasse le quota" $account

D’un point de vue esthétique, les courriers électroniques automatiques sont rarement satisfai-
sants lorsque leur texte comprend des champs de taille inconnue, par exemple $account
(compte utilisateur). Dans le cas présent, la logique de la boucle for est légèrement différente
de celle mise en œuvre pour le script n°39, fquota. Ainsi, la sortie de cette boucle étant exclu-
sivement traitée par la deuxième partie du script, elle se contente d’afficher le nom du compte
utilisateur et son utilisation du disque à chaque cycle, plutôt qu’un message d’erreur signalant
Copyright © 2004 Groupe Eyrolles

le dépassement de quota disque.

Exécuter le script
À l’instar du script n°39, celui-ci ne prend aucun argument de démarrage et doit être exécuté
en tant que root pour produire des résultats précis. La solution la plus sûre consiste à utiliser
la commande sudo.
Administration système : gérer les utilisateurs
CHAPITRE 5
123

Les résultats
$ sudo diskhogs
Le compte linda occupe 39.7 Mo d'espace disque. Utilisateur averti.
Le compte taylor occupe 21799.5 Mo d'espace disque. Utilisateur averti.

Si nous consultons maintenant la boîte aux lettres du compte linda, nous constatons que le
message envoyé par le script vient d’arriver :

Subject: Avertissement: linda depasse le quota

Vous occupez 39.7Mo d'espace disque, mais n'avez droit qu'à 20Mo. Cela
signifie que vous devez soit effacer certains fichiers, soit compacter
des fichiers (voyez pour cela «gzip» et «bzip2», programmes de
compactage puissants et faciles à utiliser), soit nous présenter une
demande argumentée d'augmentation d'espace disque.

Merci pour votre compréhension.

Dave Taylor @ x554

Pour aller plus loin


Pour améliorer ce script, vous pouvez par exemple attribuer à certains utilisateurs des quotas
plus élevés. Pour cela, il suffit de mettre en place un fichier distinct dans lequel est défini le
quota de disque de chaque utilisateur. En outre, un quota par défaut peut être prévu pour les
utilisateurs qui ne font pas l’objet d’un traitement particulier et qui ne figurent donc pas dans
ce fichier d’accompagnement. Il suffit alors de demander au script d’inspecter le fichier
contenant les paires nom d’utilisateur/quota allouées via la commande grep, et d’extraire ce
second champ par un appel à cut -f2.

N°41 – Déterminer l’espace disque disponible


L’évaluation de l’espace disque disponible sur un système relève de la gestion des quotas de
Copyright © 2004 Groupe Eyrolles

disque. La commande df indique l’utilisation de chaque disque individuellement, mais la


sortie obtenue risque de vous surprendre :

$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hdb2 25695892 1871048 22519564 8% /
/dev/hdb1 101089 6218 89652 7% /boot
none 127744 0 127744 0% /dev/shm
100 scripts shell Unix
124

Il serait préférable d’utiliser une version de df capable d’évaluer les espaces libres disponibles
affichés dans la quatrième colonne, puis de présenter le résultat sous un format plus abor-
dable. Un jeu d’enfant pour notre script !

Le code
#!/bin/sh

# diskspace - fait le bilan de l'espace disque disponible et le présente


# sous une forme logique et lisible.

tempfile="/tmp/available.$$"

trap "rm -f $tempfile" EXIT

cat << 'EOF' > $tempfile


{ sum += $4}
END{ mb = sum / 1024
gb = mb / 1024
printf "%.0f Mo (%.2f Go) d'espace disque disponible\n", mb, gb
}
EOF

df -k | awk -f $tempfile

exit 0

Exécuter le script
Tous les utilisateurs peuvent appeler ce script et obtenir un résumé succinct, présenté sur une
ligne, de l’espace disque disponible.

Les résultats
Copyright © 2004 Groupe Eyrolles

Si vous exécutez ce script sur le même système que celui utilisé précédemment pour générer
la sortie de df, vous obtenez le résultat suivant :

$ diskspace
96199 Mo (93.94 Go) d'espace disque disponible
Administration système : gérer les utilisateurs
CHAPITRE 5
125

Pour aller plus loin


Si votre système dispose d’un espace important sur un certain nombre de disques qui offrent
plusieurs giga-octets, vous pouvez compléter ce script en lui faisant renvoyer, le cas échéant,
des valeurs exprimées en téra-octets. Si vous manquez d’espace, il est généralement dépri-
mant de voir s’afficher 0,03 Go d’espace disque disponible, mais cela devrait vous encourager
à utiliser le script n°40, diskhogs, et à faire un peu de ménage.
Vous devez également déterminer s’il est plus utile de connaître l’espace disque disponible
sur tous les périphériques, y compris sur les partitions qui ne peuvent pas augmenter, comme
boot, ou si les informations relatives aux volumes utilisateur suffisent. Si le deuxième cas de
figure vous convient, appelez grep juste après df. Vous pouvez utiliser grep avec le nom du
périphérique concerné ou bien filtrer les périphériques qui ne vous intéressent pas à l’aide de
l’option -v.

N°42 – Faciliter la lecture de la sortie df


Le script n°41 résume la sortie de la commande df, alors que celui-ci en facilite la lecture.
Bien que simple, cette amélioration est importante.

Le code
#!/bin/sh

# newdf - Version de df plus conviviale.

awkscript="/tmp/newdf.$$"

trap "rm -f $awkscript" EXIT

cat << 'EOF' > $awkscript


function showunit(size)
{ mb = size / 1024; prettymb=(int(mb * 100)) / 100;
gb = mb / 1024; prettygb=(int(gb * 100)) / 100;
Copyright © 2004 Groupe Eyrolles

if ( substr(size,1,1) ! "[0-9]" ||
substr(size,2,1) ! "[0-9]" ){ return size}
else if ( mb < 1){ return size "K"}
else if ( gb < 1){ return prettymb "M"}
else{ return prettygb "G"}
}

BEGIN{
100 scripts shell Unix
126

printf "%-27s %7s %7s %7s %8s %-s\n",


"Système de fichiers", "Taille", "Occupés", "Dispo.", "Capacité", "Monté
sur"
}

!/Filesystem/{

size=showunit($2);
used=showunit($3);
avail=showunit($4);

printf "%-27s %7s %7s %7s %8s %-s\n",


$1, size, used, avail, $5, $6
}
EOF

df -k | awk -f $awkscript

exit 0

Dans le détail
La partie la plus importante de ce programme se trouve dans un script awk. Il serait d’ailleurs
parfaitement envisageable d’écrire la totalité du script en awk et d’appeler df directement, via
la fonction system(). Voici un autre cas d’école pour le langage Perl, mais nous ne nous attar-
derons pas sur le sujet.
Ce script comporte également une astuce qui me vient de mes premiers pas en programma-
tion, quand je travaillais en langage BASIC :

prettymb=(int(mb * 100)) / 100;

Lorsque vous manipulez des valeurs numériques de précision arbitraire, vous pouvez rapide-
ment les tronquer après la virgule en les multipliant par une puissance de dix, en convertissant
Copyright © 2004 Groupe Eyrolles

le résultat obtenu en entier (afin d’éliminer la partie fractionnaire), puis en le divisant par la
même puissance de 10. Dans le cas présent, une valeur comme 7.085344324 est remplacée
par 7.08 ; le résultat parle de lui-même.

INFO Certaines versions de df disposent d’une option -h qui fournit un format de sortie similaire à
celui du script proposé ici. Ce dernier, à l’instar de nombreux autres programmes de cet ouvrage,
vous permet toutefois d’obtenir une sortie conviviale et plus lisible sur tous les systèmes Unix ou
Linux, quelle que soit la version de df installée. Ce script ne prend aucun argument et peut être
exécuté par tous les utilisateurs, root ou standards. Si vous ne souhaitez filtrer les périphéri-
ques mentionnés dans les rapports envoyés, utilisez grep -v après l’appel à df .
Administration système : gérer les utilisateurs
CHAPITRE 5
127

Les résultats
Les sorties standards de df sont loin d’être claires :

$ df
Filesystem 512-blocks Used Avail Capacity Mounted on
/dev/disk1s9 78157200 43187712 34457488 55% /
devfs 196 196 0 100% /dev
fdesc 2 2 0 100% /dev
<volfs> 1024 1024 0 100% /.vol
/dev/disk0s9 234419552 71863152 162556416 30% /Volumes/110GB

Ce nouveau script fait appel à awk pour faciliter la lecture des résultats :

$ newdf
Système de fichiers Taille Occupés Dispo. Capacité Monté sur
/dev/disk1s9 37.26G 20.59G 16.43G 55% /
devfs 98K 98K 0 100% /dev
fdesc 1 1 0 100% /dev
<volfs> 512K 512K 0 100% /.vol
/dev/disk0s9 111.77G 34.26G 77.51G 30% /Volumes/110GB

N°43 – Implémenter un locate sécurisé


Le programme locate proposé dans le cadre du script n°19 est pratique, mais il présente des
lacunes en matière de sécurité. En effet, si le processus de construction est exécuté par root,
la liste créée contient tous les fichiers et répertoires du système, quel que soit leur propriétaire.
Les utilisateurs sont ainsi autorisés à accéder à des répertoires et à des fichiers qui leur sont
théoriquement interdits. Vous pourriez également intervenir en tant que simple utilisateur
(c’est le cas sous Mac OS X, où la construction de cette base de données est effectuée par
nobody), mais solution n’est pas idéale : en tant qu’utilisateur, je souhaite retrouver tous les
fichiers de mon arborescence personnelle, que l’utilisateur nobody y ait accès ou non.
Pour résoudre ce dilemme, vous pouvez notamment spécifier davantage de renseignements
dans la base de données locate, en indiquant le propriétaire, le groupe et la chaîne de permis-
Copyright © 2004 Groupe Eyrolles

sions associés à chaque entrée. Dans ces conditions, la base de données mklocatedb n’est pas
sécurisée, sauf si le script locate est exécuté en tant que setuid ou setgid, ce qu’il faut éviter
à tout prix !
La solution de compromis consiste à mettre en place un fichier locatedb propre à chaque utili-
sateur. Lorsque l’utilisateur appelle ce fichier pour la première fois, le système crée un fichier
.locatedb dans son répertoire personnel et un job cron peut mettre à jour toutes les nuits les
fichiers .locatedb existants de façon à refléter l’état du système. Lors de la première exécu-
tion du script slocate, un message prévient l’utilisateur qu’il aura uniquement accès aux
fichiers publics. Dès le jour suivant (selon le calendrier de cron), cet utilisateur obtient des
résultats personnalisés.
100 scripts shell Unix
128

Deux scripts permettent de mettre en place un locate sécurisé : le constructeur de base de


données, mkslocatedb et l’outil de recherche à proprement parler, slocate :

#!/bin/sh
# mkslocatedb - Construit la base de données centrale de locate sous
# l'identité nobody, et explore simultanément le répertoire personnel
# de chaque utilisateur à la recherche d'un fichier .slocatedb. Si ce
# fichier est trouvé, une base de données personnelle et
# complémentaire sera créée pour cet utilisateur

locatedb="/var/locate.db"
slocatedb=".slocatedb"

if [ "$(whoami)" != "root" ] ; then


echo "$0: Erreur: il faut être root pour exécuter cette commande." >&2
exit 1
fi

if [ "$(grep '^nobody:' /etc/passwd)" = "" ] ; then


echo "$0: Erreur: il faut que le compte «nobody» existe" >&2
echo "pour créer la base de données par défaut pour slocate." >&2; exit 1
fi

cd / # évite les problèmes de permissions postérieurs à su

# Tout d'abord, on crée ou met à jour la base de données publique


su -fm nobody -c "find / -print" > $locatedb 2>/dev/null
echo "construction de la base de données par défaut pour slocate (utilisateur
nobody)"
echo ... le résultat fait $(wc -l < $locatedb) lignes de long.

# On parcourt maintenant les comptes des utilisateurs sur le système pour


# savoir qui dispose d'un fichier $slocatedb dans son répertoire personnel...
Copyright © 2004 Groupe Eyrolles

for account in $(cut -d: -f1 /etc/passwd)


do
homedir="$(grep "^${account}:" /etc/passwd | cut -d: -f6)"

if [ "$homedir" = "/" ] ; then


continue # on ne fait rien pour le répertoire racine
elif [ -e $homedir/$slocatedb ] ; then
echo "construction de la base de données slocate pour l'utilisateur $account"
su -m $account -c "find / -print" > $homedir/$slocatedb \
Administration système : gérer les utilisateurs
CHAPITRE 5
129

2>/dev/null
chmod 600 $homedir/$slocatedb
chown $account $homedir/$slocatedb
echo ... le résultat comporte $(wc -l < $homedir/$slocatedb) lignes.
fi
done

exit 0

Le script slocate est, quant à lui, l’interface utilisateur vers la base de données slocate :

#!/bin/sh
# slocate - Explore la base de données sécurisée slocatedb propre à
# l'utilisateur et recherche du motif spécifié. Si cette base de
# données n'existe pas, affiche un avertissement et en crée une. Si
# elle est vide, utilise celle du système à la place.

locatedb="/var/locate.db"
slocatedb="$HOME/.slocatedb"

if [ ! -e $slocatedb -o "$1" = "–explain" ] ; then


cat << "EOF" >&2
Avertissement: locate sécurisé utilise une base de données privée propre
à chaque utilisateur, et la vôtre n'a pas encore été créée. Jusqu'à ce
qu'elle apparaisse (probablement tard ce soir), je me contenterai
d'utiliser la base de données publique, qui renverra tous les fichiers
publiquement disponibles, plutôt que les fichiers explicitement
accessibles au compte ${USER:-$LOGNAME}.
EOF

if [ "$1" = "–explain" ] ; then


exit 0
fi
Copyright © 2004 Groupe Eyrolles

# Avant d'attaquer, on crée un fichier .slocatedb rempli par cron


# lors du prochain appel du script mkslocatedb
touch $slocatedb # mkslocatedb construira ceci la prochaine fois
chmod 600 $slocatedb # on part du bon pied avec les permissions

elif [ -s $slocatedb ] ; then


locatedb=$slocatedb
else
echo "Avertissement: j'utilise la base de données publique." >&2
100 scripts shell Unix
130

echo "Tapez «$0 –explain» pour en savoir plus." >&2


fi

if [ -z "$1" ] ; then
echo "Syntaxe: $0 motif" >&2; exit 1
fi

exec grep -i "$1" $locatedb

Dans le détail
Le script mkslocatedb repose sur le fait que l’utilisateur root est capable d’endosser temporai-
rement un autre identifiant utilisateur via la commande su -m utilisateur. La commande
find peut ainsi être exécutée sur le système de fichiers de chaque utilisateur, pour lequel est
créé une base de données de noms de fichier spécifique. Il est toutefois difficile de travailler
avec la commande su dans la mesure où, par défaut, celle-ci ne se contente pas de changer
d’identifiant utilisateur, mais importe également l’environnement du compte spécifié. Vous
obtenez des messages d’erreur étranges sur la plupart des Unix. Pour remédier au problème,
spécifiez l’option -m, qui évite l’importation de cet environnement utilisateur.
Vous constatez également la présence de la notation inhabituelle 2>/dev/null dans
mkslocatedb. Celle-ci route tous les messages d’erreur vers le cimetière des bits : tout ce qui
est renvoyé vers /dev/null disparaît sans laisser de traces. Vous échappez ainsi au flot de
messages d’erreur « permission denied » (permission refusée), messages invariablement
associés à chaque appel de la commande find.

Exécuter le script
Le script mkslocatedb est très particulier : il doit être exécuté en tant que root, mais sudo ne
peut pas vous aider ici. Vous devez vous connecter au système sous l’identifiant root avant
d’exécuter ce script ou avoir recours à la commande su, plus puissante. En revanche, le script
slocate n’est pas aussi contraignant. Copyright © 2004 Groupe Eyrolles

Les résultats
Sur une Red Hat Linux 10.0, la construction de la base de données slocate pour les utilisa-
teurs nobody (qui constituent la base de données publique) et taylor produit le résultat
suivant :

# mkslocatedb
construction de la base de données par défaut pour slocate (utilisateur nobody)
... le résultat fait 99809 lignes de long.
construction de la base de données slocate pour l'utilisateur taylor
... le résultat fait 99808 lignes de long.
Administration système : gérer les utilisateurs
CHAPITRE 5
131

La même commande exécutée sur un système Mac OS X bien rempli affiche ceci :

# mkslocatedb
construction de la base de données par défaut pour slocate (utilisateur nobody)
... le résultat fait 240160 lignes de long.
construction de la base de données slocate pour l'utilisateur taylor
... le résultat fait 263862 lignes de long.

Pour rechercher un fichier ou un ensemble de fichiers correspondant à un motif précis, nous


procédons d’abord sous l’identité de l’utilisateur tintin (qui ne dispose pas encore de fichier
.slocatedb) :

tintin $ slocate Taylor-Rapport.doc


Avertissement: j'utilise la base de données publique.
Tapez «slocate –explain» pour en savoir plus.
$

Tapons la même commande, mais en tant que taylor (utilisateur possédant le fichier
recherché) :

taylor $ slocate Taylor-Rapport.doc


/Users/taylor/Documents/Merrick/Taylor-Rapport.doc

Pour aller plus loin


Si votre système de fichiers est très volumineux, cette approche risque d’utiliser beaucoup
d’espace. Pour éviter ce problème, assurez-vous que les fichiers de bases de données person-
nels .slocatedb ne dupliquent pas les entrées présentes dans la base de données publique
centrale. Le traitement est alors plus complexe en amont (tri des deux fichiers avec sort, puis
appel à diff), mais le gain d’espace en vaut généralement la peine.
Toujours dans l’optique de réduire l’espace occupé, une seconde technique consiste à cons-
truire les fichiers .slocatedb en incluant uniquement les fichiers ouverts depuis la dernière
Copyright © 2004 Groupe Eyrolles

mise à jour. Cette méthode fonctionne d’autant mieux que le script mkslocatedb est exécuté
toutes les semaines plutôt que quotidiennement. Si tel n’était pas le cas, tous les utilisateurs
reviendraient au point de départ chaque lundi, puisqu’ils exécutent rarement la commande
slocate pendant le week-end.
En dernier lieu, il est également possible de compacter les fichiers .slocatedb, puis de les
décompacter à la volée lors d’une recherche avec slocate. Pour cela, inspirez-vous de la
commande zgrep du script n°37.
100 scripts shell Unix
132

N°44 – Ajouter des utilisateurs au système


Si vous êtes responsable d’un réseau de machines Unix et Linux, vous n’êtes pas sans
connaître les incompatibilités subtiles entre ces systèmes. Les tâches d’administration les plus
simples sont parfois les plus éloignées d’un Unix à l’autre, la gestion des comptes utilisateur
remportant la palme en la matière. En effet, chaque fabricant a mis en place sa propre interface
graphique, capable de prendre en compte les particularités et les manies de son propre Unix,
au lieu d’utiliser une interface en ligne de commande cohérente d’un système à l’autre.
Bien que le protocole SNMP (Simple Network Management Protocol) ait clairement eu pour
objectif la normalisation de ce type d’implémentation, la gestion des utilisateurs est aussi
difficile qu’il y a dix ans, surtout dans les environnements informatiques hétérogènes. C’est
pourquoi la trousse à outils de chaque administrateur système doit impérativement comporter
une version personnalisée des scripts adduser (ajouter un utilisateur), deleteuser (supprimer
un utilisateur) et suspenduser (suspendre un utilisateur).

INFO Mac OS X se fait remarquer !


Mac OS X est l’exception qui confirme la règle puisqu’il repose sur une base de données de
comptes nommée NetInfo. Le chapitre 11 propose une version de ces outils pour Mac OS X.

Sur un système Unix, vous créez un compte utilisateur en ajoutant une seule entrée au fichier
/etc/passwd. Cette ligne attribue un nom de compte utilisateur composé de un à huit carac-
tères, un identifiant utilisateur unique, un identifiant de groupe, un répertoire personnel et un
shell de connexion (login shell). Les systèmes Unix modernes stockent la valeur chiffrée du
mot de passe dans le fichier /etc/shadow, où vous créez également une entrée pour l’utili-
sateur concerné. En dernier lieu, il est nécessaire d’inclure ce nouveau compte dans le fichier
/etc/group, en attribuant à l’utilisateur son propre groupe (stratégie récente implémentée dans
ce script) ou en l’ajoutant à un groupe existant.

Le code
#! /bin/sh
# adduser - Ajoute un nouvel utilisateur au système, en pensant à
# construire son répertoire personnel, à y copier les données de
Copyright © 2004 Groupe Eyrolles

# configuration par défaut, etc.

# Script valable pour un système Unix/Linux standard, pas pour Mac OS X.

pwfile="/etc/passwd" shadowfile="/etc/shadow"
gfile="/etc/group"
hdir="/home"

if [ "$(whoami)" != "root" ] ; then


Administration système : gérer les utilisateurs
CHAPITRE 5
133

echo "Erreur: il faut être root pour exécuter cette commande." >&2
exit 1
fi

echo "Ajout d'un compte utilisateur sur $(hostname)"


echo -n "login: " ; read login

# Remplacez «5000» par la valeur maximale des identifiants


# utilisateur sur votre système. Certains comptes système occupent en
# effet les uid 65535 etc.

uid="$(awk -F: '{ if (big < $3 && $3 < 5000) big=$3} END{ print big + 1}'
$pwfile)"
homedir=$hdir/$login

# On attribue à chaque utilisateur son propre groupe, donc gid=uid


gid=$uid

echo -n "nom complet: " ; read fullname


echo -n "shell: " ; read shell

echo "Mise en place du compte $login pour $fullname..."

echo ${login}:x:${uid}:${gid}:${fullname}:${homedir}:$shell >> $pwfile


echo ${login}:*:11647:0:99999:7::: >> $shadowfile

echo "${login}:x:${gid}:$login" >> $gfile

mkdir $homedir
cp -R /etc/skel/.[a-zA-Z]* $homedir
chmod 755 $homedir
find $homedir -print | xargs chown ${login}:${login}

# Mise en place d'un mot de passe initial


Copyright © 2004 Groupe Eyrolles

passwd $login

exit 0

Dans le détail
La ligne la plus intéressante de ce script contient le code suivant :

awk -F: '{ if (big < $3 && $3 < 5000) big=$3} END{ print big + 1}' $pwfile
100 scripts shell Unix
134

Elle analyse le fichier /etc/passwd, vérifie si l’identifiant utilisateur le plus élevé est inférieur
à la valeur maximale autorisée (paramétrée selon vos préférences). Elle incrémente ensuite
cette valeur pour obtenir l’identifiant du nouveau compte utilisateur. L’administrateur n’a
plus besoin de garder en mémoire le prochain identifiant disponible. La cohérence des infor-
mations de compte est ainsi assurée, quelle que soit l’évolution de la communauté des utilisa-
teurs.
Le nouveau répertoire personnel est créé après le compte et le répertoire /etc/skel y est
dupliqué. Par convention, ce nouveau répertoire contient les versions maîtres des fichiers
.cshrc, .login, .bashrc et .profile. Si le serveur Web de votre site propose le service
~compte, il est nécessaire de copier un répertoire comme /etc/skel/public_html pour l’utili-
sateur afin de couper court à toute question du type « Où dois-je créer mon nouveau site
Web ? ».

Exécuter le script
Ce script doit être exécuté en tant que root et ne prend aucune option au démarrage.

Les résultats
Mon système dispose déjà d’un compte tintin, mais je dois m’assurer que milou a également
accès à cette machine :

$ sudo adduser
Ajout d'un compte utilisateur sur aurora
login: milou
nom complet: Milou le chien
shell: /bin/bash
Mise en place du compte milou pour Milou le chien...
Changing password for user milou.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Copyright © 2004 Groupe Eyrolles

Pour aller plus loin


Lorsque vous implémentez votre propre script adduser, vous évitez que tout ajout de code ou
changement dans la logique interne des scripts standards ne soient écrasés par une mise à jour
du système. Par exemple, chaque modification locale pourrait entraîner l’envoi automatique
d’un courrier électronique de bienvenue soulignant les lignes de conduite à adopter locale-
ment et indiquant des sources de documentation. Vous pouvez également demander l’impres-
sion automatique d’une feuille d’informations sur le compte, puis son envoi à l’utilisateur, ou
bien l’ajout d’un alias Prenom_Nomfamille ou Prenom.Nomfamille au fichier aliases du cour-
Administration système : gérer les utilisateurs
CHAPITRE 5
135

rier électronique. Rien ne vous empêche non plus de définir la copie des fichiers dans ce
compte pour que le propriétaire soit immédiatement opérationnel dans le cadre d’un projet
d’équipe.

N°45 – Suspendre un compte utilisateur


Dans le cadre de votre activité, vous êtes certainement amené à désactiver des comptes utili-
sateur sans pour autant les supprimer du système : quand un utilisateur est raccompagné à la
porte par les agents de sécurité pour acte d’espionnage industriel, quand un étudiant part en
vacances pour l’été, quand un sous-traitant interrompt temporairement son contrat, etc.
Vous pouvez alors procéder le plus simplement du monde, en remplaçant le mot de passe de
l’utilisateur par une nouvelle valeur qu’il ne connaît pas. Si cet utilisateur est encore connecté,
veillez à le déconnecter de force et à couper l’accès à son répertoire personnel depuis les
autres comptes du système. Vous devez vous assurer qu’il n’a plus aucun moyen d’accéder au
système.
Ce script vérifie essentiellement si l’utilisateur est connecté. Le cas échéant, il est informé de
sa déconnexion imminente, puis expulsé du système.

Le code
#!/bin/sh
# suspenduser - Suspend un compte utilisateur jusqu'à nouvel ordre.

homedir="/home" # répertoire personnel des utilisateurs


secs=10 # délai d'attente avant déconnexion de l'utilisateur

if [ -z $1 ] ; then
echo "Syntaxe: $0 compte" >&2 ;
exit 1
elif [ "$(whoami)" != "root" ] ; then
echo "Erreur. Il faut être root pour exécuter cette commande." >&2; exit 1
fi
Copyright © 2004 Groupe Eyrolles

echo "Veuillez fournir un nouveau mot de passe pour le compte $1."


passwd $1

# Il est temps de voir si cet utilisateur est connecté, et le cas


# échéant, de l'éjecter du système
if who|grep "$1" > /dev/null ; then

tty="$(who | grep $1 | tail -1 | awk '{print $2}')"


100 scripts shell Unix
136

cat << "EOF" > /dev/$tty


*************************************************************
MESSAGE URGENT DE L'ADMINISTRATEUR:

Ce compte va être suspendu à la demande de la direction.


Vous serez déconnecté dans $secs secondes. Veuillez quitter
immédiatement tout processus en cours d'exécution et vous
déconnecter.

Si vous avez des questions, contactez votre supérieur ou Jean


Dupont, responsable du service informatique.
*************************************************************
EOF

echo "(averti $1, j'attends maintenant $secs secondes)"

sleep $secs

jobs=$(ps -u $1 | cut -d\ -f1)

kill -s HUP $jobs # on envoie le signal de fin aux


# processus de cet utilisateur
sleep 1 # on leur laisse une seconde...
kill -s KILL $jobs > /dev/null 2>1 # et on tue tout ce qui reste

echo "$1 était connecté. Il vient d'être déconnecté."


fi

# Fermons enfin ce répertoire personnel aux yeux indiscrets


chmod 000 $homedir/$1

echo "Le compte $1 a été suspendu."


exit 0
Copyright © 2004 Groupe Eyrolles

Dans le détail
Ce script ne présente aucune difficulté : le mot de passe de l’utilisateur est remplacé par une
nouvelle valeur que celui-ci ne connaît pas. Si l’utilisateur est connecté, il dispose de quelques
secondes pour fermer ses applications avant d’être expulsé du système via l’arrêt de tous ses
processus actifs. Enfin, son répertoire personnel est désactivé.
Remarquez la séquence qui consiste à envoyer le signal SIGHUP (HUP) à tous les processus en
cours d’exécution pour l’utilisateur : il s’agit du signal d’alerte. Une seconde plus tard, le
Administration système : gérer les utilisateurs
CHAPITRE 5
137

signal SIGKILL (KILL), plus agressif, est envoyé. Le signal SIGHUP met généralement fin aux
applications en cours d’exécution, bien que cela ne soit pas systématiquement le cas. En
revanche, il n’affecte absolument pas un shell de connexion. Quant au signal SIGKILL, il ne
peut pas être ignoré, ni bloqué par un programme Unix actif ; il est donc efficace à 100 %.
Toutefois, dans ce cas, l’application n’a pas le temps de nettoyer ses fichiers temporaires et de
vider ses tampons de fichiers afin de s’assurer que les modifications sont consignées sur le
disque, etc.
La réactivation d’un utilisateur se déroule simplement en deux étapes : réouverture du réper-
toire personnel (avec la commande chmod 700), affectation d’un nouveau mot de passe (via
passwd) qui est communiqué à l’utilisateur concerné.
Ce script doit être exécuté en tant que root et prend pour seul argument le nom du compte
utilisateur à suspendre.

Les résultats
Milou a violé les règles du système, nous sommes contraints de suspendre son compte :

$ sudo suspenduser milou


Veuillez fournir un nouveau mot de passe pour le compte milou.
Changing password for user milou.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
(averti milou, j'attends maintenant 10 secondes)
milou était connecté. Il vient d'être déconnecté.
Le compte milou a été suspendu.

Milou était encore connecté. Il a vu apparaître le message suivant sur son écran quelques
secondes avant d’être éjecté du système :

*************************************************************
MESSAGE URGENT DE L'ADMINISTRATEUR:
Copyright © 2004 Groupe Eyrolles

Ce compte va être suspendu à la demande de la direction.


Vous serez déconnecté dans 10 secondes. Veuillez quitter
immédiatement tout processus en cours d'exécution et vous
déconnecter.

Si vous avez des questions, contactez votre supérieur ou Jean


Dupont, responsable du service informatique.
*************************************************************
100 scripts shell Unix
138

N°46 – Supprimer un compte utilisateur


La suppression d’un compte est légèrement plus complexe que sa suspension puisque le script
doit examiner l’ensemble des disques afin de rechercher les fichiers appartenant à l’utilisateur
concerné. En outre, cette étape doit être effectuée avant la suppression des informations asso-
ciées au compte des fichiers /etc/passwd et /etc/shadow.

Le code
#!/bin/sh

# deleteuser - Détruit totalement un compte utilisateur.


# Ne pas utiliser avec Mac OS X

homedir="/home"
pwfile="/etc/passwd" shadow="/etc/shadow"
newpwfile="/etc/passwd.new" newshadow="/etc/shadow.new"
suspend="/usr/local/bin/suspenduser"
locker="/etc/passwd.lock"

if [ -z $1 ] ; then
echo "Syntaxe: $0 compte" >&2; exit 1
elif [ "$(whoami)" != "root" ] ; then
echo "Erreur. Il faut être root pour exécuter cette commande." >&2; exit 1
fi

$suspend $1 # on suspend le compte avant d'attaquer le sale boulot

uid="$(grep -E "^${1}:" $pwfile | cut -d: -f3)"

if [ -z $uid ] ; then
echo "Erreur: aucun compte $1 trouvé dans $pwfile" >&2; exit 1
fi
Copyright © 2004 Groupe Eyrolles

# On détruit ce compte des fichiers password et shadow


grep -vE "^${1}:" $pwfile > $newpwfile
grep -vE "^${1}:" $shadow > $newshadow

lockcmd="$(which lockfile)" # cherche l'application lockfile dans le PATH


if [ ! -z $lockcmd ]; then # utilisons le lockfile du système
eval $lockcmd -r 15 $locker
else # il faut tout faire soi-même!
while [ -e $locker ]; do
Administration système : gérer les utilisateurs
CHAPITRE 5
139

echo "j'attends le fichier de mots de passe"; sleep 1


done
touch $locker # mise en place d'un verrou par fichier
fi

mv $newpwfile $pwfile
mv $newshadow $shadow
rm -f $locker # clac! le verrou est levé

chmod 644 $pwfile


chmod 400 $shadow

# Il s'agit maintenant de détruire le répertoire personnel et de trouver


# tout ce qui traîne...
rm -rf $homedir/$1

echo "Fichiers restant à détruire (le cas échéant):"


find / -uid $uid -print 2>/dev/null | sed 's/^/ /'

echo ""
echo "Le compte $1 (uid $uid) a été détruit, ainsi que son"
echo "répertoire personnel ($homedir/$1)."

exit 0

Pour éviter tout problème dans la mesure où le compte est en cours de modification,
deleteuser commence par suspendre le compte utilisateur en appelant suspenduser.
Avant de modifier le fichier de mots de passe, ce script le verrouille via le programme
lockfile, s’il est disponible. Si tel n’est pas le cas, le script a recours à un mécanisme de
verrouillage relativement primitif et crée le fichier /etc/passwd.lock. Lorsque ce fichier
existe déjà, le script attend qu’un autre programme le détruise, après quoi il le crée à nouveau
immédiatement et poursuit le processus.
Copyright © 2004 Groupe Eyrolles

Exécuter le script
Ce script est exécuté en tant que root (via sudo) et requiert le nom du compte à effacer en
argument de ligne de commande.

INFO Danger !
Ce script a une action irréversible et détruit de nombreux fichiers ; une prudence extrême
s’impose donc lorsque vous le testez !
100 scripts shell Unix
140

Les résultats
$ sudo deleteuser milou
Veuillez fournir un nouveau mot de passe pour le compte milou.
Changing password for user milou.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Le compte milou a été suspendu.
Fichiers restant à détruire (le cas échéant):
/var/log/nonosse.avi

Le compte milou (uid 502) a été détruit, ainsi que son


répertoire personnel (/home/milou).

Ce petit malin avait caché un fichier AVI (nonosse.avi) sous /var/log. Nous avons fort
heureusement remarqué sa présence ; qui sait ce qu’il pouvait contenir ?

Pour aller plus loin


Le script deleteuser est volontairement incomplet. Chaque administrateur système peut ainsi
choisir les mesures à mettre en œuvre : le compactage et l’archivage d’une copie des fichiers
du compte détruit, leur sauvegarde sur bande, leur gravage sur CD-Rom, ou encore leur envoi
aux services secrets (je plaisante... enfin, je l’espère). Vous devez encore supprimer ce compte
des fichiers /etc/group. Si des fichiers se trouvent hors du répertoire personnel de l’utilisa-
teur, la commande find est capable de les retrouver. Cependant, il incombe à l’administrateur
de les effacer ou non, au cas par cas.

N°47 – Valider l’environnement utilisateur


Dans la mesure où les utilisateurs ont tendance à migrer leurs fichiers .login, .profile, ainsi
que diverses autres personnalisations de leur environnement shell, d’un système à l’autre, ces
paramètres sont parfois partiellement erronés. Vous pouvez, par exemple, trouver un PATH
Copyright © 2004 Groupe Eyrolles

composé de répertoires absents du système, un PAGER qui pointe vers un binaire inexistant, et
pire encore.
Une solution relativement élaborée consiste à contrôler en premier lieu le PATH afin de vérifier
qu’il comporte uniquement des répertoires présents sur le système. Le script peut ensuite
examiner chaque paramètre des applications d’appui principales pour savoir s’il indique un
nom de fichier absolu, présent sur le système, ou un binaire du PATH.
Administration système : gérer les utilisateurs
CHAPITRE 5
141

Le code
#!/bin/sh
# validator - Vérifie que le PATH ne contient que des répertoires
# existants, puis contrôle la validité des variables d'environnement
# SHELL, HOME, PATH, EDITOR, MAILER, et PAGER.

errors=0

in_path()
{
# Étant donné une commande et le PATH, tente de trouver la commande.
# Renvoie 1 si elle est découverte, renvoie 0 dans le cas contraire.
# Attention, ceci modifie temporairement le séparateur de champs en
# entrée (IFS), mais le remet en place à la fin.

oldIFS=$IFS; IFS=":"

for directory in $path


do
if [ -x $directory/$cmd ] ; then
retval=1 # si on est ici, c'est qu'on a trouvé $cmd dans $directory
fi
done
IFS=$oldIFS
return $retval
}

validate()
{
varname=$1 varvalue=$2

if [ ! -z $varvalue ] ; then
if [ "${varvalue%${varvalue#?}}" = "/" ] ; then
Copyright © 2004 Groupe Eyrolles

if [ ! -x $varvalue ] ; then
echo "** $varname a la valeur $varvalue, mais je ne trouve pas cet
exécutable."
errors=$(( $errors + 1 ))
fi
else
if in_path $varvalue $PATH ; then
echo "** $varname a la valeur $varvalue, mais je ne la trouve pas dans le PATH."
errors=$(( $errors + 1 ))
100 scripts shell Unix
142

fi
fi
fi
}

####### Début du script à proprement parler #######

if [ ! -x ${SHELL:?"Je ne peux pas travailler sans définition de SHELL."} ] ; then


echo "** SHELL a la valeur $SHELL, mais je ne trouve pas cet exécutable."
errors=$(( $errors + 1 ))
fi

if [ ! -d ${HOME:?"Il faut que la variable HOME indique votre répertoire


personnel"} ]
then
echo "** HOME a la valeur $HOME, mais ce n'est pas un répertoire."
errors=$(( $errors + 1 ))
fi

# Notre premier test intéressant: tous les chemins du PATH sont-ils valides?

oldIFS=$IFS; IFS=":" # IFS est le séparateur de champs. Nous utiliserons ici «:»

for directory in $PATH


do
if [ ! -d $directory ] ; then
echo "** Le PATH comporte le répertoire incorrect $directory"
errors=$(( $errors + 1 ))
fi
done

IFS=$oldIFS # on remet en place l'ancienne valeur pour le reste du script

# Les variables suivantes doivent correspondre chacune à un chemin


Copyright © 2004 Groupe Eyrolles

# absolu, mais elles ne sont pas nécessairement définies ou ne contiennent pas


# toujours un nom de programme.

# Ajoutez d'autres variables en fonction de votre site et de votre


# communauté d'utilisateurs.

validate "EDITOR" $EDITOR


validate "MAILER" $MAILER
validate "PAGER" $PAGER
Administration système : gérer les utilisateurs
CHAPITRE 5
143

# La fin dépend du nombre d'erreurs rencontrées (0 ou plus?)

if [ $errors -gt 0 ] ; then


echo "Des erreurs se sont produites."
echo "Voyez l'administrateur système pour en savoir plus."
else
echo "Votre environnement semble correct."
fi

exit 0

Dans le détail
Les tests effectués par ce script ne sont pas excessivement complexes. Pour savoir si tous les
répertoires du PATH sont valides, le code les parcourt un à un et vérifie leur existence. Notez
que le séparateur interne de champs (internal field separator ou IFS) se voit affecter la valeur
d’un caractère deux-points (:), permettant ainsi au script de parcourir correctement tous les
répertoires du PATH. Par convention, cette variable utilise ce caractère pour séparer les réper-
toires, comme indiqué ci-après :

$ echo $PATH
/bin/:/sbin:/usr/bin:/sw/bin:/usr/X11R6/bin:/usr/local/mybin

Pour valider les valeurs des variables d’environnement, la fonction validate() commence par
examiner si elles commencent par une barre de division (slash ou /). Si tel est le cas, la fonc-
tion vérifie si cette variable est un exécutable. Lorsque la valeur ne commence pas par un
slash, le script appelle la fonction in_path() afin de contrôler si le programme se trouve dans
l’un des répertoires du PATH actuel.
Ce script se distingue notamment par son utilisation de valeurs par défaut pour certaines
conditionnelles et du fractionnement des variables. Les valeurs par défaut sont intégrées de la
façon suivante dans les conditionnelles :
Copyright © 2004 Groupe Eyrolles

if [ ! -x ${SHELL:?"Je ne peux pas travailler sans définition de SHELL."} ] ; then

La notation ${var:?"messageErreur"} signifie : si nom_var existe, utiliser sa valeur ; dans le


cas contraire, faire échouer via l’erreur « messageErreur ».
La notation du fractionnement des variables, ${var%${var#?}} est la fonction de sous-chaîne
de la norme POSIX. Elle produit uniquement le premier caractère de la variable var. Dans le
cas présent, elle permet de vérifier si une variable d’environnement est un chemin de fichier
absolu valide (commence par un slash / et spécifie le chemin vers un binaire).
100 scripts shell Unix
144

Si votre version d’Unix ou de Linux ne comprend aucune de ces notations, vous pouvez les
remplacer simplement. Ainsi, il est possible de substituer ce qui suit à ${SHELL:?Pas de
shell} :

if [ -z $SHELL ] ; then
echo "Pas de shell" >&2; exit 1
fi

Quant à la notation {var%${var#?}}, elle peut être remplacée par le code suivant ; vous
obtenez alors un résultat identique :

$(echo $var | cut -c1)

Exécuter le script
Ce code est exécuté par les utilisateurs afin de vérifier l’environnement. Il n’accepte aucun
argument de ligne de commande.

Les résultats
$ validator
** Le PATH comporte le répertoire incorrect /usr/local/mybin
** MAILER a la valeur /usr/local/bin/elm, mais je ne trouve pas cet exécutable.
Des erreurs se sont produites.
Voyez l'administrateur système pour en savoir plus.

N°48 – Nettoyer après le départ des invités


Bien que de nombreux sites désactivent le compte guest pour des raisons de sécurité, d’autres
proposent ce compte, généralement associé à un mot de passe très facile à deviner, afin de
permettre aux employés d’autres services d’accéder au réseau. Bien qu’utile, ce compte
présente un inconvénient majeur : chaque utilisateur effectue ses propres expériences (test de
diverses commandes, édition de fichiers .rc, ajout de sous-répertoires, etc.) et certains ne se
gênent pas pour laisser un véritable capharnaüm à l’utilisateur suivant.
Copyright © 2004 Groupe Eyrolles

Ce script résout le problème en nettoyant l’espace du compte guest chaque fois qu’un utilisa-
teur le quitte. Il efface donc tout fichier ou sous-répertoire créé sous ce compte et détruit
également tous les fichiers cachés (dont le nom commence par un point). En dernier lieu, il
reconstruit les fichiers officiels du compte à partir de leur copie stockée dans une archive en
lecture seule placée dans le répertoire ..template du compte.
Administration système : gérer les utilisateurs
CHAPITRE 5
145

Le code
#!/bin/sh

# fixguest - Nettoie le compte «guest» lors du processus logout.

# Ne fait pas confiance aux variables d'environnement.


# Seules les sources en lecture seule sont référencées.

iam=$(whoami)
myhome="$(grep "^${iam}:" /etc/passwd | cut -d: -f6)"

# *** NE PAS exécuter ce script depuis un compte utilisateur normal!

if [ "$iam" != "guest" ] ; then


echo "Erreur: c'est une très mauvaise idée d'exécuter fixguest sur ce compte."
>&2
exit 1
fi

if [ ! -d $myhome/..template ] ; then
echo "$0: je n'ai pas trouvé le répertoire de patrons pour la reconstruction."
>&2
exit 1
fi

# Détruit tous les fichiers et répertoires du répertoire personnel

cd $myhome

rm -rf * $(find . -name ".[a-zA-Z0-9]*" -print)

# Il ne devrait maintenant plus y rester que le répertoire ..template


cp -Rp ..template/* .
Copyright © 2004 Groupe Eyrolles

exit 0

Dans le détail
Pour que ce script fonctionne correctement, vous devez mettre en place un ensemble de
fichiers et de répertoires patrons qui serviront de référence. Vous les insérez ensuite dans le
sous-répertoire ..template du compte utilisateur. Ce dernier contient des permissions en
lecture seule ; assurez-vous qu’il comporte uniquement des fichiers et répertoires qui appar-
tiennent à l’utilisateur guest.
100 scripts shell Unix
146

Exécuter le script
Le script fixguest est logiquement exécuté lors de la déconnexion. Il est appelé depuis le
fichier .logout, opération qui fonctionne avec la plupart des shells, mais pas tous. Pour couper
court à d’inévitables protestations de la part des utilisateurs, le script de connexion peut les
prévenir comme suit :

Avertissement: tous les fichiers présents dans le compte «guest» seront


détruits à la déconnexion. Ne stockez ici aucun fichier dont vous ayez
besoin. Si vous souhaitez sauvegarder quelque chose, envoyez-le par
courrier électronique à votre compte principal. Vous êtes prévenu!

Certains invités seront probablement suffisamment rusés pour modifier le script .logout. Le
cas échéant, appelez aussi le script fixguest depuis l’ordonnanceur de tâches cron. Assurez-
vous simplement, lors de son exécution, que personne n’est connecté à ce compte !

Les résultats
Ce programme ne produit aucun résultat visible, à ceci près que le répertoire personnel de
l’invité est restauré avec la structure et les fichiers de son sous-répertoire ..template.

Copyright © 2004 Groupe Eyrolles