31
100 scripts shell UNIX Dave Taylor Groupe Eyrolles, 2004 pour l’édition française, ISBN : 2-212-11483-4.

Titre 100scripts 30/07/04 10:24 Page 1 100 - Accueil - Librairie …€¦ ·  · 2004-09-02destinés à faciliter la vie des administrateurs système Unix. D’ailleurs, ... Une

Embed Size (px)

Citation preview

100scripts

shell UNIXD a v e T a y l o r

Titre_100scripts 30/07/04 10:24 Page 1

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

ISBN : 2-212-11483-4.

5Administration système :

gérer les utilisateurs

Aucun système d’exploitation sophistiqué, qu’il s’agisse de Windows, Mac OS, ou Unix, nepeut fonctionner seul et sans intervention humaine. Si vous avez installé un système Unixmulti-utilisateur, une personne est nécessairement chargée de son administration. Vousignorez peut-être l’existence de ce technicien discret en coulisses ou bien vous occupez cerô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’unadministrateur, que vous en soyez conscient ou non.

Mais soyez rassuré, les scripts shell, des plus simples aux plus complexes, sont notammentdestinés à faciliter la vie des administrateurs système Unix. D’ailleurs, certaines commandesUnix sont en réalité des scripts shell. La plupart des tâches les plus simples, par exemplel’ajout d’un nouvel utilisateur, l’analyse de l’utilisation du disque, la gestion des fichiers del’utilisateur « invité » (guest) peuvent être traitées par des scripts relativement courts, qui nepré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 cesstatistiques 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 Unix118

Copyright ©

2004 Groupe E

yrolles

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

À l’instar de mute, les scripts proposés dans ce chapitre sont courts, utiles et se chargent denombreuses tâches administratives : ils facilitent les sauvegardes du système, ils indiquent lesservices du système activés par inetd et xinetd, ils fournissent une interface conviviale à lacommande date en vue de la modification de la date et de l’heure courantes, ainsi qu’un outilfort pratique permettant de valider les fichiers crontab.

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

#! /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

Administration système : gérer les utilisateursCHAPITRE 5

119

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

N°39 – Analyser l’utilisation du disqueMalgré l’arrivée sur le marché de disques excessivement volumineux, dont le prix ne cesse debaisser, les administrateurs système semblent contraints de surveiller leur utilisation enpermanence 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’entreeux 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 oudans un répertoire inutilisé et ouvert par erreur de la zone ftp, ils ne sont pas détectés par cettetechnique. C’est pourquoi l’analyse de l’arborescence /home n’est pas toujours une méthodeidéale si vous disposez de répertoires utilisateur répartis sur plusieurs périphériques (oudisques).

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 chaquecompte. 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 # 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 Unix120

Copyright ©

2004 Groupe E

yrolles

Dans le détailPar convention, les identifiants utilisateur numérotés de 1 à 99 correspondent aux démons dusystème et aux tâches administratives. Ce sont les comptes utilisateur qui commencent à partirde 100. Les administrateurs système Unix sont généralement rigoureux, c’est pourquoi cescript 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ériquesamovibles, le répertoire /proc des processus en cours d’utilisation (sur Linux), et divers autresemplacements similaires.

De prime abord, ce script semble générer le message de dépassement de quota disque pourtous les comptes sans exception. Mais en fait, l’instruction awk qui suit la boucle laisse passerce message uniquement pour les comptes qui occupent plus de MAXDISKUSAGE (méga-octets),cette valeur étant prédéfinie.

Exécuter le scriptCe script ne prend aucun argument et doit être exécuté en tant que root si vous souhaitezaccéder à tous les répertoires et systèmes de fichiers. Pour cela, faites appel à la commandesudo (tapez man sudo pour en savoir plus) qui vous permet d’exécuter une commande en tantque root, puis de retrouver ensuite votre statut d’utilisateur non privilégié. Chaque fois quevous 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 quisuivent jusqu’à ce que vous quittiez le sous-shell ainsi appelé. Attention cependant, il est trèsfacile de se laisser distraire, d’oublier qu’on est root et de taper une commande aux consé-quences désastreuses.

Les résultatsLa durée d’exécution de ce script est particulièrement longue puisque celui-ci parcourt lessystèmes de fichiers. Si votre système est volumineux, vous aurez largement le temps deprendre 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 :

Vous pouvez constater que taylor bat tous les records avec ses 21 giga-octets ! Ouh le vilain !

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

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

Administration système : gérer les utilisateursCHAPITRE 5

121

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

Pour aller plus loinPour ê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. Cetteamélioration est mise en place dans le cadre du script suivant.

