Cours administration Linux

ADMINISTRATION LINUX
ADMINISTRATION LINUX
AVERTISSEMENT:
Le cours administration Linux repose sur l'utilisation de la distribution Mandrake 5.3 basée sur la distribution Red Hat 5.2
objectif:
A la fin de ce module vous serez capable
ressources:
Documentation:
Matériel:
sommaire
SectionsPages
Installation du système________________________________________________________
Préparation de la machine____________________________________________________
GESTION DES UTILISATEURS_______________________________________________
Les utilisateurs du système____________________________________________________
Création de comptes utilisateurs sur la machine____________________________________
Le système d'impression_______________________________________________________
Gestion des quotas___________________________________________________________
Gestion des packages RPM____________________________________________________
Compilation du noyau________________________________________________________
Généralités________________________________________________________________
Les sources du noyau________________________________________________________
Installation des sources_______________________________________________________
La compilation_____________________________________________________________
Commandes différées et cycliques_______________________________________________
Gestion des systèmes de fichiers_________________________________________________
Démarrage et arrêt du système__________________________________________________
LILO______________________________________________________________________
Communications sous Linux___________________________________________________
ANNEXE 1_________________________________________________________________
Utilité et domaine d'utilisation_________________________________________________
Algorithme fondamental de make______________________________________________
Les connaissances implicites___________________________________________________
Les macros de substitution____________________________________________________
Les macros speciales_________________________________________________________
Addition de règles implicites___________________________________________________
Les règles de précédence_____________________________________________________
Les règles d'inférence________________________________________________________
Directives et caractères de début de règles de production_____________________________
Lancement, par make, de make sur d'autres répertoires_____________________________
Les options de la commande___________________________________________________
Interfaçage avec sccs________________________________________________________
Les librairies______________________________________________________________
bibliographie______________________________________________________________
Il existe deux types d'utilisateurs sur le système:
- root
Login name du compte administrateur du système. L'utilisateur root à tous les droits sur le système.
- Tous les autres utilisateurs du système
Utilisateurs créés par l'administrateur.
Il est possible de réunir des utilisateurs au sein d'un groupe ce qui simplifie le gestion des utilisateurs en permettant l'attribution simultanée de droits à plusieurs utilisateurs.
Un utilisateur peut appartenir à plusieurs groupes.
La création des utilisateurs sur une machine Unix passe d'abord par l'inscription d'entrées dans différents fichiers systèmes:
- /etc/passwd
contient la liste des utilisateurs
- /etc/group
contient la liste des groupes d'utilisateurs
Il faut ensuite créer le répertoire de connexion personnel de l'utilisateur (home directory dont la spécification est ensuite inscrite par le système, lors de la connexion, dans la variable #HOME), l'en rendre propriétaire (chown), attribuer le répertoire à un groupe, en général celui auquel appartient l'utilisateur (chgrp) et le protéger (chmod 700).
La dernière étape consiste en la création des fichiers de configuration de l'environnement de l'utilisateur. Les prototypes de ces fichiers pour un utilisateur travaillant sous Bourne Again Shell (bash) se trouvent dans le répertoire /etc/skel. Il faut en faire une copie dans le répertoire de connexion de l'utilisateur et effectuer les mêmes actions d'attribution et de protection que pour le répertoire.
Le fichier /etc/passwd
Ce fichier comprend une entrée (ligne) par utilisateur de la machine.
Chaque entrée comporte sept champs séparés par le caractère ' : '
User Name:Password:UID:GID:Comment:Home Directory:shell
Signification des différents champs:
User Name:
Contient le nom de l'utilisateur. Ce champs ne doit contenir que des caractères alphanumériques.
Password:
Contient le mot de passe codé de l'utilisateur. Il est renseigné par la commande passwd.
UID:
User IDentifier; nombre entier unique alloué par l'administrateur à chaque utilisateur.
GID:
Group IDentifier; nombre entier unique alloué par l'administrateur à chaque goupe.
Comment:
Contient un commentaire. En général on y met le nom complet de l'utilisateur, sa localisation et son numéro de poste téléphonique séparés par des virgules; ces informations sont exploitées par la commande finger qui a une fonction analogue à la commande who.
Home directory:
Contient le nom complet du répertoire de l'utilisateur.
Shell:
Contient le nom du shell qui sera lancé lors de la connexion de l'utilisateur au système.
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:
daemon:x:2:2:daemon:/sbin:
adm:x:3:4:adm:/var/adm:
lp:x:4:7:lp:/var/spool/lpd:
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:
news:x:9:13:news:/var/spool/news:
uucp:x:10:14:uucp:/var/spool/uucp:
operator:x:11:0:operator:/root:
games:x:12:100:games:/usr/games:
gopher:x:13:30:gopher:/usr/lib/gopher-data:
ftp:x:14:50:FTP User:/home/ftp:
nobody:x:99:99:Nobody:/:
guest:x:500:500:invite:/usr/guest:/bin/bash
gigi:x:501:0::/usr/gigi:/bin/bash
titi:x:502:100::/usr/titi:/bin/ksh
michel:x:503:100::/usr/michel:/bin/ksh
user01:x:504:500::/home/user01:/bin/ksh
Contenu du fichier/etc/passwd
Exemple:
ted:t5Myr3uQNIXvc:Teddy GIMP,E6,183:/home/ted:/bin/bash
Nota:
Ce fichier est consultable par l'ensemble des utilisateurs de la machine; cela peut poser un problème de sécurité car le mot de passe est visible et peut être sujet à une "attaque par le dictionnaire"
Le fichier /etc/group
Ce fichier comprend une entrée par groupe d'utilisateurs de la machine.
Chaque entrée comporte quatre champs séparés par le caractère ' : '.:
Group Name:Password:GID:Users list
Signification des différents champs:
Group Name:
Contient le nom du groupe. Ce champs ne doit contenir que des caractères alphanumériques.
Password:
Mot de passe. Ce champs est inutilisé aujourd'hui et doit être laissé vide.
Group Identifier (GID):
Contient le numéro d'identification du groupe. Ce champs ne doit contenir que des caractères numériques. Chaque GID doit être unique.
Users list
Contient la liste des utilisateurs affiliés au groupe. Les noms d'utilisateurs sont séparés par une virgule.
Exemple:
compta::512:gigi,al,steph
root::0:root,gigi,titi
bin::1:root,bin,daemon
daemon::2:root,bin,daemon
sys::3:root,bin,adm
adm::4:root,adm,daemon
tty::5:
disk::6:root
lp::7:daemon,lp
mem::8:
kmem::9:
wheel::10:root
mail::12:mail
news::13:news
uucp::14:uucp
man::15:
games::20:
gopher::30:
dip::40:
ftp::50:
nobody::99:
users::100:guest,michel,user01
floppy:x:19:
pppusers:x:230:
popusers:x:231:
slipusers:x:232:
essai::500:user01
Contenu du fichier/etc/group
Le shadowing
Le shadowing a été mis en place sur le système Unix pour pallier au défaut de sécurité lié à la visibilité du fichier /etc/passwd.
Le principe consiste en l'utilisation d'un fichier supplémentaire /etc/shadow contenant le mot de passe codé et inaccessible aux utilisateurs du système.
Sur Linux le shadowing n'est pas mis en place par défaut: pour le rendre effectif il faut entrer la commande pwconv; pour revenir en arrière il suffit d'entrer la commande pwunconv.
Le fichier /etc/shadow comprend une entrée par utilisateur de la machine.
Chaque entrée comporte neuf champs séparés par le caractère ' : '
User Name:Password:Ch3:Ch4:Ch5:Ch6:Ch7:Ch8:Ch9
User Name:
Contient le nom de l'utilisateur. Ce champs ne doit contenir que des caractères alphanumériques.
Password:
Contient le mot de passe codé de l'utilisateur. Il est renseigné par la commande passwd.
Ch3: Date de dernière modification
Contient le nombre de jours qui se sont écoulés entre le 1er Janvier 1970 et le jour de la dernière modification du mot de passe.
Ch4: Durée minimum
Contient le nombre de jours avant que le mot de passe ne puisse être changé.
Ch5: Durée maximum
Contient le nombre de jours après lesquels le mot de passe doit être changé.
Ch6: Avertissement
Contient le nombre de jours précédent l'expiration du mot de passe pendant lesquels l'utilisateur sera averti que le mot de passe arrive à expiration.
root:ASu9TSYHFbR4A:10618:0:99999:7:::
bin:*:10618:0:99999:7:::
daemon:*:10618:0:99999:7:::
adm:*:10618:0:99999:7:::
lp:*:10618:0:99999:7:::
sync:*:10618:0:99999:7:::
shutdown:*:10618:0:99999:7:::
halt:*:10618:0:99999:7:::
mail:*:10618:0:99999:7:::
news:*:10618:0:99999:7:::
uucp:*:10618:0:99999:7:::
operator:*:10618:0:99999:7:::
games:*:10618:0:99999:7:::
gopher:*:10618:0:99999:7:::
ftp:*:10618:0:99999:7:::
nobody:*:10618:0:99999:7:::
guest::10618:0:99999:7:::
gigi:x:10618:0:99999:7:::
titi:fmBwU0U78H3.I:10618:0:99999:7:::
michel:IInsQroVza4/6:10618:0:99999:7:::
user01:4lOuNtA3abzMI:10623::::::
Contenu du fichier/etc/shadow
Ch7: Désactivation
Contient le nombre de jours suivant l'expiration du mot de passe après lesquels le compte utilisateur sera bloqué.
Ch8: Date d'expiration
Contient le nombre de jours qui se sont écoulés entre le 1er Janvier 1970 et la date d'expiration du compte utilisateur.
Ch: RFU
Réservé pour utilisation future.
Un système d'impression comprend en général les parties suivantes:
- des commandes de lancement d'impression
- des files d'attente pour stocker et traiter les requêtes d'impression; ce sont en général des répertoires spécifiques qui contiennent une copie du document à imprimer, copie qui sera effacée une fois le job terminé; sur certains systèmes (AIX, system V) c'est un fichier pointant sur le fichier à imprimer qui est créé dans la file d'attente.
- un processus serveur qui à pour tâche de transférer les requêtes du répertoire de files d'attente sur le périphérique.
- Des commandes d'administration du sous-système d'impression.
Daemon d'impression
Dans le monde Unix il existe deux types de sous-systèmes d'impression, un type BSD et un type system V.
Le sous-système d'impression Linux est de type BSD.
Il repose sur le Daemon lpd. Celui-ci doit donc être démarré avant tout travail d'impression; en général cela est fait lors du démarrage de la machine par le biais d'un script d'initialisation. Dans le cas d'une distribution Red Hat (et Mandrake…) il s'agit du script /etc/rc.d/init.d/lpd, pointé par les liens S65lpd dans les répertoires /etc/rc.d/rc[2345].d.
Il ne peut y avoir qu'un seul deamon lpd actif sur le système. Pour s'en assurer le premier à être lancé crée le fichier afin d'indiquer sa présence.
Dès son lancement lpd se met à l'écoute de la socket /dev/printer pour répondre aux requêtes d'impression. A chaque requête il crée un processus fils qui est chargé de la traiter.
Il prend en charge également les requêtes d'impression réseau en écoutant le port 515 défini sous le nom printer dans le fichier /etc/services.
Configuration du système d'impression: /etc/printcap
Le fichier /etc/printcap définit les caractéristiques des impression vers une imprimante donnée:
- Le nom logique de l'imprimante
- Le fichier spécial d'interface avec l'imprimante
- Le chemin d'accès au spool
- Divers autres paramètres
Ce fichier est orienté ligne, c'est à dire que les caractéristiques des impressions vers un périphérique donné sont définies sur une ligne. Celles-ci sont composées d'un certain nombre d'options contenues dans différents champs séparés par le caractère ' : '. Cependant, les champs pouvant être nombreux, la visibilité peut être améliorée en spécifiant chacune des options sur une ligne différente en terminant chaque ligne par le caractère ' \ '.
La définition d'une imprimante débute par un premier champs définissant le nom de l'imprimante et éventuellement des alias de nom séparés par le caractère ' | '. Si le nom défini est ' lp ' il s'agit de l'imprimante par défaut sur le système.
Chaque champs possède un nom sur deux caractères. Il existe trois types de champs:
- Chaîne de caractères.
Syntaxe : nom=chaîne de caractères - Numérique.
Syntaxe: nom#valeur - Booléen
Spécifiés en indiquant leur nom. Sinon la valeur est la valeur définie par défaut pour ce champs.
Une ligne débutant par le caractère " # " introduit un commentaire dans le fichier.
#
#Imprimante 1 (locale)
#
eps|epson-5200:\
:sd=/var/spool/lpd/lp:\
:mx#0:\
:sh:\
:lp=/dev/lp1:\
:if=/var/spool/lpd/lp/gigi-filter:
#
#Imprimante 2 (distante)
#
lp|default_printer:\
:sd=/var/spool/lpd/lp0:\
:mx#0:\
:sh:\
:rm=ethan:\
:rp=lp:\
:lp=/dev/null:\
:if=/var/spool/lpd/lp0/filter:
ATTENTION
Un caractère d'espacement ou de tabulation minimumobligatoireau début de chaque ligne commençant par le caractère ':' !
Le fichier/etc/printcap
Signification des principaux champs du fichier /etc/printcap
Nom | Type | Défaut | Description |
hl | booléen | false | Imprime une page de séparation après chaque job si sh n'est pas spécifié |
if | caractères | NULL | Nom du filtre de prétraitement du fichier |
lf | caractères | /dev/console | Nom du fichier de journalisation des erreurs |
lp | caractères | /dev/lp | Nom du fichier spécial périphérique vers lequel envoyer les tâches d'impression |
mx | numérique | 1000 | Taille maximum du fichier à imprimer; illimité si mx est défini à 0 |
pl | numérique | 66 | Nombre de lignes par page |
pw | numérique | 132 | Nombre de caractères par ligne |
rg | caractères | NULL | Nom du group auquel est restreint l'usage de cette imprimante |
rm | caractères | NULL | Nom du serveur d'impression distant |
rp | caractères | lp | Nom de l'imprimante distante |
rs | booléen | false | Les impressions distantes ne sont autorisées que pour les utilisateurs ayant un compte sur le serveur d'impression |
sc | booléen | false | Interdit les copies multiples |
sd | caractères | /var/spool/lpd | Nom du répertoire de la file d'attente |
sh | booléen | false | Pas d'impression de page de séparation |
Pour une liste exhaustive des paramètres consulter la page du manuel pour printcap (man 5 printcap).
Les fichiers de contrôle
Ces fichiers permettent aux diverses commandes du système d'impression de dialoguer entre elles.
Le premier de ces fichiers de contrôle est le fichier qui permet d'éviter d'avoir plus d'un daemon lpd père à la fois. C'est le seul fichier global; les autres sont relatifs à une file d'attente.
- lock
Utilisé par lpd pour qu'il n'imprime pas deux fichiers à la fois sur une même imprimante.
Il contient au moins une ligne indiquant le PID du dernier processus lpd qui à géré cette file. Sur une seconde ligne on trouve le nom du fichier de configuration de la dernière requête d'impression traitée si l'impression est stoppée ou de la requête en cours de traitement.
Dans cet exemple, l'impression est suspendue:
#cat lock
1423
cfA318Aa01416
#ps aux|grep lpd
root89 0.0 0.6 788 312 ? S 11:20 0:00 /usr/sbin/lpd
root 1423 0.0 .08 804 380 ? S 19:52 0:00 /usr/sbin/lpd
La première ligne contient le PID du processus lpd qui traite la requête (1423) et qui est fils du processus lpd lancé au démarrage de la machine (PID 89).
Les permissions d'accès au fichier lock indiquent a lpd et lpr le statut de la file d'attente et de l'imprimante:
- si le propriétaire dispose du droit d'exécution, alors l'impression est interdite.
- Si le groupe dispose du droit d'exécution, alors la file d'attente est fermée.
- Il est possible de combiner ces deux situations.
- status
Le fichier status renseigne sur l'état de l'imprimante. Il est consulté par les commandes lpq et lpr.
#cat status
printing disabled
Dans ce cas l'impression est suspendue. Les requêtes continuent à être acceptées et stockées dans la file d'attente.
Le nom par défaut est status mais peut être modifié par l'utilisation du paramètre st dans le fichiet /etc/printcap.
- .seq
Contient le numéro de séquence du job suivant. Il permet à la commande lpr de numéroter les fichiers de traitement de la requête.
#ls -al
…………………3.seq
…………………76cfA318Aa01416
………………… 678dfA318Aa01416
…………………76
…………………19lock
…………………18status
#cat .seq
319
Deux autres fichiers (temporaires) sont créés à chaque requête:
- le premier est une copie du document à imprimer (dfA318Aa01416dans cet exemple). Son nom est formé d'un préfixe, d'une lettre de A à Z, d'un numéro d'ordre trouvé dans le fichier .seq et d'un suffixe identifiant la station. Le préfixe est df ce qui donne vingt six fichiers possibles de dfA à dfZ. S'il y a plus de vingt six fichiers à imprimer les préfixes ef à zf seront utilisés. Dans le cas d'une demande d'impression avec l'option -s ce fichier est un lien sur le fichier à imprimer.
- Le deuxième contient un certain nombre de paramètres concernant l'impression proprement dite.
La commande de lancement d'impression: lpr
Cette commande demande l'impression du fichier dont le nom est passé en argument.
Elle peut également travailler à partir de son canal d'entrée standard et donc être utilisée derrière un pipe.
La commande :
#ls -ail |lpr
imprimera le contenu du répertoire courant.
Sans option spécifique lpr envoie la commande d'impression sur l'imprimante par défaut.
L'imprimante par défaut peut être définie de deux façons:
- Son nom dans le fichier /etc/printcap est lp. Valable pour tous les utilisateurs du système.
- Son nom, quel qu'il soit, est spécifié dans la variable d'environnement #PRINTER. Valable pour un utilisateur donné.
Cette commande admet un certain nombre d'option dont voici les plus courantes:
-P | Permet l'impression sur une autre imprimante que l'imprimante par défaut. |
-m | Avertit l'utilisateur lorsque le job est terminé. Utile lorsque l'on demande l'impression en différé. |
-r | Supprime le fichier une fois l'impression terminée. |
-s | Demande à lpr d'utiliser le fichier demandé sans en faire une copie dans le répertoire de spool. C'est un lien vers le fichier à imprimer qui sera créé dans ce répertoire. |
-#n | Demande l'impression de n copies du fichier. |
Commandes de gestion de file d'attente: lpq, lprm
Permettent de consulter la liste des jobs en cours d'impression et éventuellement d'en annuler.
lpq
Sans option cette commande montre le contenu de la file d'attente de l'imprimante par défaut.
#lpq
RankOwnerJobFilesTotal size
1stsystem503bug.c678 bytes
2ndroot504linux_admin10549 bytes
Pour consulter une file d'attente particulière il faut utiliser l'option -P.
lprm
Permet de supprimer un job de la file d'attente en lui fournissant en argument le N° de job.
Sans option elle supprime un job de la file d'attente par défaut. Pour supprimer un job d'une file d'attente particulière utiliser l'option -P.
Un utilisateur ne peut supprimer que les jobs qu'il a lui-même lancé. Seul l'administrateur peut supprimer n'importe quel job d'une file d'attente.
Si un utilisateur veut supprimer tous les jobs en attente il utilisera l'option ' - ' seule.
Administration du système d'impression: lpc
L'administration du système d'impression consiste en l'une ou l'autre des tâches suivantes:
- Activer ou désactiver une imprimante, sans incidence sur le fonctionnement de la file d'attente associée.
- Activer ou désactiver une file d'attente.
- Modifier l'ordre de prise en compte des requêtes présentes dans une file d'attente.
- Afficher l'état des diverses imprimantes, files d'attente et processus associés.
Toutes les tâches d'administration se font avec la commande lpc. Cette commande peut fonctionner en mode interactif ou non; lancée sans argument elle fonctionne en mode interactif et affiche le prompt lpc> en attendant la saisie d'une commande.
Les actions que peut exécuter la commande lpc sont:
| Aide en ligne globale ou à propos d'une commande dont le nom est passé en argument. |
| Arrête l'impression en cours et désactive l'imprimante indiquée. |
| Désactive l'imprimante indiquée après la fin du job en cours. |
| Active l'imprimante indiquée; les files d'attente restent en l'état. |
| Identique à start mais supprime les processus existants et en relance d'autres. |
| Désactive la file d'attente indiquée, interdisant l'envoi de nouvelles requêtes à destination de cette file. |
| Active une file d'attente ayant été désactivée par la commande disable. |
| Désactive la file d'attente et le périphérique associés à l'imprimante indiquée et met le message donné dans le fichier status. Le contenu de ce fichier est affiché par la commande lpq. |
| Active la file d'attente et le périphérique associés à l'imprimante indiquée. |
| Positionne les jobs dont les numéros sont donnés au début de la file d'attente. Lorsqu'un nom d'utilisateur est donné, toutes ses requêtes sont mises en tête de la file d'attente. |
| Affiche l'état du périphérique, du daemon lpd éventuel et de la file d'attente associés à l'imprimante désignée. |
| Nettoie la file d'attente de l'imprimante désignée en supprimant les fichiers de contrôle résiduels. |
| Termine la session interactive de lpc. |
Les filtres d'impression
Les filtres d'entrée sont des programmes qui, recevant des données à imprimer sur leur entrée standard (stdin), les formatent avant de les ressortir sur leur sortie standard (stdout).
Ils peuvent être utilisés pour convertir du texte en postscript par exemple.
Un problème apparaît sur les imprimantes HP500 notamment : l'impression se fait avec un effet de "marches d'escalier".
Ceci est la première ligne
Ceci est la deuxième ligne
Ceci est la troisième ligne
Ceci est la quatrième ligne
Cela est dû au fait que Linux termine chaque ligne par le caractère LF au lieu du caractère CR. Il est possible de réparer cela à l'aide du filtre suivant écrit en shell script.
#/bin/sh
if [ "#1" = -c ]
then
cat
else
sed -e s/#/^M/
fi
# echo -ne suppose que /bin/sh correspond à bash
echo -ne \\f
Activation des quotas sur les systèmes de fichiers
La gestion des quotas disque permet à l'administrateur du système de limiter l'espace disque attribué aux utilisateurs de la machine.
Il est possible de limiter l'espace disque pour un utilisateur ou\et pour un groupe d'utilisateurs.
Pour activer le système de gestion des quotas il faut tout d'abord ajouter les options usrquota et grpquota pour les système de fichiers concernés dans le fichier /etc/fstab.
/dev/sdb5 / ext2 defaults,usrquota,grpquota 1 1
/dev/cdrom /mnt/cdrom iso9660 noauto,ro 0 0
/dev/hda5 /mnt/dosdisk1 msdos ignore 0 0
/dev/fd0 /mnt/floppy ext2 noauto 0 0
Les fichiers de gestion des quotas s'appelle et quota.group et doivent être créés sur la racine du système de fichier concerné par la gestion des quotas.
L'activation de la gestion des quotas est ensuite lancée par la commande
#/usr/sbin/quotaon -avug
La suppression de la gestion des quotas se fait par la commande
#/usr/sbin/quotaoff -avug
La vérification des information de gestion des quotas se fait par la commande
#/usr/sbin/quotacheck -avug
Attribution des quotas à un utilisateur
L'attribution des quotas à un utilisateur se fait par la commande edquota.
A TERMINER !!!!!!
Le système Linux de base contient un noyau, des outils et des fichiers de données et de configuration.
L'administrateur aura à installer des utilitaires supplémentaires, des applications pour les utilisateurs et divers fichiers de données en fonction des besoins.
Le terme 'installer' signifie copier les fichiers sur le disque dur dans une arborescence spécifique et configurer l'application (assigner des ressources) pour un fonctionnement correct.
Ces opération peuvent s'avérer fastidieuses et compliquées.
Les distributions Red Hat, Caldera et Mandrake facilitent ces opérations grâce au principe des RPMs (Red Hat Package Management). Chaque applicatif est contenu dans un fichier unique, compressé, ayant l'extension '.rpm'; l'installation se fait par la commande rpm.
La commande rpm permet, entre autre, d'installer, de supprimer ou de mettre à jour un applicatif par l'utilisation de l'option adéquate:
#rpm [option] nom_de_package
Les noms de package ont un format bien déterminé; par exemple le package de gestion des quotas disque aura pour nom:
ou
quota est le nom
1.55 est la version
4 est la release
i386 est l'architecture matérielle supportée
.rpm est l'extension typique
Cependant le package peut avoir un nom n'ayant aucun rapport avec l'applicatif, le nom de l'applicatif étant inscrit dans le fichier rpm.
Les packages se trouvent sur le cdrom installation dans le répertoire /RedHat/RPMS. La commande rpm permet d'installer des packages situés sur d'autres ordinateurs en utilisant ftp.
Installer des packages
Installer un package se fait par la commande :
#rpm -i nom_de_package
Lors de l'installation d'un applicatif la commande rpm effectue les opérations suivantes:
| chaque package peut dépendre d'un autre logiciel déjà installé. |
| rpm vérifie si un composant est déjà installé ou s'il n'est pas antérieur à celui qui à déjà été installé. |
| rpm essaie de créer un fichier de configuration adapté, et s'il découvre qu'il y en a déjà un, il le sauvegarde. |
| rpm décompacte les divers composants du package et les installe dans les répertoires appropriés. |
| Après l'installation des divers composants, rpm effectue les tâches éventuellement requises pour configurer le système. |
| rpm garde une trace de toutes les opérations effectuées dans une base de données. |
L'utilisation de l'option -i seule ne permet pas d'avoir d'information au cours de l'installation.
Utiliser l'option -v (verbose: bavard) pour avoir des informations pendant l'installation.
L'option -h permet d'obtenir une barre de défilement composée de caractères # .
La commande utilisée en général pour installer un package est donc:
#rpm -ivh nom_de_package
Autres options d'installation:
| Informations en mode très bavard |
| Affiche le caractère % à la place du caractère # pour la barre de défilement. |
| N'installe pas le package. Teste l'installation et rend compte d'éventuelles erreurs. |
| Remplace les fichiers d'autres packages. |
| Force rpm à installer le package malgré des erreurs de conflit éventuelles. |
Installation depuis un serveur ftp:
#rpm -i
Supprimer des packages
Utiliser l'option -e pour supprimer un package du disque
#rpm -e nom_de_package
De même que pour l'installation on peut utiliser l'option -v pour avoir des indications pendant le processus de désintallation.
Autres options de désinstallation:
| Idem installation |
| Idem installation |
| Ordonne à rpm d'ignorer les dépendances pendant la désinstallation. ATTENTION l'utilisation de cette option peut s'avérer dangereuse! |
Lors de la désinstallation, rpm effectue les opérations suivantes:
| rpm contrôle dans sa base de données si d'autres packages dépendent de celui à supprimer. Si c'est le cas rpm ne désinstalle pas à moins d'un ordre explicite. |
| rpm exécute un script d'avant suppression. |
| rpm sauvegarde les fichiers de configuration qui ont été modifiés. |
| rpm supprime tous les fichiers associés au package à désinstaller. |
| rpm exécute un script d'après suppression. |
| rpm supprime de la base de données toute référence au package désinstallé. |
Mise à jour des packages
Un package installé peut avoir besoin d'être mis à jour soit pour lui ajouter des fonctionnalités soit pour le déboguer.
L'option -U (U majuscule) permet d'effectuer la mise à jour:
#rpm -U
Mise à jour des packages
Pour avoir la liste de tous les packages installés sur le système utiliser la commande:
#rpm -qa
Autres option possibles:
| Donne le nom, la version et le numéro de release du package. |
| Interroge le package associé au fichier dont le nom est passé en argument. |
| Interroge le package. |
| Donne le nom, la description, la release, la taile, la date de compilation, la date d'installation et divers autres renseignements sur le package. |
| Donne la liste des packages associés au package dont le nom est passé en argument. |
Vérification des packages
Utiliser la commande:
#rpm -V quota
Si rien n'a été modifié pour ce package la commande n'indique rien. Sinon la commande renvoie un ou plusieurs des codes suivants:
| Il s'agit d'un fichier de configuration. |
| Le fichier à échoué au test de somme de contrôle MD5. |
| La taille du fichier a changé depuis l'installation. |
| Problème avec les liens symboliques. |
| L'heure de modification du fichier ne correspond pas à l'original. |
| Attribut de périphérique. |
| Le paramètre utilisateur est différent. |
| Le paramètre groupe est différent. |
| Le mode est différent pour l'autorisation ou le type de fichier. |
La recompilation du noyau constitue un savoir faire indispensable pour l'administrateur système notamment sur Linux; cela doit être fait essentiellement dans deux cas:
- Modification du fonctionnement du noyau en cours d'utilisation.
- Evolution du noyau vers une version plus récente; en effet des mises à jour du noyau sont continuellement mises à disposition de la communauté Linux.
Pour connaître la version du noyau en cours utiliser la commande:
#uname -r
la sortie de cette commande ressemble à ce qui suit:
2.0.36
Pour obtenir plus d'informations utiliser la commande uname -a.
Le format du numéro de version est le suivant:
<majeur>.<mineur>.<révision>
ou
| est le numéro de version majeure qui évolue très rarement. |
| est le numéro de version mineure qui indique la "série" en cours. |
| le nombre de corrections effectuées. |
Par convention un numéro de version mineure pair indique une version stable, les révisions ne contenant alors que des corrections de bogues mais jamais de nouveautés.
Les versions mineures impaires sont des versions de développement dont les révisions peuvent contenir tout code que les développeurs désirent ajouter. Lorsqu'une version de ce type atteint un niveau de stabilité et de performance tel qu'il peut être mis à la disposition de la communauté le numéro de version mineure pair est alors incrémenté.
Le noyau officiel est diffusé sous la forme d'une archive tar compressée par gzip, à laquelle il faut ajouter les différentes révisions. L'archive tar contient le code source de la version non révisée.
Le nom de l'archive est au format:
Les révisions contiennent ce que l'on appelle des patches et sont dans des fichiers séparés dont le nom est de la forme:
L'application d'un patch se fait par la commande patch.
Il est possible de se procurer un nouveau noyau par exemple sur internet sur le site suivant:
Une version du noyau 2.2 est disponible sur le CDROM "installation" de la distribution Mandrake 5.3 utilisée ici.
Les fichiers "sources" du noyau doivent impérativement être installés dans le répertoire /usr/src/linux car deux liens symboliques, /usr/include/linux et /usr/include/asm, pointent sur cette arborescence pour permettre au compilateur d'accéder à certains en-têtes lors de la compilation.
Le répertoire linux est contenu dans l'archive. La décompression devra donc se faire dans le répertoire /usr/src.
Avant d'installer les nouveaux fichiers il est nécessaire de transférer les anciens fichiers sources dans un répertoire de sauvegarde.
#cd /usr/src
#mkdir save-old-src
#mv linux* save-old-src
Procéder ensuite à l'extraction de l'archive à l'aide de la commande:
#tar xvzf
qui devrait créer l'arborescence ci-contre.
/usr/src/linux
COPYINGFichier
CREDITSFichier
DocumentationRépertoire
MAINTAINERSFichier
MakefileFichier
READMEFichier
Fichier
archRépertoire
driversRépertoire
extraRépertoire
fsRépertoire
includeRépertoire
initRépertoire
ipcRépertoire
kernelRépertoire
libRépertoire
mmRépertoire
modulesRépertoire
netRépertoire
pcmcia-cs-3.0.5Répertoire
scriptsRépertoire
Arborescence des sources du noyau
Les modules sont des pilotes de périphériques chargeables.
Traditionnellement, les pilotes de périphériques sont intégrés au noyau. Cela implique que l'administrateur doit reconstruire intégralement le noyau chaque fois qu'il ajoute un nouveau pilote au système.
La compilation
Un programme est en général composé de plusieurs fichiers sources (il peuvent être très nombreux!). La génération d'un exécutable passe par deux opérations:
- La compilation de tous les fichiers sources qui va générer pour chaque fichier source un fichier objet binaire mais non exécutable (*.o).
- L'édition des liens qui va permettre d'obtenir le fichier exécutable.
La modification de quelques uns de ces fichiers ne nécessite que la recompilation des fichiers modifiés et l'édition des liens complète. Ces opérations peuvent s'avérer fastidieuses voire complexe pour un non spécialiste du développement.
Il existe sur Unix un utilitaire permettant de s'affranchir de ces tâches: le programme make (/usr/bin/make). Celui-ci, s'appuyant sur un fichier de configuration Makefile, va exécuter toutes ces opérations automatiquement (pour plus d'informations sur cette commande voir annexe 1 page51).
Les opérations à effectuer sont les suivantes:
Make [config|menuconfig|xconfig]
Make dep
Make clean
Make (b)zImage
Make modules
Make modules_install
5.6LANCEMENT DES PROCESSUS
Le document UNIX Développement présente les différents modes de lancement d'un processus (interactif, asynchrone, différé, cyclique). Dans le mode interactif, ou séquentiel, le processus est lancé par le shell. Dans les autres modes il est lancé par un processus indépendant du shell. Un tel processus est appelé deamon (deffered auxiliary execution monitor) dont le rôle est d'exécuter des fonctions spécifiques pour le compte des utilisateurs. Le démon (deamon) le plus connu est cron, il est chargé du lancement des commandes à une date donnée (différée et cyclique). Il existe d'autres démons: init pour le lancement de toutes les activités et lpsched chargé de traiter les requêtes d'impression.
Exécution différée
La commande at permet à un utilisateur, s'il est autorisé, de lancer un processus à une date déterminée. Lorsqu'il lance cette commande at vérifie dans les fichiers /usr/lib/cron/at.allow et (voir manuel de la commande) s'il est autorisé puis place un shell script dans le répertoire /usr/spool/cron/atjobs. Ce shell script contient, entre autres, les commandes à exécuter. Il sera exécuté, puis détruit, par le démon cron à l'heure fixée. Pendant son exécution les sorties standard 1 et 2 seront redirigées vers la boîte aux lettres de l'utilisateur.
La commande batch repose sur les mêmes concepts. Elle est en faite strictement identique à la commande at now.
Exécution cyclique
L'exécution cyclique est prise en charge par le démon cron et par la commande /usr/lib/crontab.
Pour lancer cycliquement une série de commandes il s'agit:
? de créer un fichier dans lequel apparaît la période d'exécution, le nom et les arguments des commandes
? d'exécuter la commande crontab avec le fichier comme argument
Le fichier est de type texte. Il comprend autant de lignes que de commandes à lancer, chaque ligne ayant 6 champs (minutes, heure, jour, mois, jour semaine, commande). Par exemple:
# exemple de fichier
17 5 * * 0 /etc/cleanup > /dev/null
0 2 * * 0,4 /usr/lib/cron/logchecker
20,40 8-16 ** 1-5 /usr/lib/sa/sa2 -s 8:00 -e 18:01 -i 1200 -A
cleanup sera lancée tous les dimanches à 5h17,
logchecker sera lancée les dimanches et jeudis à 2h00,
sa2 sera lancée tous les jours de lundi à vendredi et de 8h00 à 16h00 à 20 et 40
de chaque heure.
La commande crontab est chargée de placer la liste de commandes en file d'attente dans le répertoire /usr/spool/cron/crontabs, une par utilisateur. Le démon cron les explore périodiquement et exécute éventuellement les commandes. Si leurs sorties ne sont pas redirigées, elles le seront vers la boîte aux lettres des utilisateurs. L'administrateur gère les droits d'utilisation du service avec 2 fichiers cron.allowed et placés dans le répertoire /usr/lib/cron (voir le manuel de crontab).
Pour modifier la période d'exécution ou rajouter de nouvelles commandes il est préférable de ne pas modifier directement les files d'attente car cron travaille avec une copie en mémoire de celles-ci. Il est préférable d'utiliser la procédure suivante:
crontab -l > fichier obtient une copie de la file d'attente
vi fichier modifications
crontab fichier lancement d'une nouvelle série
Le démon cron
Il est lancé automatiquement par le système au moment du passage en mode multiutilisateurs. C'est un processus qui est toujours endormi et qui se réveille, soit par une commande de service (at ou crontab), soit par une échéance (date à laquelle une commande doit être lancée). Par exemple:
? après l'exécution de crontabs, il se réveille, scrute les files d'attente, calcule la prochaine échéance et se rendort,
? lorsqu'elle arrive, il se réveille, lance la commande, scrute les files d'attente, recalcule la prochaine échéance et se rendort.
cron archive un historique de ses actions dans le fichier /usr/lib/cron/log si le fichier /etc/default/cron contient CRONLOG=YES. La taille du fichier log peut devenir très grande, il faut donc la surveiller. C'est le rôle du processus périodique /usr/lib/cron/logchecker, lancé par root.
EXERCICES
1) Analyser avec précision les travaux cycliques effectués par le système et les adapter au fait que la machine est arrêtée la nuit et en fin de semaine.
2) Autoriser à certains utilisateurs d'utiliser l'exécution cyclique et l'exécution différée.
3) Générer un fichier d'historique qui stocke les actions de cron.
4) Modifier les exécutions cycliques de root pour que le message "Il est l'heure d'aller manger" soit envoyé, à 11h30, à tous les utilisateurs connectés.
Démarrage du système
Le démarrage du système se fait généralement en deux étapes
- Analyse du matériel ou POST (Power-On Self-Test) exécuté par le BIOS sur un PC.
- Chargement du noyau en mémoire.
Une fois le POST terminé, le code du secteur 0 du disque (MBR - Master Boot Record) est chargé en mémoire.
Ce code va charger le noyau Linux, le fichier /boot/vmlinuz-2.0.36 par exemple. Ce fichier est compressé sur le disque dur et décompressé à la volée au moment du chargement.
La taille de ce noyau est variable car elle dépend des options de configuration qui ont été retenues.
Il est possible d'enrichir le fonctionnement du système sans augmenter cette taille en utilisant les modules.
Au moment de son chargement, le noyau effectue un certain nombre d'analyses et d'initialisations de périphériques. Lors de cette phase de nombreux messages sont affichés à l'écran: ils sont ensuite stockés dans le fichier /proc/kmsg. Il est possible de consulter ce fichier grâce à la commande dmesg.
Une fois les initialisations terminées, le noyau charge le processus init, premier processus et père de tous les processus sur un système Unix.
Ce processus est en particulier le père des shells de connexion sur les consoles virtuelles et séries.
Le processus init utilise le fichier /etc/inittab pour configurer le fonctionnement général du système.
Le fichier /etc/inittab va permettre la configuration du système en fonction du niveau d'exécution (run level) souhaité.
Les run-levels
Un run-level, ou niveau de fonctionnement, est une configuration logicielle du système qui définit l'exécution d'un groupe spécifique de processus.
A l'origine il en existait 3:
| Hors service | Arrêt de la machine |
| Mono-utilisateur | Mode maintenance. Un seul utilisateur peut se connecter sur la machine |
| Multi-utilisateurs | Fonctionnement normal de la machine. |
A l'heure actuelle on retrouve les précédents plus:
| Multi-utilisateurs | Fonctionnement en réseau |
| Inutilisé. | |
| X11 | Démarrage de la machine en mode graphique. |
| Reboot | Provoque la réinitialisation de la machine. |
Le fichier inittab
Ce fichier est orienté ligne, chaque ligne représente une entrée définissant le processus que doit lancer init, ainsi que les conditions de son exécution.
Il est possible d'introduire un commentaire en le faisant précéder du caractère #.
Chaque ligne comprend 4 champs séparés par le caractère :.
| Identifiant l'entrée. Il est formé d'au moins deux caractères alphanumériques (deux seulement dans la plupart des cas). Ce label doit être unique dans le fichier. | ||
| Contient la liste des run-levels concernés par cette entrée. Si ce champs est vide le processus concerné sera lancé pour tous les run-levels. La liste est constituée des identificateurs de run-level juxtaposés. Par exemple si ce champs contient 1235, le processus sera lancé pour les run-levels 1, 2, 3 et 5. | ||
| Ce champs indique de quelle manière le processus doit être lancé. Voir le tableau ci-contre. | ||
| Contient le chemin d'accès complet au programme à lancer. | ||
respawn | Le processus est relancé chaque fois qu'il se termine. | ||
wait | Lorsqu'init entre dans le run-level concerné, le processus est lancé et init doit attendre la fin de son exécution pour continuer. | ||
once | Le processus associé n'est lancé qu'une seule fois. S'il est déjà en train de s'exécuter, il ne sera pas relancé. | ||
boot | Le processus est lancé au démarrage du système. Le champs 2 est ignoré. | ||
bootwait | Identique à boot, mais init attends la fin du processus. | ||
off | Entrée inactivée. Cela permet de créer des entrées sans les activer. | ||
ondemand | Identique à respawn mais associée aux pseudo run-levels a, b et c. Cela permet de demander à init d'entreprendre une action sans qu'il y ait de changement de run-level. | ||
initdefault | Permet d'indiquer à init le run-level par défaut qui sera pris en compte au démarrage du système. Si aucune entrée ne contenant initdefault dans le champs 3 n'existe, c'est à l'administrateur de l'indiquer sur la console. Le champs 4 est ignoré. | ||
sysinit | Le processus est exécuté au démarrage du système, avant les éventuels processus marqués boot et bootwait. De la même manière le champs 2 sera ignoré. | ||
powerwait | Le processus associé est exécuté lorsque init reçoit le signal SIGPWR. init attend la fin du processus avant de continuer. | ||
powerfail | Identique à powerwait mais init n'attends pas la fin du processus. | ||
powerokwait | Le processus associé est lancé par init à condition qu' fichier /etc/powerstatus contenant la chaîne OK, indiquant que l'alimentation est de nouveau assurée. | ||
ctrlaltdel | Le processus associé est exécuté lorsque init reçoit le signal SIGINT. Cela signifie que la séquence de touches CTRL + ALT + DEL a été effectuée. | ||
Liste des options de démarrage du fichier /etc/inittab
Détermination du run-level courant
La commande runlevel permet de connaître le run-level courant ainsi que le précédent le cas échéant.
[root@ethan /root]#runlevel
N 5
Le caractère N indique qu'il n'y a eu aucun changement de run-level depuis le démarrage.
Changement de run-level
La commande init, suivie du numéro de run-level souhaité, permet de changer de run-level.
[root@ethan /root]#init 5
Scripts de démarrage
A chaque niveau sont associés un ou plusieurs script de démarrage. Pour la distribution Mandrake il existe trois fichiers:
- /etc/rc.d/rc
- /etc/rc.d/rc.local
- /etc/rc.d/rc.sysinit
Contenu du fichier #HOME/.bashrc
# .bashrc
# User specific aliases and functions
#alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias mc='mc -c'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
Contenu du fichier #HOME/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=#PATH:#HOME/bin:/opt/kde/bin:.
ENV=#HOME/.bashrc
PS1="_[7m[\u@\h]_[0m"'#PWD#'
USERNAME="root"
export USERNAME ENV PATH PS1
mesg n
alias ls='ls --color'
alias lpr='lpr -P epson'
#setleds -D +num
alias dir='ls -ailF|more'
wellcomeroot
alias dp=". #HOME/bin/defprinter"
PRINTER=`cat #HOME/bin/default-printer`
export PRINTER
Contenu du fichier #HOME/.bash_logout
# ~/.bash_logout
clear
echo "_[10;20H_[7m Salut a toi oh grand ROOT !!! _[0m"
sleep 2
clear
Contenu du fichier /etc/fstab
#
# /etc/fstab
#
# Vous devriez utiliser fstool (control-panel) pour éditer ce fichier!
#
#<device> <mountpoint> <filesystemtype> <options> <dump> <fsckorder>
/dev/sdb5 / ext2 defaults 1 1
/dev/cdrom /mnt/cdrom iso9660 noauto,ro 0 0
/dev/hda5 /mnt/dosdisk1 msdos ignore 0 0
/dev/fd0 /mnt/floppy ext2 noauto 0 0
/dev/hda1 none ignore 0 0 0
/dev/sda1 none ignore 0 0 0
/dev/sdb1 none ignore 0 0 0
/dev/sdb2 none ignore 0 0 0
none /proc proc defaults
/dev/sdb6 none swap sw
ethan:/nfsmnt /mnt/nfs nfs rsize=1024,wsize=1024 0 0
MAKE
SYNTAXE ET UTILISATION
Dans la construction d’un programme
en langage C sous UNIX
Prenons comme exemple le schéma classique d'une application composée d'un certain nombre d'exécutables; chaque exécutable est le résultat d'une édition de liens groupant un certain nombre de fichiers binaires, (qui peuvent être communs à plusieurs exécutables); chaque fichier binaire est le résultat de la compilation d'un fichier source pouvant faire référence à plusieurs autres fichiers sources d'inclusion (par exemple, les fameux fichiers "include" d'un source écrit en langage C).
Bien entendu, et ce qui est généralement le cas car ils existent pour cela, un fichier d'inclusion peut être référencé dans plusieurs fichiers sources.
Lorsque l'on modifie des fichiers sources, comment peut-on être sûr que l’application soit bien mise à jour ?
2 solutions viennent à l'esprit:
Première solution:
Minimise le temps calculateur mais augmente le travail du programmeur:
Se rappeler quels sont les fichiers sources modifiés; si un source modifié est un fichier d'inclusion, chercher quels sont les fichiers sources dans lesquels celui-ci est référencé, et lancer les compilations correspondantes. Chercher ensuite dans quelles éditions de lien entrent les fichiers binaires résultant de ces compilations, et ne lancer que ces éditions de lien.
Nous ne parlons pas ici, pour ne pas trop compliquer l'exemple, de fichiers d'inclusion référencés dans d'autres fichiers d’inclusion, ( cela peut arriver ) .
Deuxième solution:
Simplifie le travail du programmeur, mais augmente celui du calculateur:
Lancer systématiquement l'ensemble des compilations et éditions de liens qui reconstruisent l'application, au besoin à l'aide d'un fichier de commandes. Ceci, bien entendu, dans un environnement multi-utilisateurs peut entraîner si plusieurs programmeurs utilisent simultanément cette manière de travailler, l'écroulement des performances du calculateur de développement.
Entre ces deux (mauvaises) solutions, laquelle choisir?
Sous UNIX, il existe une troisième solution: Utiliser l'outil "make" standard dans tout système UNIX.
Appelé outil de maintenance, de mise à jour et de construction automatique de programmes, make minimise à la fois la tâche du programmeur, et le temps calculateur utilisé pour reconstruire un programme après une création ou une modification de fichiers. Une bonne utilisation du système UNIX comme système de développement est inconcevable sans l'utilisation de cet outil qui, soulignons le, est standard dans tout système UNIX.
Bien compris et bien utilisé make résume le développement du logiciel à une série de cycles tenant en ces quatre mots :
C'est dire l'importance particulière de cet outil
On remarquera qu'entre l'édition de texte et les tests, les travaux de compilation et d'édition des liens deviennent transparents pour l'utilisateur, ceux-ci étant gérés par make.
Prenons un fichier CibleFile qui dépend d'un fichier SourceFile. La dépendance signifie que: si SourceFile est modifié, il faut reconstruire CibleFile en lançant la commande "Action".
cela peut se traduire par la notation :
CibleFile: SourceFile
Action
Make utilise l'algorithme suivant:
SI (CibleFile est plus ancien que SourceFile)
OU
Si (CibleFile n'existe pas et SourceFile existe)
ALORS
Exécuter ACTION
make s'appuie sur un fichier appelé fichier de description ou fichier Makefile dans lequel, suivant une certaine syntaxe, sont décrits comme dans l'exemple ci-dessus, les fichiers Cible, Source et les actions à lancer, en principe pour créer CibleFile à partir de SourceFile.
Dans l'exemple donné, le fichier CibleFile est appelé la cible, le fichier SourceFile est appelé la dépendance, et la commande Action est appelée la règle de production.
La ligne CibleFile : SourceFile est appelée la règle de dépendance.
Exemple :
Un exécutable prog est le résultat de l'édition de lien des fichiers binaires mod1.o, mod2.o et mod3.o. Le fichier binaire mod1.o est le résultat de la compilation du fichier source, écrit en langage C: mod1.c. De même, mod2.o est le résultat de la compilation du source mod2.c qui contient le fichier d'inclusion inc1.h; le binaire mod3.o est le résultat de la compilation du source mod3.c qui contient les fichiers d'inclusion inc1.h et inc2.h.
Ceci peut être représenté par le graphe de dépendances suivant :
Attention, il serait erroné de croire que c'est le fichier source qui dépend d'une modification d'un fichier d'inclusion qu'il référence. (exemple que mod3.c dépend de inc1.h et de inc2.h). En fait, make considère que c'est au niveau de l'objet mod3.o qu'une modification de inc1.h ou de inc2.h se fera sentir .
Le graphe de dépendances se traduit dans le fichier Makefile par:
fichier Makefile traduisant le graphe de dépendances
# Edition des liens du programme
prog : mod1.o mod2.o mod3.o
cc mod1.o mod2.o mod3.o -o prog
# Compilation des différents fichiers
# composant le programme
mod1.o : mod1.c
cc -c mod1.c
mod2.o : mod2.c inc1.h
cc -c mod2.c
mod3.o : mod3.c inc1.h inc2.h
cc -c mod3.c
Fin du fichier fichier Makefile
On distingue dans ce fichier les lignes commençant par un # qui sont des lignes de commentaires; les lignes commençant en colonne 1 qui sont les règles de dépendance, et les lignes commençant par le caractère "tabulation" qui sont les règles de production.
Dans les règles de dépendance, les cibles sont les fichiers à gauche des ":", les dépendances sont les fichiers à droite des ":"
Les commentaires (précédés de #) peuvent se trouver surtoutes les lignes. Une ligne logique peut s’étaler sur plusieurs lignes physiques du fichier, si on utilise le caractère " \ " à la fin des lignes qui se poursuivent sur la ligne suivante.
Supposons que les heures de dernière modification des fichiers soient les suivantes (pour simplifier toutes heures sont supposées être du même jour.
prog : 12h.00
mod1.o : 09h.25
mod2.o : 11h 05
mod3.o : 10h.35
mod1.c : 09h.20
mod2.c : 10h.05
mod3.c : 10h.15
inc1.h : 09h.10
inc2.h : 10h.40
Quel est le travail nécessaire et suffisant à lancer pour être sûr que le programme prog soit bien à jour sur les modifications de ses sources ?
Une étude attentive des dates de dernières modifications des différents fichiers laisse apparaître que le fichier inc2.h est plus récent que le fichier mod3.o, il sera donc nécessaire et suffisant de lancer la compilation de mod3.c et l'édition de lien pour reconstruire prog.
L'utilisateur de make, ayant créé le fichier Makefile précédant n'a pas bien sûr à se poser de telles questions, et à considérer les dates de dernière révision de ses fichiers; il lance la commande et il obtient les actions suivantes (en gras ce que l'utilisateur rentre au clavier, en normal ce que le calculateur répond sur l’écran):
%make
cc -c mod3.c
cc mod1.o mod2.o mod3.o -o prog
%
Le fichier Makefile peut être grandement simplifié make connaissant implicitement certaines règles.
Par exemple make sait que pour construire un fichier objet (caractérisé par son suffixe ".o") à partir d'un fichier source C (caractérisé par son suffixe ".c", il faut lancer la règle "cc -c", avec pour paramètre, le nom du fichier source .
Dans le fichier Makefile pris en exemple, la ligne
cc -c mod1.c
est connue implicitement par make et peut donc être omise dans le fichier Makefile. De même, make sait implicitement que s'il existe un fichier source C (exemple mod2.c) dans le répertoire courant, et que la cible à reconstruire est un binaire mod2.o, alors ce binaire dépend de ce source.
Par contre, make ne sait pas implicitement de quels fichiers d'inclusion dépend un fichier binaire, ni quels sont les fichiers binaires intervenant dans une édition de lien.
Grâce aux règles implicites, le fichier Makefile peut être simplifié de la manière suivante:
fichier Makefile simplifié en tenant compte des règles implicites
prog : mod1.o mod2.o mod3.o
cc mod1.o mod2.o mod3.o -o prog
mod2.o : inc1.h
mod3.o : inc1.h inc2.h
Fin du fichier Makefile
Par ses règles implicites, make peut reconstruire certaines cibles, sans fichier de fichier Makefile.
exemple:
s'il existe dans le répertoire courant, un fichier mod4.c, le simple appel à make, sans fichier de description, avec le fichier mod4.o en paramètre, lance la compilation.
%make mod4.o
cc -c mod4.c
Le lecteur est invité à prendre un premier contact avec make de cette manière. Bien entendu, les règles données explicitement ont le pas sur les règles implicites.
Les macros permettent de paramètrer un fichier Makefile. La syntaxe de définition d'une macro est la suivante.
Nom macro = chaîne de caractères
Quand make interprète le fichier Makefile, il remplace l'expression #(Nom macro) par la valeur "chaîne de caractères"
Exemple:
Le fichier Makefile précédant aurait pu s'écrire:
fichier Makefile utilisant la macro OBJ
OBJ = mod1.o mod2.o mod3.o
prog : #(OBJ)
cc #(OBJ) -o prog
mod2.o : inc1.h
mod3.o : inc1.h inc2.h
Fin du fichier Makefile
Ceci est particulièrement intéressant si l'on veut ajouter (ou supprimer) un objet intervenant dans l'édition de lien. Il suffit alors de modifier la macro OBJ, et le nouvel objet est alors connu, partout où l'expression #(OBJ) est utilisée dans le fichier Makefile.
Les macros peuvent être définies à l'extérieur du fichier Makefile, en paramètres de la commande lançant make:
Le fichier Makefile suivant permet de choisir le nom de l'exécutable à partir de la commande lançant make:
fichier Makefile avec une macro définie extérieurement
EXEC =
OBJ = mod1.o mod2.o mod3.o
#(EXEC) : #(OBJ ) ·
cc #(OBJ) -o #(EXEC)
mod2.o : inc1.h
mod3.o : inc1.h inc2.h
Fin du fichier Makefile
on lance alors la commande :
%make "EXEC = nouveau nom"
cc mod1.o mod2.o mod3.o -o nouveau nom
%
si une macro, définie dans le fichier Makefile, est redéfinie dans la ligne de commande, c'est la macro définie dans la ligne de commande qui a le pas sur celle définie dans le fichier Makefile. Dans l'exemple ci dessus, le lancement de make sans paramètre pour préciser la macro EXEC aboutirait à une erreur. Une façon de faire, conforme aux conventions de l’éditeur de lien d’UNIX, serait alors la suivante:
fichier Makefile avec une valeur par défaut pour EXEC
EXEC = a.out
OBJ = mod1. o mod2. 0 mod3.o
#(EXEC) : #(OBJ)
cc #(OBJ) -o #(EXEC)
mod2.o : inc1.h
mod3.o : inc1.h inc2.h
Fin du fichier Makefile
si l'utilisateur ne précise pas la macro EXEC dans sa ligne de commande, l'exécutable produit s'appellera a.out
Des macros permettent de généraliser certaines lignes du fichier Makefile. Parmi elles, 4 sont particulièrement importantes: #@ , #* , #< et #?
#@
est remplacé par le nom du fichier cible (avec son suffixe).
#*
est remplacé par le nom du fichier cible (sans son suffixe).
#<
est remplacé par le nom du fichier dépendances à partir duquel, la cible est reconstruite.
#?
est remplacé par la liste des noms de fichiers dépendance, dont la date de dernière modification est plus récente que celle de la cible.
Exemple :
Le fichier Makefile pris en exemple pourrait s'écrire:
fichier Makefile avec utilisation de macros spéciales
OBJ = mod1.o mod2.o mod3.o
prog : #(OBJ)
cc #(OBJ) -o #@
mod2.o : inc1.h
cc -c #*.c
mod3.o : inc1.h inc2.h
cc -c #<
@echo 'les modifications sur #? \ entraînent la reconstruction de #@
Fin du fichier Makefile
On remarquera que les commandes du fichier Makefile précédant:
" cc -c #< "
et
" cc -c #*.c "
sontéquivalentes.
Si on modifie les fichiers inc1.h et mod3.c, nous obtiendrons :
%make
cc -c mod2.c
cc -c mod3.c
les modifications sur inc1.h mod3.c entraînent la reconstruction de mod3.o
cc mod1.o mod2.o mod3.o -o prog
make sait comment lancer un certain nombre d'actions, en se basant sur les suffixes des fichiers (voir chap. 3); par exemple make connaît les commandes à lancer pour passer d'un fichier ".c" à un fichier ".o", d'un fichier ".y" (YACC) ou ".l" (LEX) à unfichier ".c"
L'utilisateur peut étendre les connaissances implicites de make en ajoutant ses propres règles dans le fichier Makefile. Pour cela, il doit définir deux catégories de règles: lesrègles. de précédence et lesrègles d'inférence.
Les règles de précédence agissant d'après les suffixes des fichiers, peuvent être définies explicitement, dans le fichier Makefile, par la directive .SUFFIXES
make connaît implicitement un certain nombre de suffixes:
Entre autres :
.o qui est le suffixe caractérisant un fichier objet.
.c qui est le suffixe caractérisant un fichier source C
.f qui est le suffixe caractérisant un fichier source Fortran
.s qui est le suffixe caractérisant un fichier source
assembleur (as)
ces suffixes sont définis implicitement, dans make, de la manière suivante:
SUFIXES : .o .c .f .s
Les règles de précédence permettent de résoudre le problème suivant:
supposons qu'il existe, dans son répertoire courant, un fichier source C et un fichier source Assembleur de même nom. seul le suffixe permet à make de différencier les deux fichiers. Quel fichier make va choisir pour construire le fichier objet correspondant '
make vabalayer la liste des suffixes de gauche à. droite et reconstruire le fichier dont le suffixe, caractérisant le type de source, est le plus près du suffixe caractérisant le fichier cible. Ici dans les précédence: .o .c .f .S, c’est le suffixe .c qui est le plus proche du .o donc make va reconstruire le binaire à partir du source C et non pas du source Assembleur.
Exemple :
Si l'utilisateur veut construire des fichiers objets (.o) à partir de fichiers Sources Pascal (.pas) ou de fichiers sources Assembleur (.as68), il définit dans son fichier Makefile:
SUFFIXES: # Suppression des suffixes implicites
SUFFIXES: .o .pas . as68 # Addition nouveaux suffixes
make cherchera alors, pour construire un fichier objet, s'il existe dans le répertoire courant, un fichier de suffixe .pas et sinon un fichier de suffixe .as68
La directive .SUFFIXES : suivie d'un retour chariot permet d'annuler les règles de précédence implicites. On définit alors ses propres règles.
Si on omet la directive .SUFFIXES: suivie de retour chariot, les règles de précédence définies par l’utilisateur sont ajoutées à la suite des règles de précédence implicites!
Les règles de précédence étant définies, il reste à indiquer à make quelles actions lancer, pour passer d'un fichier avec un certain suffixe, à un fichier avec un autre suffixe. Ce sont les règles d'inférence.
La syntaxe est la suivante:
:
Action
.SRC est le suffixe du fichier à partir duquel on reconstruit la cible.
.CIB est le suffixe du fichier cible à reconstruire
Action est la règle de production qui sera appliquée pour reconstruire la cible.
Exemple:
La règle d'inférence implicite pour construire un fichier objet (.o) à partir d'un fichier source C (.C) est définie de la manière suivante:
c.o :
cc -c #<
Remarque: La syntaxe suivante est aussi correcte:
.c.o : ; cc -c #<
Supposons que le répertoire courant contienne des fichiers sources Assembleur 68000 (de suffixe .sa) et des fichiers source Pascal 68000 (de suffixe .pas). On veut utiliser un fichier Makefile qui permette de construire des fichiers binaires (de suffixe .ro) à partir, soit des sources Assembleur, soit des sources Pascal.
Le fichier Makefile suivant permet de résoudre le problème:
fichier Makefile pour Assemblage ou Compilation de fichiers 68000
#
# règles de précédence
#
SUFFIXES :
SUFFIXES : .ro .pas . sa
#
# règles d'inférence
#
:
p68 #*
masm #*
: ;masm #*
Fin du fichier Makefile
Les directives sont des mots réservés, qui, introduits dans le fichier de description, affectent le fonctionnement de make. Leurs effets s'appliquent à l'ensemble des actions contenues dans le fichier de description.
.SILENT
En fonctionnement normal, les règles de production sont affichées sur le fichier standard de sortie, avant d'être exécutées. Avec cette directive, elles ne sont pas affichées .
Cet effet est aussi obtenu pour chaque règle de production commençant par le caractère @.
.IGNORE
En fonctionnement normal, si une règle de production retourne un code différent de 0 (signe, en principe, qu'un problème est intervenu durant son exécution), cela entraîne l'arrêt de make. Avec cette directive, make continue .
Cet effet est aussi obtenu pour chaque règle de production commençant par le caractère -.
.PRECIOUS
En fonctionnement normal, si l'utilisateur arrête l'exécution de make, la cible reconstruite et les fichiers intermédiaires sont détruits.
Les fichiers dont le nom figure dans la liste associée à cette directive ne sont pas détruits.
.DEFAULT
Si aucune règle de production explicite ou implicite n'existe pour reconstruire une cible, les actions associées à cette directive sont exécutées.
.SUFFIXES.
".SUFFIXES :" suivi d'un retour chariot sert à supprimer les règles de précédences implicites.
".SUFFIXES :" suivi d'une liste de suffixes, ajoute ces suffixes à la liste des suffixes implicites ·
fichier Makefile utilisant des directives
.PRECIOUS mod2.o
# si un interrupt ou un Quit interviennent alors
# que mod2.o est reconstruit, mod2.o ne sera pas
# détruit.
.DEFAULT
echo " #@ n'existe pas "
# Quand mod4.o doit être reconstruit, le message
# "mod4.o n'existe pas" va être affiché sur le
# fichier standard de sortie.
OBJ = mod1.o mod2.o mod3.o
prog : #(OBJ) mod4.o
@cc #(OBJ) -o prog
# cette ligne n'est pas écrite sur le fichier
# standard de sortie. .
mod2.o : inc1.h
-cc -c mod2.c
# Si la compilation retourne un code non
# nul, on passe quand même à l'édition de lien de
# prog.
mod3.o : inc1.h inc2.h
Fin du fichier Makefile
On remarquera la règle de production de prog qui commence par le caractère "@", et la règle de production de mod2.o qui commence par le caractère "-".
Dans la règle de production associée à la .directive .DEFAULT, en fait, on verra apparaître sur le fichier standard de sortie, les deux phrases: '
echo "mod4.o n'existe pas"
mod4.o n'existe pas .
La première des deux phrase (parasite) aurait pu être évitée, si on avait écrit à la place, la règle de production, en utilisant le caractère de début de règle : @
@echo "mod4 . o n ' existe pas".
Jusque là, tous les fichiers traités par make se trouvent dans le même répertoire. Cela n'est pas une obligation.
Supposons que prog soit dans un répertoire r_prog, mod1.c et mod1.o dans un répertoire r_prog/r_mod1, mod2.c et mod2.o dans un répertoire r_prog/r_mod2, mod3.c et mod3.o dans un répertoire r_prog/r_mod3, et les fichier include inc1.h et inc2.h , dans le répertoire r_prog/include
Le fichier Makefile suivant, situé sur le répertoire r_prog permet d'obtenir, en lançant make sur ce répertoire, un fichier exécutable prog.
fichier Makefile allant chercher des fichiers sur différents répertoires
OBJ = mod1.o mod2.o mod3.o
prog : etap1 etap2 etap3
ln mod1.o r_modl/mod1.o
ln mod2.o r_mod2/mod2.o
ln mod3.o r_mod3/mod3.o
cc #(OBJ) -o prog
rm #(OBJ)
etap1 :
cd r_mod1;make
etap2 :
cd r_mod2;Make
etaD3 :
cd r_mod3;make
Fin du fichier Makefile .
Sur le répertoire r_mod1 un fichier Makefile est inutile, car make utilise, pour reconstruire mod1.o, qui ne dépend que de mod1.c, les règles implicites de dépendances et de productions.
Sur le répertoire r mod2, seul doit être indiqué dans le fichier Makefile, la dépendance entre mod2. o et inc1.h. La règle de production est implicite. Le fichier Makefile pourrait être le suivant :
fichier Makefile sur r_prog/r_mod2
mod2.o : ../include/inc1.h
Fin du fichier Makefile
De même, sur r_mod3, le fichier Makefile pourrait également sedéduire au fichier suivant: .
fichier Makefile sur r_prog/r_mod3
mod3.o : ../include/inc1.h ../include/inc2.h
Fin de fichier Makefile
Le fichier Makefile produisant prog, sur le répertoire r_prog, appelle plusieurs commentaires :
1- Pour qu'une édition de lien puisse se faire (par cc), les " fichiers objets doivent se trouver, ou être référencés sur le répertoire d'où on lance la commande . cc. Dans le cas présent, les fichiers objets sont produits sur d'autres répertoires. Il faut donc établir des "links", ou des copies, des fichiers objets correspondants, sur le répertoire de travail. Une fois la compilation faite, on peut détruire, sur le répertoire courant, les fichiers objets, ou leurs références, désormais inutiles. Il existe des versions évoluées de make qui intègrent des solutions à ce genre de problème (exemple BUILD).
2- Nous voyons que la commande make ' peut être appelée dans un fichier Makefile. Par cette méthode, il est possible, à partir d'une seule commande make, de lancer make sur tous les répertoires d'une arborescence. cette méthode comporte un piège. Pour le à comprendre, il faut connaître cornent make procède pour lancer une règle 'de production.
Toute règle de production, lancée par make, est passée à un processus fils. Lorsque la règle est terminée, il y a retour au processus père, donc perte ' de l'environnement dans lequel la dernière règle de production s'est exécutée. Donc, si une règle de. production change l'environnement, après son exécution , on retrouve l'environnement précédent .
Les deux règles de dépendance :
cd nouv_répertoire
make
ne donneront pas l'effet désiré. En effet, la commande: "cd nouv_répertoire" une fois exécutée, on retourne au répertoire de départ, où on exécute la deuxième commande : " make"
Ce problème peut être résolu en plaçant, dans une seule règle de production, toutes les · commandes à lancer, séparées. par le caractère ";":
cd nouv_repertoire; make
La syntaxe de la commande make est la suivante:
%make [ options ] [ définition des macros ] [ cibles ]
"options", "définition des macros" et "cibles" sont optionnelles dans la commande .
La définition des macros a été décrite dans le paragraphe 4.
Plusieurs macros peuvent être définies dans la ligne de commande .
Par défaut, si aucune cible n’apparaît dans la ligne de commande lançant make, celui ci va construire son graphe de dépendances à partir de la première cible rencontrée (prog dans l'exemple) .
Il est possible de définir d'autres cibles dans la ligne 'de commandes. Par exemple on peut ne reconstruire que les binaires mod2:o et mod3.o en lançant la commande :
%make mod2.o mod3.o
Les options sont des lettres précédées d'un tiret. Les différentes options possibles sont:
%make [-f nom de fichier] [-piksrnbemtqd]
Les options les plus utilisées sont:
-f nom de fichier
permet de choisir un fichier de description
exemple:
make -f .
-p
sort la liste des macrodéfinitions et la description des cibles.
-i
produit le même effet que la directive .IGNORE
-s
produit les mêmes effets que la directive .SILENT
-n
sort les règles de production, sur la sortie standard, sans les exécuter (permet de mettre au point un fichier Makefile).
-t
met les dates de dernière modification des cibles à la date de lancement de make (sans lancer effectivement les règles de production).
%make -d pour tracer le travail de make, etmettre au point la reconstruction d'une Application.
SCCS (Source Code Control system) est l'utilitaire de gestion de l'archivage et des versions de fichiers sources. SCCS est standard sur les systèmes UNIX (version Bell Labs).
Un fichier source est archivé la première fois dans SCCS par la commande admin. Ilest tiré ensuite de cette archive, en lecture seule, par la commande get, et en lecture/écriture par la commande get @e. Dans ce dernier cas, les différences entre le fichier modifié et le fichier source initial sont remises dans l'archive SCCS par la commande delta, et le numéro de version/révision du fichier source . est automatiquement incrémenté . *
Etre dans une archive SCCS peut être la situation "normale" d'un source, sous UNIX. L'utilitaire make, des versions d'UNIX qui offrent ce mode d'archivage, peut rechercher directement la date de dernière modification d'un fichier dans l'archive SCCS.
make cherche un fichier source dans une archive SCCS si, dans les règles de dépendance, ce fichier source est suivi du caractère "" .
Les fichiers sources de l'exemple seront recherchés dans des archives SCCS, si le fichier Makefile est le suivant:
fichier Makefile tirant les sources à partir d'archives SCCS
prog : mod1.o mod2.o mod3.o
cc mod1.o mod2.o mod3.o -o prog
mod1.o : mod1.c
mod2.o: mod2.c
inc1 . h" ,
mod3.o : mod3.c inc1.h inc2.h
Fin du fichier Makefile
Les règles implicites de make permettent de reconstruire un binaire, soit à ' partir d'un source du répertoire courant, soit si ce source n'existe pas, dans le répertoire où on le cherche, de le tirer d'une archive SCCS.
Un objet est archivé dans une librairie par la commande ar. Pour archiver, par exemple, les binaires mod2.o et mod3.o dans une librairie lib, on fera:
%ar rv lib mod2.o
%ar rv lib mod3.o
make permet de mettre à jour les librairies par des règles implicites, et une nouvelle notation.
Les règles implicites d'inférence, pour les objets reconstruits à partir de sources, en langage C, sont les suivantes :
.c.a:
#(CC) -c #(CFLAGS) #<
ar rv #@ #*.o
rm -f #*.o
Ces règles implicites peuvent être utilisées, par make, si on ajoute dans le fichier Makefile, la règle de dépendance suivante:
lib : lib (mod2.o) lib (mod3.o)
Si make rencontre, dans une règle de dépendance, des parenthèses, il déduit que le nom du fichier à l'intérieur de la parenthèse (exemples mod2.o) est un binaire, et la partie à l'extérieur de la parenthèse (exemple: lib) est le nom de la librairie qui le contient.
make développera les macros spéciales de la règle de production implicite "ar rv #@ #*.o" qui place le fichier binaire mod2.o dans la librairie lib, de la manière suivante:
#@ est remplacé par lib
#* est remplacé par mod2 .
Il est ainsi possible de maintenir une librairie. Si par exemple, le fichier source mod3.c a une date de dernière modification plus récente que celle de la librairie lib.a; make lancera les actions suivantes:
%make
cc -c mod3.c
ar rv lib mod3.o
rm -f mod3.o
1 - S.I. Feldman, "make - a program for maintaining computer program", software - Practice and Experience, Vol 9 No 4 pp. 256-265 April 1979.
2 - Augmented Version of Make, rsïx system V Release2.0, Support pools Guide , pp. 3 . 1-3 . 19 April 1984.
3 - v.B. Erickson and J.F. @ellegrin, Build - A Software construction @ool, A@&m Bell Laboratories - :echnical Journal vol 63 No 6 Part 2 pp. 1049-1059, July-AuguSt 1984.
1
UNIX est une marque déposée par les Laboratoires BELL.