Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Archive for May, 2007

Niveau :      
Résumé : hdparm -z || blktool reread-part

Il ne faut pas confondre ce qui est enregistré sur disque et ce qui est en cours d'utilisation par le logiciel. Ceci est valable en beaucoup d'endroits (fichiers de configuration par exemple), c'est aussi valable pour les partitions.

Lorsque vous allumez votre machine, le noyau scanne la table des partitions de vos disques une seule fois et l'enregistre en mémoire. Toute modification que vous pourriez faire par la suite ne sera pas prise en compte. Par conséquent lorsque vous modifiez une table de partition (avec fdisk par exemple), la modification n'est pas directement prise en compte. Mais il n'est pas nécessaire pour autant de rebooter. En effet, il existe un appel système qui permet de demander au noyau de relire la table des partitions. Et celui-ci est appelé automatiquement par fdisk ou cfdisk lorsqu'une modification a été faite (ouf !).

Alors pourquoi toute cette histoire me direz-vous ? Hé bien il existe 2 cas où vous pourriez avoir besoin de faire cet appel vous-même. Tout d'abord si vous êtes expérimentateur dans l'âme et que vous modifiez votre table des partitions à la main.

Ensuite, si vous modifiez un disque dont une des partitions est montée le noyau refusera de relire la table. A vous de démonter les partitions nécessaires avant de relancer la commande magique :

$ hdparm -z /dev/hda

Pour ceux qui voudraient s'ancrer dans la modernité et utiliser les nouveaux outils :

$ blktool /dev/hda reread-part

Notez que dans le cas où votre disque modifié contient '/', rien à faire, vous serez obligé de rebooter pour relire la table (à moins que vous ne soyez capable de démonter / :-). Pour ceux qui voudraient chercher, il est possible de démonter / (enfin de le remplacer par un autre) avec la commande pivot_root ...

Niveau :      
Résumé : tail | head <= sed

Supposons que vous ayez un gros fichier et que vous vouliez récupérer les lignes 200 à 235. Votre premier réflexe sera sûrement :

$ head -n 235 file.txt | tail -n 35

Oui, mais en pratique cela revient a faire lire le fichier par 2 processus, ce qui pour un gros fichier peut être particulièrement consommateur de ressources. Utilisez plutôt la commande suivante qui fait le tout en une seule passe (et qui vous évitera de faire une soustraction) :

$ sed -n '200,235p' file.txt

Oui, mais vous aimeriez bien ne pas avoir à mesurer les numéros des lignes que vous voulez récupérer. Qu'à cela ne tienne, vous pouvez utiliser autre chose que des numéros de ligne pour l'extraction. Par exemple des expressions régulières :

$ sed -n '/^Begin/,/^End/p' file.txt

Vous pouvez aussi faire le contraire, c'est-à-dire supprimer des lignes plutôt que de les sélectionner :

$ sed '/^Begin/,/^End/d' file.txt

Et cerise sur le gâteau, vous pouvez appliquer une expression de substitution uniquement aux lignes concernées :

$ sed '/^Begin/,/^End/s/search.*/replace/' file.txt

Niveau :      
Résumé : vi /etc/inittab

Init

Init est un démon comme beaucoup d'autres, il a besoin d'un fichier de configuration. Celui-ci s'appelle /etc/inittab. Comme beaucoup le savent, ce fichier contient la définition des runlevel (pour connaître le niveau en cours, utilisez la commande /sbin/runlevel) et des processus associés. Mais il peut aussi faire des choses bien plus passionnantes. Ex :

1:2345:respawn:/sbin/getty 38400 tty1
  • Le premier paramètre est un identifiant choisi par vous (ou votre distribution).
  • Ensuite on trouve la liste des runlevel pour lesquels la directive est valable.
  • Suivi de la directive elle même.
  • Et enfin la commande associée à la directive.