N°40 – Signaler les utilisations excessives du disqueLa plupart des administrateurs système recherchent systématiquement les solutions les plussimples. Dans le cas des quotas de disque, il s’agit de compléter le script n°39, fquota, pourlui 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 | \ 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 Unix122

Copyright ©

2004 Groupe E

yrolles

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

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érentede 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 compteutilisateur et son utilisation du disque à chaque cycle, plutôt qu’un message d’erreur signalantle 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 à utiliserla commande sudo.

while read account usage ; do cat << EOF | fmt | mail -s "Avertissement: $account dépasse le quota" $accountVous occupez ${usage}Mo d'espace disque, mais n'avez droit qu'à${MAXDISKUSAGE}Mo. Cela signifie que vous devez soit effacer certainsfichiers, 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'espacedisque. 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

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

Administration système : gérer les utilisateursCHAPITRE 5

123

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

Les résultats

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

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

N°41 – Déterminer l’espace disque disponibleL’évaluation de l’espace disque disponible sur un système relève de la gestion des quotas dedisque. La commande df indique l’utilisation de chaque disque individuellement, mais lasortie obtenue risque de vous surprendre :

$ sudo diskhogsLe compte linda occupe 39.7 Mo d'espace disque. Utilisateur averti.Le compte taylor occupe 21799.5 Mo d'espace disque. Utilisateur averti.

Subject: Avertissement: linda depasse le quota Vous occupez 39.7Mo d'espace disque, mais n'avez droit qu'à 20Mo. Celasignifie que vous devez soit effacer certains fichiers, soit compacterdes fichiers (voyez pour cela «gzip» et «bzip2», programmes decompactage 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

$ dfFilesystem 1K-blocks Used Available Use% Mounted on/dev/hdb2 25695892 1871048 22519564 8% //dev/hdb1 101089 6218 89652 7% /bootnone 127744 0 127744 0% /dev/shm

100 scripts shell Unix124

Copyright ©

2004 Groupe E

yrolles

Il serait préférable d’utiliser une version de df capable d’évaluer les espaces libres disponiblesaffiché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

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

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

#!/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

$ diskspace96199 Mo (93.94 Go) d'espace disque disponible

Administration système : gérer les utilisateursCHAPITRE 5

125

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

Pour aller plus loinSi votre système dispose d’un espace important sur un certain nombre de disques qui offrentplusieurs 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 disponiblesur tous les périphériques, y compris sur les partitions qui ne peuvent pas augmenter, commeboot, ou si les informations relatives aux volumes utilisateur suffisent. Si le deuxième cas defigure vous convient, appelez grep juste après df. Vous pouvez utiliser grep avec le nom dupériphérique concerné ou bien filtrer les périphériques qui ne vous intéressent pas à l’aide del’option -v.

N°42 – Faciliter la lecture de la sortie dfLe 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' > $awkscriptfunction showunit(size) { mb = size / 1024; prettymb=(int(mb * 100)) / 100; gb = mb / 1024; prettygb=(int(gb * 100)) / 100; 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 Unix126

Copyright ©

2004 Groupe E

yrolles

Dans le détailLa partie la plus importante de ce programme se trouve dans un script awk. Il serait d’ailleursparfaitement envisageable d’écrire la totalité du script en awk et d’appeler df directement, viala 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 :

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 convertissantle résultat obtenu en entier (afin d’éliminer la partie fractionnaire), puis en le divisant par lamême puissance de 10. Dans le cas présent, une valeur comme 7.085344324 est remplacéepar 7.08 ; le résultat parle de lui-même.

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

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

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 ouLinux, quelle que soit la version de df installée. Ce script ne prend aucun argument et peut êtreexé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 utilisateursCHAPITRE 5

127

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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

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

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 deslacunes 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 sontthé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 parnobody), mais solution n’est pas idéale : en tant qu’utilisateur, je souhaite retrouver tous lesfichiers 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 renseignementsdans la base de données locate, en indiquant le propriétaire, le groupe et la chaîne de permis-sions associés à chaque entrée. Dans ces conditions, la base de données mklocatedb n’est passé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 lesfichiers .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 auxfichiers publics. Dès le jour suivant (selon le calendrier de cron), cet utilisateur obtient desrésultats personnalisés.

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

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

100 scripts shell Unix128

Copyright ©

2004 Groupe E

yrolles

Deux scripts permettent de mettre en place un locate sécurisé : le constructeur de base dedonné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 1fi 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 1fi cd / # évite les problèmes de permissions postérieurs à su # Tout d'abord, on crée ou met à jour la base de données publiquesu -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... 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 utilisateursCHAPITRE 5

129

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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

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

#!/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'à cequ'elle apparaisse (probablement tard ce soir), je me contenteraid'utiliser la base de données publique, qui renverra tous les fichierspubliquement disponibles, plutôt que les fichiers explicitementaccessibles au compte ${USER:-$LOGNAME}. EOF if [ "$1" = "–explain" ] ; then exit 0 fi # 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 Unix130

Copyright ©

2004 Groupe E

yrolles

Dans le détailLe 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 commandefind peut ainsi être exécutée sur le système de fichiers de chaque utilisateur, pour lequel estcréé une base de données de noms de fichier spécifique. Il est toutefois difficile de travailleravec la commande su dans la mesure où, par défaut, celle-ci ne se contente pas de changerd’identifiant utilisateur, mais importe également l’environnement du compte spécifié. Vousobtenez 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 dansmkslocatedb. Celle-ci route tous les messages d’erreur vers le cimetière des bits : tout ce quiest renvoyé vers /dev/null disparaît sans laisser de traces. Vous échappez ainsi au flot demessages d’erreur « permission denied » (permission refusée), messages invariablementassociés à chaque appel de la commande find.

Exécuter le scriptLe script mkslocatedb est très particulier : il doit être exécuté en tant que root, mais sudo nepeut pas vous aider ici. Vous devez vous connecter au système sous l’identifiant root avantd’exécuter ce script ou avoir recours à la commande su, plus puissante. En revanche, le scriptslocate n’est pas aussi contraignant.

Les résultatsSur 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ésultatsuivant :

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

# mkslocatedbconstruction 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 utilisateursCHAPITRE 5

131

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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

Pour rechercher un fichier ou un ensemble de fichiers correspondant à un motif précis, nousprocédons d’abord sous l’identité de l’utilisateur tintin (qui ne dispose pas encore de fichier.slocatedb) :

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

Pour aller plus loinSi votre système de fichiers est très volumineux, cette approche risque d’utiliser beaucoupd’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 publiquecentrale. Le traitement est alors plus complexe en amont (tri des deux fichiers avec sort, puisappel à 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èremise à 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 utilisateursreviendraient au point de départ chaque lundi, puisqu’ils exécutent rarement la commandeslocate pendant le week-end.

En dernier lieu, il est également possible de compacter les fichiers .slocatedb, puis de lesdécompacter à la volée lors d’une recherche avec slocate. Pour cela, inspirez-vous de lacommande zgrep du script n°37.

# mkslocatedbconstruction 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.

tintin $ slocate Taylor-Rapport.docAvertissement: j'utilise la base de données publique.Tapez «slocate –explain» pour en savoir plus.$

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

100 scripts shell Unix132

Copyright ©

2004 Groupe E

yrolles

N°44 – Ajouter des utilisateurs au systèmeSi vous êtes responsable d’un réseau de machines Unix et Linux, vous n’êtes pas sansconnaître les incompatibilités subtiles entre ces systèmes. Les tâches d’administration les plussimples sont parfois les plus éloignées d’un Unix à l’autre, la gestion des comptes utilisateurremportant la palme en la matière. En effet, chaque fabricant a mis en place sa propre interfacegraphique, 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 pourobjectif la normalisation de ce type d’implémentation, la gestion des utilisateurs est aussidifficile qu’il y a dix ans, surtout dans les environnements informatiques hétérogènes. C’estpourquoi la trousse à outils de chaque administrateur système doit impérativement comporterune version personnalisée des scripts adduser (ajouter un utilisateur), deleteuser (supprimerun utilisateur) et suspenduser (suspendre un utilisateur).

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 unshell de connexion (login shell). Les systèmes Unix modernes stockent la valeur chiffrée dumot 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 dansce script) ou en l’ajoutant à un groupe existant.

Le code

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 decomptes nommée NetInfo. Le chapitre 11 propose une version de ces outils pour Mac OS X.

#! /bin/sh# adduser - Ajoute un nouvel utilisateur au système, en pensant à# construire son répertoire personnel, à y copier les données de# 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 utilisateursCHAPITRE 5

133

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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

echo "Erreur: il faut être root pour exécuter cette commande." >&2 exit 1fi 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=uidgid=$uid echo -n "nom complet: " ; read fullnameecho -n "shell: " ; read shell echo "Mise en place du compte $login pour $fullname..." echo ${login}:x:${uid}:${gid}:${fullname}:${homedir}:$shell >> $pwfileecho ${login}:*:11647:0:99999:7::: >> $shadowfile echo "${login}:x:${gid}:$login" >> $gfile mkdir $homedircp -R /etc/skel/.[a-zA-Z]* $homedirchmod 755 $homedirfind $homedir -print | xargs chown ${login}:${login} # Mise en place d'un mot de passe initialpasswd $login exit 0

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