Attention, si vous êtes sur une ubuntu, le paquet sysvinit (init standard qui date de l'époque des pyramides) a été remplacé par upstart qui gère le processus de boot un peu différemment. Vous retrouverez donc les fonctionnalités équivalentes (ou presque) dans /etc/event.d (à vous de trouver les fichiers a modifier :-).

Configuration

L'une des directives de configuration d'init est ctrlaltdel. Elle permet de définir ce qui se passe lorsque quelqu'un appuie sur les célèbres touches ctrl-alt-del. Par défaut cela lance un reboot propre de la machine, mais si vous êtes en train de mettre en place une machine publique (comme dans un cybercafé), vous ne voulez pas que les utilisateurs puissent le faire.

Il vous suffit de remplacer la commande par une commande vide pour que la combinaison ne fasse rien. Vous pouvez aussi la remplacer par un arrêt de la machine, une vérification automatique des partitions ou toute autre commande exécutable.

ca:12345:ctrlaltdel:/sbin/fsck -A

C'est aussi à cet endroit que vous pouvez gérer ce qui se passe en cas de coupure de courant (normalement init est alerté de ces coupures). Ceci avec les directives powerwait, powerfail, powerokwait, powerfailnow et grâce au fait que les processus de monitoring ups sont censés avertir init lorsqu'un événement surgit.

Une dernière option intéressante : kbrequest. Elle associe une commande au signal KeyboardSignal. Signal que vous devez associer à une combinaison de touches de la console (fichier /etc/console-tools/remap pour ceux qui ont le paquet console-tools d'installé). Ex:

# /etc/inittab
kb::kbrequest:/bin/echo "OK ca marche"
# /etc/console-tools/remap
# ctrl-alt-end
control alt keycode 107 = KeyboardSignal

PS : Savez vous qui est David Bradley ?

Niveau :      
Résumé : bash fork & exec

Supposons que vous ayez un script que vous voulez faire tourner en arrière plan. Par exemple un script d'init qui s'obstine à vous bloquer le processus de boot alors que vous savez pertinemment qu'il n'est pas indispensable à la suite du processus (pur exemple).

Comment faire ceci simplement ?

Méthode 1 : vous créez un script stub

Écrivez un deuxième script exécutable qui sera appelé à la place du premier et contenant :

#!/bin/sh
/votre/script "$@" &

Inconvénient, vous avez maintenant 2 scripts à gérer et il vous faut changer soit le nom du script original, soit les chemins d'appels. De plus votre 2e script dépend du chemin du premier.

Méthode 2 : vous "démonisez" votre script

Et c'est maintenant que bison futé fait son apparition. L'expérience a fait de bison futé un bison rôdé à toutes les ornières de la route du sysadmin bienheureux.

Voici donc la ligne miracle à déposer en début du script à lancer en arrière plan :

[ -z "$FORK" ] && { FORK=1 $0 "$@" & exit; }

Explications :

  • [ ] -> lance un test
  • -z -> la chaîne à tester est vide (pas encore de fork)
  • && -> équivalent du if, si ce qui est à gauche est vrai on continue l'évaluation
  • { } -> groupe de sous commandes sans sous shell
  • FORK=1 -> variable d'environnement (car juste avant une commande)
  • $0 -> exécute le script dans lequel on est (-> avec FORK à 1 -> false pour le test initial)
  • "$@" -> passe en argument au script exactement ceux qu'on vient de recevoir correctement séparés par des " (pour les espaces)
  • & -> lance la commande précédente en arrière plan, pas besoin de ; après &
  • exit -> arrête définitivement le script en cours (le père)
  • ; -> indispensable à la fin de { }

En résumé, on fait un fork avec les même paramètres + une variable FORK=1 en arière plan et on quitte le script en cours. Dans processus ainsi créé, on continue comme si de rien n'était.

Niveau :      
Résumé : htop ; top -b

Un grand nombre de processus tourne en permanence sur votre machine. Certains sont plus importants que d'autres et certains sont plus consommateurs en ressources (RAM, processeur ...).

Comme vous le savez tous, toutes ces informations sont disponibles à travers la commande top.

$ top

Mais si vous utilisez encore la commande top, vous êtes has been. Il existe maintenant un équivalent qui propose les couleurs, et surtout, la possibilité de scroller facilement (avec les flèches) dans la liste des processus.

# installer le paquet htop si besoin
$ htop 

En dehors de ce coté pratique, htop fournit sensiblement les mêmes informations que top.

Alors devez-vous jeter top à la poubelle ?
Non car il existe une fonction bien pratique de top : le mode batch. Ce mode permet à top d'afficher son contenu une unique fois, mais pour l'intégralité des processus :

$ top -b

Ceci permet d'utiliser les informations disponibles depuis top dans un script. Vous me ferez la remarque que ps peut normalement donner ces informations et vous aurez raison. Mais on ne sait jamais ...

Niveau :      
Résumé : nice -n 19 ; renice 19 -p 1234

Lorsque vous lancez un processus gourmand en ressources, il arrive que vous sachiez d'avance que celui-ci prendra du temps. Dans ce cas, vous acceptez qu'il ne consomme pas le maximum de ressources de la machine dont il est capable, pour que celle-ci puisse continuer à fonctionner normalement (répondre aux commandes shell par exemple).

Si vous êtes prévoyants, vous pouvez utiliser la commande nice :

$ nice -n 19 ./poid-lourd

Nice utilise des niveaux de priorité. Ces niveaux sont compris entre -20 (priorité absolue) et +20 (tout le monde passe avant). Les valeurs négatives ne peuvent être utilisées que par l'utilisateur root. Pour connaître le nice d'un processus, la commande top affiche la valeur pour chaque processus dans la colonne NI.

Un processus hérite du nice de son père par défaut (en général 0 car init est à 0). Mais il se peut que vous vouliez changer cette valeur après coup. Pour cela il existe la commande renice :

# 1234 est un pid
$ renice 10 1234

Attention toutefois, un utilisateur normal ne peut qu'augmenter la valeur de nice (et donc réduire la priorité d'un processus). Seul root peut la réduire (et éventuellement lui donner une valeur négative).

Faites attention, utiliser des valeurs négatives fortes peut bloquer indéfiniment votre système.

Niveau :      
Résumé : uuidgen

Il existe une commande vous permettant de créer un identifiant garanti unique. C'est un identifiant sur 128 bits de la forme XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.

Notez que 128 bits c'est la taille des adresse ipv6. Cela signifie qu'il est possible d'en générer 1000 milliards toutes les nanosecondes pendant 10 milliards d'années et de les avoir tous différents.

Un uuid (universaly unique identifier) peut être créé de plusieurs façons :

  • aléatoirement (unicité très probable)
  • adresse mac + nombre de dixièmes de microsecondes depuis le calendrier grégorien (unicité par machine et par date de création)
  • hash md5 d'une uri (unicité par uri)
  • hash sha-1 (idem)

Pour créer un tel uuid pour vos propres besoins, vous pouvez soit utiliser la commande uuidgen soit utiliser http://www.famkruithof.net/uuid/uuidgen

Pourquoi utiliser de tels identifiants ?

  • pour identifier votre matériel (code barre ...)
  • pour identifier un élément unique dans votre logiciel (les types de partition ont un uuid par exemple) de façon universelle (valable en tout temps sur toutes les machines)
  • pour créer un fichier / identifiant base de données / ... garanti unique