100 scripts shell Unix134

Copyright ©

2004 Groupe E

yrolles

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 ensuitecette valeur pour obtenir l’identifiant du nouveau compte utilisateur. L’administrateur n’aplus 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 estdupliqué. 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 siteWeb ? ».

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

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

Pour aller plus loinLorsque vous implémentez votre propre script adduser, vous évitez que tout ajout de code ouchangement dans la logique interne des scripts standards ne soient écrasés par une mise à jourdu système. Par exemple, chaque modification locale pourrait entraîner l’envoi automatiqued’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, oubien l’ajout d’un alias Prenom_Nomfamille ou Prenom.Nomfamille au fichier aliases du cour-

$ sudo adduserAjout d'un compte utilisateur sur auroralogin: milounom complet: Milou le chienshell: /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.

Administration système : gérer les utilisateursCHAPITRE 5

135

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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

N°45 – Suspendre un compte utilisateurDans 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é à laporte par les agents de sécurité pour acte d’espionnage industriel, quand un étudiant part envacances 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 del’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 lesautres comptes du système. Vous devez vous assurer qu’il n’a plus aucun moyen d’accéder ausystème.

Ce script vérifie essentiellement si l’utilisateur est connecté. Le cas échéant, il est informé desa 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 utilisateurssecs=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 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èmeif who|grep "$1" > /dev/null ; then tty="$(who | grep $1 | tail -1 | awk '{print $2}')"

100 scripts shell Unix136

Copyright ©

2004 Groupe E

yrolles

Dans le détailCe script ne présente aucune difficulté : le mot de passe de l’utilisateur est remplacé par unenouvelle valeur que celui-ci ne connaît pas. Si l’utilisateur est connecté, il dispose de quelquessecondes pour fermer ses applications avant d’être expulsé du système via l’arrêt de tous sesprocessus actifs. Enfin, son répertoire personnel est désactivé.

Remarquez la séquence qui consiste à envoyer le signal SIGHUP (HUP) à tous les processus encours d’exécution pour l’utilisateur : il s’agit du signal d’alerte. Une seconde plus tard, le

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 quitterimmé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 indiscretschmod 000 $homedir/$1 echo "Le compte $1 a été suspendu." exit 0

Administration système : gérer les utilisateursCHAPITRE 5

137

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

signal SIGKILL (KILL), plus agressif, est envoyé. Le signal SIGHUP met généralement fin auxapplications en cours d’exécution, bien que cela ne soit pas systématiquement le cas. Enrevanche, il n’affecte absolument pas un shell de connexion. Quant au signal SIGKILL, il nepeut 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 devider ses tampons de fichiers afin de s’assurer que les modifications sont consignées sur ledisque, 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 (viapasswd) qui est communiqué à l’utilisateur concerné.

Ce script doit être exécuté en tant que root et prend pour seul argument le nom du compteutilisateur à suspendre.

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

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

$ sudo suspenduser milouVeuillez 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.

************************************************************* MESSAGE URGENT DE L'ADMINISTRATEUR: Ce compte va être suspendu à la demande de la direction.Vous serez déconnecté dans 10 secondes. Veuillez quitterimmé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 Unix138

Copyright ©

2004 Groupe E

yrolles

N°46 – Supprimer un compte utilisateurLa suppression d’un compte est légèrement plus complexe que sa suspension puisque le scriptdoit examiner l’ensemble des disques afin de rechercher les fichiers appartenant à l’utilisateurconcerné. 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 # On détruit ce compte des fichiers password et shadowgrep -vE "^${1}:" $pwfile > $newpwfile grep -vE "^${1}:" $shadow > $newshadow lockcmd="$(which lockfile)" # cherche l'application lockfile dans le PATHif [ ! -z $lockcmd ]; then # utilisons le lockfile du système eval $lockcmd -r 15 $lockerelse # il faut tout faire soi-même! while [ -e $locker ]; do

Administration système : gérer les utilisateursCHAPITRE 5

139

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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 programmelockfile, s’il est disponible. Si tel n’est pas le cas, le script a recours à un mécanisme deverrouillage relativement primitif et crée le fichier /etc/passwd.lock. Lorsque ce fichierexiste déjà, le script attend qu’un autre programme le détruise, après quoi il le crée à nouveauimmédiatement et poursuit le processus.

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

echo "j'attends le fichier de mots de passe"; sleep 1 done touch $locker # mise en place d'un verrou par fichierfi mv $newpwfile $pwfilemv $newshadow $shadowrm -f $locker # clac! le verrou est levé chmod 644 $pwfilechmod 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

INFO Danger !

Ce script a une action irréversible et détruit de nombreux fichiers ; une prudence extrêmes’impose donc lorsque vous le testez !

100 scripts shell Unix140

Copyright ©

2004 Groupe E

yrolles

Les résultats

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

Pour aller plus loinLe script deleteuser est volontairement incomplet. Chaque administrateur système peut ainsichoisir les mesures à mettre en œuvre : le compactage et l’archivage d’une copie des fichiersdu compte détruit, leur sauvegarde sur bande, leur gravage sur CD-Rom, ou encore leur envoiaux services secrets (je plaisante... enfin, je l’espère). Vous devez encore supprimer ce comptedes 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’administrateurde les effacer ou non, au cas par cas.

N°47 – Valider l’environnement utilisateurDans la mesure où les utilisateurs ont tendance à migrer leurs fichiers .login, .profile, ainsique diverses autres personnalisations de leur environnement shell, d’un système à l’autre, cesparamètres sont parfois partiellement erronés. Vous pouvez, par exemple, trouver un PATHcomposé de répertoires absents du système, un PAGER qui pointe vers un binaire inexistant, etpire encore.

Une solution relativement élaborée consiste à contrôler en premier lieu le PATH afin de vérifierqu’il comporte uniquement des répertoires présents sur le système. Le script peut ensuiteexaminer chaque paramètre des applications d’appui principales pour savoir s’il indique unnom de fichier absolu, présent sur le système, ou un binaire du PATH.

$ sudo deleteuser milouVeuillez 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 sonrépertoire personnel (/home/milou).

Administration système : gérer les utilisateursCHAPITRE 5

141

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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 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 Unix142

Copyright ©

2004 Groupe E

yrolles

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# 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" $EDITORvalidate "MAILER" $MAILERvalidate "PAGER" $PAGER

Administration système : gérer les utilisateursCHAPITRE 5

143

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

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

Pour valider les valeurs des variables d’environnement, la fonction validate() commence parexaminer 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 unslash, le script appelle la fonction in_path() afin de contrôler si le programme se trouve dansl’un des répertoires du PATH actuel.

Ce script se distingue notamment par son utilisation de valeurs par défaut pour certainesconditionnelles et du fractionnement des variables. Les valeurs par défaut sont intégrées de lafaçon suivante dans les conditionnelles :

La notation ${var:?"messageErreur"} signifie : si nom_var existe, utiliser sa valeur ; dans lecas contraire, faire échouer via l’erreur « messageErreur ».

La notation du fractionnement des variables, ${var%${var#?}} est la fonction de sous-chaînede la norme POSIX. Elle produit uniquement le premier caractère de la variable var. Dans lecas présent, elle permet de vérifier si une variable d’environnement est un chemin de fichierabsolu valide (commence par un slash / et spécifie le chemin vers un binaire).

# 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

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

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

100 scripts shell Unix144

Copyright ©

2004 Groupe E

yrolles

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

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

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

Les résultats

N°48 – Nettoyer après le départ des invitésBien que de nombreux sites désactivent le compte guest pour des raisons de sécurité, d’autresproposent ce compte, généralement associé à un mot de passe très facile à deviner, afin depermettre aux employés d’autres services d’accéder au réseau. Bien qu’utile, ce compteprésente un inconvénient majeur : chaque utilisateur effectue ses propres expériences (test dediverses commandes, édition de fichiers .rc, ajout de sous-répertoires, etc.) et certains ne segênent pas pour laisser un véritable capharnaüm à l’utilisateur suivant.

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, ilreconstruit les fichiers officiels du compte à partir de leur copie stockée dans une archive enlecture seule placée dans le répertoire ..template du compte.

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

$(echo $var | cut -c1)

$ 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.

Administration système : gérer les utilisateursCHAPITRE 5

145

Cop

yrig

ht ©

200

4 G

roup

e E

yrol

les

Le code

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

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

100 scripts shell Unix146

Copyright ©

2004 Groupe E

yrolles

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

Certains invités seront probablement suffisamment rusés pour modifier le script .logout. Lecas é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ésultatsCe programme ne produit aucun résultat visible, à ceci près que le répertoire personnel del’invité est restauré avec la structure et les fichiers de son sous-répertoire ..template.

Avertissement: tous les fichiers présents dans le compte «guest» serontdétruits à la déconnexion. Ne stockez ici aucun fichier dont vous ayezbesoin. Si vous souhaitez sauvegarder quelque chose, envoyez-le parcourrier électronique à votre compte principal. Vous êtes prévenu!