Compare commits

..

19 commits

Author SHA1 Message Date
Alpinux
044d1c45e6 Reprendre la documentation de déploiement, qui vivait dans alpinux-owni
Ce dépôt d'infrastructure décrit la machine ; le déploiement de ce site-ci le
regarde lui, et le tenir ailleurs garantissait qu'il divergerait du code qu'il
décrit.

Repris tel quel depuis alpinux-owni/docs/, où il est supprimé en retour.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFbwnJurBwTs7x7t93ecku
2026-09-27 13:00:18 +02:00
Alpinux
b13d33a2d5 Guide installer mint : modification des chemins poir les scripts 2026-09-26 00:01:12 +02:00
Cédrix
3c2773c7fa Faire prendre les scripts sur le serveur de la salle, d'abord
Le guide donnait l'adresse Internet en premier et l'adresse locale comme
raccourci. C'est l'inverse de ce qui se passe : en install party, la machine
n'a pas encore de réseau qui sorte, et c'est le serveur de la salle qui répond.
Les trois téléchargements commencent donc par « http://alpicache.lan », le nom
plutôt que l'adresse, puisqu'il suit le réseau si celui-ci doit déménager. Les
quatre noms servis ont été vérifiés sur la machine.

Un encadré donne le repli une fois pour toutes — « alpicache », « apt-proxy »,
« 10.0.0.1 » — cette dernière adresse valant même quand la résolution de noms
n'est pas encore en place. C'était jusqu'ici la seule adresse citée, sans que
rien n'explique laquelle essayer ni pourquoi.

Les adresses Internet, elles, désignent désormais alpinux.scripts, dépôt propre
à ces trois fichiers, sur sa branche « stable » : celle que le serveur
redistribue, et non celle où l'on travaille.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BssvzfDMeXVoUQHEcnavW7
2026-09-26 00:00:52 +02:00
Cédrix
15e50ff49b Compter les caractères et non les octets, dans le tableau des disques
Ces trois correctifs avaient été éprouvés sur alpicache jeudi soir — commit
5d606ab du dépôt du serveur, 22 h 56 — cinq minutes après que ce dépôt-ci ait
repris le relevé. Ils n'ont donc jamais été versés ici, et la version amont,
celle que le serveur redistribue, les ignorait. Les voilà.

« printf %-10s » compte les octets : « mécanique » en pèse dix pour neuf
signes, et le tableau des disques glissait d'un cran à partir de la deuxième
colonne. La fonction « colonne » compte les caractères, ce que Bash sait faire
quand la locale le permet — d'où la locale forcée plutôt qu'espérée.

Le contrôle affiche par ailleurs les chiffres sur lesquels il se fonde, et pas
seulement ce qui cloche : modèle, type, taille, état SMART, heures de marche
pour un disque mécanique ou usure pour un SSD, et les trois compteurs de
secteurs. On peut répondre à qui demande comment se porte son disque, même
quand tout va bien.

Cette version est désormais identique, au seul en-tête d'usage près, à celle
qui tourne sur la machine.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BssvzfDMeXVoUQHEcnavW7
2026-09-25 23:02:56 +02:00
Alpinux
c1a6d1f9a4 Guide installer mint : modification deposition du cadre 2026-09-25 22:37:17 +02:00
7818a39532 Verser le relevé de fiche matérielle dans le dépôt (#12) 2026-09-24 22:40:10 +00:00
6063e32443 Documenter le serveur qu'on emporte en install party (#11) 2026-09-24 22:39:17 +00:00
Alpinux
10110a9d6e Faire télécharger les deux scripts, sans quoi le relevé ne part jamais
install.sh n'appelle le relevé que s'il le trouve à côté de lui, et le
guide ne faisait télécharger qu'install.sh : dans le cas nominal, la
fiche n'aurait jamais été relevée.

Les deux fichiers se prennent maintenant ensemble, et un encadré dit
pourquoi — téléchargé seul, install.sh fonctionne, simplement sans
relevé.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:59:08 +02:00
Alpinux
1f2bb9f6f4 Faire voyager le verdict avec la fiche, au lieu de le refaire au serveur
Sur une machine réelle, un HP 250 G4 affichait devant son propriétaire
« NE PAS INSTALLER EN L'ÉTAT — 976 secteurs en attente », et apparaissait
« sain » sur le tableau de bord. La fiche ne transportait que le compteur
de secteurs réalloués, nul sur ce disque, et le serveur rejugeait
là-dessus. Deux juges, deux verdicts, et c'est le rassurant qu'on lisait.

Le verdict part désormais avec la fiche — champs « verdict » et
« motifs », ces derniers débarrassés de leurs couleurs — et le serveur
les affiche sans rien recalculer. Un seul juge, celui qui a vu le disque.

Les trois compteurs SMART cessent d'être confondus : les secteurs
réalloués disent l'usure et se comptent, ceux en attente et les
illisibles disent une panne en cours, et un seul suffit à déclencher
l'alerte. Ce ne sont pas des secteurs fatigués mais des données que le
disque n'arrive plus à relire. Les deux nouveaux compteurs voyagent aussi
dans la fiche.

Le relevé se chronomètre enfin, sur la collecte seule : la pause du
verdict attend quelqu'un devant l'écran, la mesurer reviendrait à
chronométrer la personne.

Constat, correctifs et version de référence : session alpicache.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:56:13 +02:00
Alpinux
c428d1d040 Reprendre le relevé éprouvé sur machine, avec ses trois correctifs
La session alpicache a essayé le relevé sur une machine réelle et en a
tiré trois défauts, tous vérifiés là-bas :

Le verdict ne sortait qu'en session live. Relancé après installation, le
relevé ne disait donc rien de l'état des disques — précisément ce dont on
voulait parler au propriétaire pendant qu'il est encore là. Il sort
maintenant à tous les coups, sauf en mode --montrer.

Un disque mécanique n'était signalé qu'au-delà de cinq ans de marche, ce
qui laissait passer sans un mot un disque de trois ans — alors que c'est
le premier frein d'une machine par ailleurs correcte. Il se signale
désormais quel que soit son âge, qui est simplement rappelé.

Le verdict défilait sans que personne ne le lise : trois secondes quand
tout va bien, vingt avec des réserves, et il attend une touche — deux
minutes au plus — quand il dit de ne pas installer. Jamais indéfiniment,
ni du tout sans terminal : le script tourne aussi appelé par install.sh.

La détection de session live est reprise dans sa version, plus fine que
celle que j'avais faite : /cdrom et /rofs comptent de nouveau, mais
seulement montés, et pour /cdrom seulement avec un système de fichiers
de média. Un répertoire vide ne prouve plus rien.

Seul l'en-tête reste de moi : le script se prend dans ce dépôt, pas sur
le serveur.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:41:19 +02:00
Alpinux
3d6635fd52 alpi-fiche : ne plus prendre un /cdrom vide pour une session live
L'installateur de Mint laisse derrière lui un /cdrom vide sur la machine
installée. La détection s'y fiait, et déclarait donc « session live » des
machines parfaitement installées — ce qui fausse aussi le chronométrage,
puisqu'il se calcule entre les deux relevés.

Restent les deux signes qui ne mentent pas : la racine montée en overlay
ou squashfs, et boot=casper sur la ligne du noyau. /rofs disparaît avec
/cdrom, n'ayant pas plus de valeur probante.

Constat de la session alpicache, sur une machine réelle. Je n'ai pas pu
le reproduire moi-même — la machine d'essai ne se laissait pas piloter —
mais le changement est sûr dans les deux sens : ces deux signes-là sont
présents sur toute session live, et aucun ne l'est sur un système
installé.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:38:04 +02:00
Alpinux
10f97b5048 Verser le relevé de fiche matérielle dans le dépôt
La demande initiale faisait télécharger un script depuis alpicache et
l'exécuter en root sur la machine de chaque participant. Le relevé est
désormais versionné ici, relu comme le reste, et appelé localement : rien
n'est tiré du réseau, rien n'est exécuté sans avoir été publié.

Le script vient de la session alpicache, éprouvé sur place. Il relève le
modèle, le processeur, la mémoire et le détail de ses connecteurs, les
disques et leur état SMART, puis envoie la fiche au serveur de la salle.
Depuis une session live, il rend en plus un verdict — bon, avec réserves,
ou ne pas installer — que le bénévole peut opposer à un disque qui
faiblit pendant que la machine est encore là.

install.sh l'appelle en tête de fichier, dans sa passe root, et seulement
s'il le trouve à côté de lui : une machine qui rejoue le script chez son
propriétaire n'envoie rien à personne.

L'en-tête du relevé disait « rien qui touche à la personne ». C'était
inexact : la fiche emporte le nom de la machine — souvent un prénom — et
l'adresse matérielle de la carte réseau. Les deux sont maintenant
nommés, dans le script comme dans le guide, avec la consigne qui va
avec : le dire à la personne dont on installe l'ordinateur.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:37:36 +02:00
6a82dbfd81 Ne pas régénérer GRUB quand il est déjà configuré (#15) 2026-09-24 20:34:59 +00:00
Cédrix
369a7f2b82 Ne pas régénérer GRUB quand il est déjà configuré
update-grub lance os-prober, qui sonde toutes les partitions à la recherche
d'autres systèmes, puis régénère la configuration entière : vingt à trente
secondes par machine, payées jusqu'ici même lorsqu'il n'y avait rien à changer.
Sur une install party de quinze machines, cela se voit.

La fonction vérifie donc d'abord, et sort si les deux réglages sont là.

Deux défauts corrigés au passage. Le sed insérait ses lignes avec
l'indentation du script : /etc/default/grub se retrouvait avec des directives
décalées, que GRUB accepte mais qui trompent la lecture quand on vient
déboguer. Et il ne faisait rien du tout si « GRUB_DEFAULT=0 » avait disparu,
ce qui arrive dès qu'un autre outil est passé avant nous — les deux lignes sont
désormais ajoutées si elles manquent, plutôt qu'insérées avant une ligne qui
peut ne plus exister.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XLTJ8DoPfvhZMK5Yxtrfx2
2026-09-24 22:34:39 +02:00
Alpinux
7074cbdc73 Corriger la correspondance des noms de code Mint
Je l'avais écrite de mémoire, et de mémoire elle était fausse : Xia
donnée pour la 22.2, Wilma pour la 22.1, et Zara absente alors que c'est
elle qui occupe la 22.2. Relevé par la session alpicache, recoupé sur
l'historique des versions de Linux Mint.

L'erreur n'était pas anodine ici : c'est par ces noms que le
pré-chargement désigne ce qu'il va tirer. Quelqu'un qui suivait la page
pour préparer une 22.2 aurait garni le cache de la 22.1, et s'en serait
aperçu le samedi matin — précisément ce que l'encadré cherche à éviter.

La correspondance est maintenant donnée en tableau, série 21 comprise.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:20:27 +02:00
Alpinux
7ea3e145a9 Rappeler que le cache ne sert que les versions qu'il connaît
Le 24/09, la première Mint 22.3 de la soirée a tiré 1,3 Go d'Internet
pour 82 Mo servis par le cache : le pré-chargeur visait encore les
versions précédentes. Une version absente de la liste ne profite à
personne, et cela ne se voit qu'au compteur.

Les noms de code sont donnés, puisque c'est par eux que le pré-chargement
désigne les versions : Zena pour la 22.3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:18:22 +02:00
Alpinux
593eb05fe2 Ajouter la panne du cache qui s'est produite ce soir
apt renvoyait des « 503 Connection closed » en série et une installation
Mint s'est arrêtée là-dessus : le cache acceptait les requêtes sans
savoir où aller les chercher.

Le piège mérite d'être écrit, parce qu'il envoie chercher au mauvais
endroit : interroger le cache directement répondait parfaitement pendant
ce temps. Un bénévole qui teste ainsi conclut que tout va bien et
retourne fouiller la machine du participant.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:07:31 +02:00
Alpinux
a7eb79ceb1 Nommer la vue des noyaux comme le gestionnaire la nomme
« Analyseur de noyaux » n'existe pas : la vue s'ouvre par Affichage →
Noyaux Linux. Écrit de mémoire, vérifié ce soir sur la machine d'essai —
c'est la deuxième fois que cette page décrit une commande qui n'est pas
là, après les niveaux de mise à jour.

Elle s'ouvre d'ailleurs sur un avertissement qui méritait sa place ici :
un noyau plus récent peut coûter le Wi-Fi, l'accélération graphique ou
l'affichage, et la sortie de secours — Maj au démarrage, Advanced
options, noyau antérieur — se connaît avant d'en avoir besoin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:07:20 +02:00
Alpinux
c2fbd50a7f Documenter le serveur qu'on emporte en install party
Le guide d'installation envoie chercher des scripts sur http://10.0.0.1/
sans jamais dire ce qu'est cette adresse, et le wiki ne mentionnait nulle
part le cache de paquets — alors que c'est lui qui rend possible quinze
installations simultanées sur la ligne d'une salle des fêtes.

La page décrit ce qu'un bénévole doit en savoir sur place : le réseau de
la salle et pourquoi les postes se branchent sur le switch et jamais sur
la box, les trois adresses utiles (page de santé, mandataire du cache,
scripts), les quatre cartes à surveiller, et surtout le geste qui change
tout — le mandataire à saisir pendant l'installation de Debian, contre
auto-apt-proxy installé après coup pour Mint et Ubuntu.

Puis ce qui coince : la salle sans réseau et le téléphone en secours, le
disque du cache à brancher avant d'allumer, et l'adresse en 169.254 qui
trahit un poste qui n'a reçu aucune réponse.

La configuration de la machine reste dans son propre dépôt : cette page
renvoie vers lui plutôt que de le recopier, et n'expose rien de ce qui
touche à son accès.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BE4rvHVETRoWnYNDTGssdo
2026-09-24 22:07:20 +02:00
9 changed files with 620 additions and 62 deletions

View file

@ -1,7 +1,8 @@
#!/bin/bash #!/bin/bash
# Relève la fiche d'une machine, et l'envoie au serveur de l'install party. # Relève la fiche d'une machine, et l'envoie au serveur de l'install party.
# #
# À récupérer depuis le dépôt du wiki, comme les autres scripts d'Alpinux : # Ce script vit dans le dépôt du wiki, à côté d'install.sh : il est lu et
# versionné comme lui, et c'est de là qu'il faut le prendre.
# #
# wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-wiki/raw/branch/main/code/linux/linux-mint/alpi-fiche.sh # wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-wiki/raw/branch/main/code/linux/linux-mint/alpi-fiche.sh
# chmod +x alpi-fiche.sh # chmod +x alpi-fiche.sh
@ -18,25 +19,22 @@
# mémoire et un disque mécanique qui commence à réallouer des secteurs répond # mémoire et un disque mécanique qui commence à réallouer des secteurs répond
# à la question avant de l'avoir posée. # à la question avant de l'avoir posée.
# #
# Ce qui est envoyé, et rien d'autre : le modèle et la marque, les quatre # Ce qui est envoyé : le modèle, le processeur, la mémoire, les disques et
# derniers caractères du numéro de série, la date du BIOS, le processeur, la # leur santé, le système installé.
# mémoire et le détail de ses connecteurs, les disques avec leur santé SMART,
# l'occupation des systèmes de fichiers, le système installé, l'architecture,
# l'adresse matérielle de l'interface réseau et le nom de la machine.
# #
# Ni nom d'utilisateur, ni fichiers, ni historique, ni adresse IP publique. # Deux de ces champs touchent à la personne, et il faut le dire plutôt que de
# prétendre le contraire — la première version de cet en-tête annonçait « rien
# qui touche à la personne », ce qui était faux :
# #
# Deux réserves à connaître avant de s'en servir, parce qu'elles concernent # · le NOM DE LA MACHINE, choisi pendant l'installation, contient très
# des gens et pas des machines : # souvent un prénom ;
# · l'ADRESSE MATÉRIELLE de la carte réseau identifie durablement l'appareil.
# #
# - le **nom de la machine** est celui choisi pendant l'installation, et il # Les deux servent : le nom pour s'y retrouver, l'adresse pour rapprocher la
# contient souvent un prénom (« portable-jean ») ; # fiche du bail DHCP. Mais ils appartiennent à la personne dont on installe
# - l'**adresse matérielle** identifie durablement la carte réseau ; elle # l'ordinateur — il faut le lui dire. Ne sont en revanche jamais envoyés : son
# sert ici à rapprocher la fiche du bail DHCP, rien de plus. # nom d'utilisateur, ses fichiers, son historique, ni rien de ce qu'elle a
# # installé. Le numéro de série est tronqué à quatre caractères.
# Le relevé part en clair sur le réseau local de la salle, vers le serveur de
# l'association, et n'en sort pas. Prévenez-en la personne dont vous installez
# la machine : c'est la sienne.
# #
# alpi-fiche relève et envoie # alpi-fiche relève et envoie
# alpi-fiche --montrer relève et affiche, sans rien envoyer # alpi-fiche --montrer relève et affiche, sans rien envoyer
@ -49,6 +47,27 @@
set -u set -u
# Bash ne compte les caractères — et non les octets — que si la locale le dit.
# C'est ce qui aligne les colonnes du tableau des disques.
export LC_ALL="${LC_ALL:-C.UTF-8}"
# Le temps que met la collecte, en millisecondes.
#
# Une machine n'est relevée qu'une fois quand elle n'a pas connu de session
# live : il n'y a alors pas d'écart entre deux passages à mesurer. Cette durée-
# ci existe toujours, et elle se compare — elle dit ce que la machine met à
# s'interroger elle-même : lire le SMART de ses disques, réveiller ceux qui
# dorment, énumérer ses barrettes. Un plateau qui rame se voit là.
#
# On arrête le chronomètre à la fin de la collecte, avant le verdict : celui-ci
# attend une touche, et l'on mesurerait la personne devant l'écran.
DEBUT_NS="$(date +%s%N 2>/dev/null || echo 0)"
# smartctl et dmidecode vivent dans /usr/sbin, que le PATH d'un shell ordinaire
# ne contient pas toujours — un « command -v » y échouait alors que le binaire
# était là.
PATH="$PATH:/usr/sbin:/sbin"
SERVEUR="${ALPI_SERVEUR:-http://alpicache.lan}" SERVEUR="${ALPI_SERVEUR:-http://alpicache.lan}"
MONTRER=0 MONTRER=0
CHECK=0 CHECK=0
@ -63,6 +82,41 @@ else
V=""; O=""; R=""; B=""; D=""; Z="" V=""; O=""; R=""; B=""; D=""; Z=""
fi fi
# Ce dont le relevé a besoin, et qu'il installe lui-même plutôt que de rendre
# un verdict à trous.
#
# « état des disques inconnu » n'aide personne : c'est précisément la réponse
# qu'on était venu chercher. Les deux paquets pèsent moins de deux mégaoctets,
# ils sont dans le cache, et l'installation prend deux secondes sur le réseau
# de l'install party. On ne le fait qu'en root, qu'avec apt, et sans rien
# demander d'autre.
completer_outils() {
[ "$(id -u)" = "0" ] || return 0
command -v apt-get >/dev/null 2>&1 || return 0
local manquants=""
command -v smartctl >/dev/null 2>&1 || manquants="$manquants smartmontools"
command -v dmidecode >/dev/null 2>&1 || manquants="$manquants dmidecode"
[ -z "$manquants" ] && return 0
echo "==> Installation de ce qui manque au relevé :$manquants"
# Par le cache s'il répond, directement sinon. « -qq » pour ne pas noyer
# l'écran : ce n'est pas l'objet de la manœuvre.
local proxy=""
if command -v wget >/dev/null 2>&1 \
&& wget -q --spider --timeout=3 "$SERVEUR/" 2>/dev/null; then
proxy="-o Acquire::http::Proxy=http://apt-proxy:3142"
fi
DEBIAN_FRONTEND=noninteractive apt-get $proxy -qq -y install $manquants \
>/dev/null 2>&1 \
|| echo " (échec — le relevé se fera sans)"
# Ce qui vient d'arriver est dans /usr/sbin, que le PATH d'un shell
# ordinaire ne contient pas toujours.
PATH="$PATH:/usr/sbin:/sbin"
}
completer_outils
lire_dmi() { lire_dmi() {
cat "/sys/class/dmi/id/$1" 2>/dev/null | tr -d '\n' | sed 's/^ *//; s/ *$//' cat "/sys/class/dmi/id/$1" 2>/dev/null | tr -d '\n' | sed 's/^ *//; s/ *$//'
} }
@ -111,13 +165,9 @@ ARCHITECTURE="$(uname -m)"
# ajoute « boot=casper » ou « boot=live » sur la ligne de commande du noyau. # ajoute « boot=casper » ou « boot=live » sur la ligne de commande du noyau.
# #
# L'existence de /cdrom ou de /rofs, elle, ne prouve rien : l'installateur de # L'existence de /cdrom ou de /rofs, elle, ne prouve rien : l'installateur de
# Mint laisse un /cdrom vide derrière lui. La première version de ce test a # Mint laisse un /cdrom vide derrière lui, et la première version de ce script
# donc déclaré « session live » une machine parfaitement installée — constaté # a donc déclaré « session live » une machine parfaitement installée. On ne les
# le 24/09/2026 sur un HP 250 G4. Ce n'est pas anodin : la durée d'une # retient que s'ils sont réellement montés.
# installation se mesure entre le relevé d'avant et celui d'après, et deux
# relevés « avant » ne se soustraient pas. On ne retient donc ces répertoires
# que s'ils sont réellement montés, et montés depuis un support en lecture
# seule.
MOMENT="post-installation" MOMENT="post-installation"
if findmnt -n -o FSTYPE / 2>/dev/null | grep -qE '^(overlay|aufs|squashfs)$' \ if findmnt -n -o FSTYPE / 2>/dev/null | grep -qE '^(overlay|aufs|squashfs)$' \
|| grep -qE '(^| )boot=(casper|live)( |$)' /proc/cmdline 2>/dev/null \ || grep -qE '(^| )boot=(casper|live)( |$)' /proc/cmdline 2>/dev/null \
@ -199,6 +249,27 @@ $(champ detail "$detail")}"
fi fi
BARRETTES="$BARRETTES]" BARRETTES="$BARRETTES]"
TABLE_DISQUES=""
# Remplir une colonne à la bonne largeur.
#
# « printf %-10s » compte les octets, pas les caractères : « mécanique » en
# pèse dix pour neuf signes, et la colonne suivante glisse d'un cran. Bash,
# lui, sait compter les caractères quand la locale est en UTF-8 — on lui
# laisse ce travail, et l'on force la locale plutôt que d'espérer.
colonne() {
local texte="$1" largeur="$2" cote="${3:-gauche}" n
n=${#texte}
if [ "$n" -gt "$largeur" ]; then
printf '%s' "${texte:0:$largeur}"
return
fi
local blancs=""
while [ "$n" -lt "$largeur" ]; do blancs="$blancs "; n=$((n + 1)); done
if [ "$cote" = droite ]; then printf '%s%s' "$blancs" "$texte"
else printf '%s%s' "$texte" "$blancs"; fi
}
# --- Les disques ----------------------------------------------------------- # --- Les disques -----------------------------------------------------------
# #
# lsblk donne la taille et le type ; le drapeau « rotational » du noyau # lsblk donne la taille et le type ; le drapeau « rotational » du noyau
@ -220,21 +291,85 @@ for chemin in /sys/block/*; do
# L'état SMART, s'il est lisible. Sans smartctl on ne prétend rien. # L'état SMART, s'il est lisible. Sans smartctl on ne prétend rien.
sante="" sante=""
reallocations="" reallocations=""
pending=""
illisibles=""
heures="" heures=""
usure=""
ecrit=""
if command -v smartctl >/dev/null 2>&1; then if command -v smartctl >/dev/null 2>&1; then
sortie="$(smartctl -H -A "/dev/$nom" 2>/dev/null)" sortie="$(smartctl -H -A "/dev/$nom" 2>/dev/null)"
sante="$(printf '%s' "$sortie" | grep -iE 'overall-health|SMART Health' \ sante="$(printf '%s' "$sortie" | grep -iE 'overall-health|SMART Health' \
| sed 's/.*: *//' | head -1)" | sed 's/.*: *//' | head -1)"
reallocations="$(printf '%s' "$sortie" \ reallocations="$(printf '%s' "$sortie" \
| awk '/Reallocated_Sector_Ct|Reallocated_Event/{print $10; exit}')" | awk '/Reallocated_Sector_Ct|Reallocated_Event/{print $10; exit}')"
# Les secteurs que le disque n'arrive plus à lire. Ils manquaient à la
# fiche, et c'est ce qui a fait qu'alpicache annonçait « sain » un
# disque déclaré à remplacer : il ne les avait jamais reçus.
pending="$(printf '%s' "$sortie" | awk '$2 == "Current_Pending_Sector"{print $10; exit}')"
illisibles="$(printf '%s' "$sortie" | awk '$2 == "Offline_Uncorrectable"{print $10; exit}')"
heures="$(printf '%s' "$sortie" | awk '/Power_On_Hours/{print $10; exit}')" heures="$(printf '%s' "$sortie" | awk '/Power_On_Hours/{print $10; exit}')"
# L'usure d'un SSD, en pour cent de vie consommée.
#
# Un disque mécanique s'use en tournant, un SSD en écrivant : les
# heures de marche ne disent rien de son état. Chaque constructeur a
# son attribut, et deux conventions coexistent — les uns comptent ce
# qui est consommé, les autres ce qui reste. On ramène tout à
# « consommé », qui est le sens qu'on veut lire. NVMe donne directement
# « Percentage Used » ; pour les SATA, la colonne VALUE part de 100 et
# descend.
usure="$(printf '%s' "$sortie" | awk '/Percentage Used:/{gsub(/[^0-9]/,"",$3); print $3; exit}')"
if [ -z "$usure" ]; then
usure="$(printf '%s' "$sortie" | awk '
/Media_Wearout_Indicator|Wear_Leveling_Count|SSD_Life_Left|Percent_Lifetime_Remain/ {
if ($4 ~ /^[0-9]+$/ && $4 <= 100) { print 100 - $4; exit }
}')"
fi
# Ce que le disque a écrit depuis sa mise en service : l'autre façon de
# juger un SSD, dont les modèles courants tiennent 100 à 600 To.
ecrit="$(printf '%s' "$sortie" | awk '
/Total_LBAs_Written|Host_Writes_32MiB|Total_Host_Writes/ {
if ($10 ~ /^[0-9]+$/) { print $10; exit }
}
/Data Units Written:/ { gsub(/[^0-9]/,"",$4); print $4; exit }')"
fi fi
# Les mêmes chiffres, mis en table pour être lus par quelqu'un. Le verdict
# ne dit que ce qui cloche ; on veut aussi voir ce qui va, et sur quoi le
# verdict se fonde.
taille_go="$(awk -v o="$taille" 'BEGIN{printf "%.1f", o/1000000000}' | tr . ,)"
secteurs="—"
for valeur in "${pending:-0}" "${illisibles:-0}" "${reallocations:-0}"; do
case "$valeur" in ''|*[!0-9]*) continue ;; esac
[ "$valeur" -gt 0 ] && secteurs="!"
done
[ "$secteurs" = "!" ] && secteurs="$(printf '%s/%s/%s' \
"${reallocations:-0}" "${pending:-0}" "${illisibles:-0}")"
usure_dite="—"
if [ "$rotatif" = 1 ]; then
case "$heures" in ''|*[!0-9]*) ;; *)
usure_dite="$heures h"
[ "$heures" -ge 8760 ] && usure_dite="$usure_dite ($(( heures / 8760 )),$(( (heures % 8760) * 10 / 8760 )) an)" ;;
esac
else
case "$usure" in ''|*[!0-9]*) ;; *) usure_dite="usé à $usure %" ;; esac
fi
TABLE_DISQUES="$TABLE_DISQUES$(
colonne "$nom" 7; printf ' '
colonne "${modele:-—}" 20; printf ' '
colonne "$([ "$rotatif" = 1 ] && echo mécanique || echo SSD)" 10; printf ' '
colonne "$taille_go Go" 10 droite; printf ' '
colonne "${sante:-—}" 8; printf ' '
colonne "$usure_dite" 16; printf ' '
printf '%s' "$secteurs")"$'\n'
[ "$premier" = 0 ] && DISQUES="$DISQUES," [ "$premier" = 0 ] && DISQUES="$DISQUES,"
premier=0 premier=0
DISQUES="$DISQUES{$(champ nom "$nom"),$(champ modele "$modele"),\ DISQUES="$DISQUES{$(champ nom "$nom"),$(champ modele "$modele"),\
\"octets\":$taille,$(champ type "$([ "$rotatif" = 1 ] && echo mécanique || echo SSD)"),\ \"octets\":$taille,$(champ type "$([ "$rotatif" = 1 ] && echo mécanique || echo SSD)"),\
$(champ sante "$sante"),$(champ reallocations "$reallocations"),$(champ heures "$heures")}" $(champ sante "$sante"),$(champ reallocations "$reallocations"),\
$(champ pending "$pending"),$(champ illisibles "$illisibles"),$(champ heures "$heures"),\
$(champ usure "$usure"),$(champ ecrit "$ecrit")}"
done done
DISQUES="$DISQUES]" DISQUES="$DISQUES]"
@ -271,6 +406,19 @@ $(champ vitesse_memoire "$VITESSE_MEMOIRE"),\
\"slots_total\":$SLOTS_TOTAL,\"slots_pris\":$SLOTS_PRIS,\"barrettes\":$BARRETTES,\ \"slots_total\":$SLOTS_TOTAL,\"slots_pris\":$SLOTS_PRIS,\"barrettes\":$BARRETTES,\
\"disques\":$DISQUES,\"occupation\":$OCCUPATION}" \"disques\":$DISQUES,\"occupation\":$OCCUPATION}"
DUREE_MS=0
case "$DEBUT_NS" in
''|*[!0-9]*) ;;
0) ;;
*) FIN_NS="$(date +%s%N 2>/dev/null || echo 0)"
case "$FIN_NS" in
''|*[!0-9]*|0) ;;
*) DUREE_MS=$(( (FIN_NS - DEBUT_NS) / 1000000 )) ;;
esac ;;
esac
[ "$DUREE_MS" -lt 0 ] && DUREE_MS=0
RAPPORT="${RAPPORT%\}},\"duree_releve_ms\":$DUREE_MS}"
if [ "$MONTRER" = 1 ]; then if [ "$MONTRER" = 1 ]; then
if command -v python3 >/dev/null 2>&1; then if command -v python3 >/dev/null 2>&1; then
printf '%s' "$RAPPORT" | python3 -m json.tool 2>/dev/null || printf '%s\n' "$RAPPORT" printf '%s' "$RAPPORT" | python3 -m json.tool 2>/dev/null || printf '%s\n' "$RAPPORT"
@ -295,6 +443,8 @@ fi
echo "Système : $SYSTEME" echo "Système : $SYSTEME"
echo echo
MOTIFS=""
# --- Le verdict ------------------------------------------------------------ # --- Le verdict ------------------------------------------------------------
# #
# Trois réponses possibles, et une seule question : peut-on installer sur cette # Trois réponses possibles, et une seule question : peut-on installer sur cette
@ -302,9 +452,11 @@ echo
# d'un idéal — une machine de dix ans avec 4 Go et un disque sain fait très # d'un idéal — une machine de dix ans avec 4 Go et un disque sain fait très
# bien l'affaire, et c'est souvent celle qu'on nous apporte. # bien l'affaire, et c'est souvent celle qu'on nous apporte.
# Depuis une session live, le verdict est tout l'intérêt de l'exercice : on # Le verdict sort toujours, live ou non. C'est l'information qu'on est venu
# le rend sans qu'on ait à le demander. # chercher : la première version ne le rendait qu'en session live, et le
[ "$MOMENT" = "live" ] && CHECK=1 # relevé d'après installation défilait sans rien dire de l'état des disques —
# précisément ce dont on voulait parler au propriétaire.
[ "$MONTRER" = 1 ] || CHECK=1
if [ "$CHECK" = 1 ]; then if [ "$CHECK" = 1 ]; then
GRAVITE=0 # 0 rien à signaler · 1 à surveiller · 2 ne pas installer GRAVITE=0 # 0 rien à signaler · 1 à surveiller · 2 ne pas installer
@ -313,6 +465,17 @@ if [ "$CHECK" = 1 ]; then
note() { note() {
[ "$1" -gt "$GRAVITE" ] && GRAVITE="$1" [ "$1" -gt "$GRAVITE" ] && GRAVITE="$1"
REMARQUES="$REMARQUES$2"$'\n' REMARQUES="$REMARQUES$2"$'\n'
# Le même motif, débarrassé de ses couleurs et de ses retours à la
# ligne, pour qu'alpicache dise exactement ce qui a été dit ici.
if [ "$1" -ge 1 ]; then
# Une note tient sur plusieurs lignes à l'écran ; le motif, lui,
# est d'un seul tenant — il ira dans une case de tableau.
nu="$(printf '%s' "$2" | tr '\n' ' ' | sed -e 's/\x1b\[[0-9;]*m//g' \
-e 's/[[:space:]]\{1,\}/ /g' \
-e 's/^ *[!?✗·] *//' \
-e 's/^ *//' -e 's/ *$//')"
[ -n "$nu" ] && MOTIFS="$MOTIFS$nu"$'\n'
fi
} }
# Les disques. C'est pour eux qu'on fait ce contrôle. # Les disques. C'est pour eux qu'on fait ce contrôle.
@ -333,25 +496,112 @@ if [ "$CHECK" = 1 ]; then
if printf '%s' "$sortie" | grep -qiE 'overall-health.*(FAILED|FAILING)'; then if printf '%s' "$sortie" | grep -qiE 'overall-health.*(FAILED|FAILING)'; then
note 2 " ${R}✗${Z} ${B}/dev/$nom se déclare défaillant${Z} — ne pas installer dessus." note 2 " ${R}✗${Z} ${B}/dev/$nom se déclare défaillant${Z} — ne pas installer dessus."
fi fi
# Les trois attributs ne disent pas la même chose, et les confondre
# revient à sous-estimer les deux qui comptent.
#
# Reallocated_Sector_Ct des secteurs déjà remplacés par la réserve
# du disque. Quelques-uns sont de l'usure
# ordinaire ; c'est leur nombre qui parle.
# Current_Pending_Sector des secteurs que le disque n'arrive plus à
# lire et n'a pas encore pu déplacer. Ce
# qu'ils contenaient est en train d'être
# perdu. Un seul suffit à s'inquiéter.
# Offline_Uncorrectable des secteurs définitivement illisibles.
#
# Les deux derniers ne sont pas de l'usure mais une panne en cours :
# on ne les mesure pas à la même aune que le premier.
for attribut in Reallocated_Sector_Ct Current_Pending_Sector Offline_Uncorrectable; do for attribut in Reallocated_Sector_Ct Current_Pending_Sector Offline_Uncorrectable; do
valeur="$(printf '%s' "$sortie" | awk -v a="$attribut" '$2 == a {print $10; exit}')" valeur="$(printf '%s' "$sortie" | awk -v a="$attribut" '$2 == a {print $10; exit}')"
case "$valeur" in ''|*[!0-9]*) continue ;; esac case "$valeur" in ''|*[!0-9]*) continue ;; esac
[ "$valeur" = "0" ] && continue [ "$valeur" = "0" ] && continue
if [ "$valeur" -ge 50 ]; then case "$attribut" in
note 2 " ${R}✗${Z} /dev/$nom : $valeur $attribut — disque à remplacer." Reallocated_Sector_Ct)
else libelle="secteur(s) déjà remplacé(s)"
note 1 " ${O}!${Z} /dev/$nom : $valeur $attribut — à surveiller." if [ "$valeur" -ge 50 ]; then
fi note 2 " ${R}✗${Z} /dev/$nom : ${B}$valeur $libelle${Z} — disque à remplacer."
else
note 1 " ${O}!${Z} /dev/$nom : $valeur $libelle — à surveiller."
fi ;;
Current_Pending_Sector)
note 2 " ${R}✗${Z} /dev/$nom : ${B}$valeur secteur(s) illisible(s)${Z} en attente.
${R}Ce ne sont pas des secteurs usés mais des données que le disque
n'arrive plus à relire : le disque est en train de lâcher.${Z}
${D}Sauvegarder ce qui doit l'être avant toute autre chose, et
ne rien installer dessus — l'installation ne tiendrait pas.${Z}" ;;
Offline_Uncorrectable)
note 2 " ${R}✗${Z} /dev/$nom : ${B}$valeur secteur(s) définitivement perdu(s)${Z}.
${R}Le disque a renoncé à les relire. À remplacer.${Z}" ;;
esac
done done
heures="$(printf '%s' "$sortie" | awk '/Power_On_Hours/{print $10; exit}')" heures="$(printf '%s' "$sortie" | awk '/Power_On_Hours/{print $10; exit}')"
rotatif="$(cat "$chemin/queue/rotational" 2>/dev/null)" rotatif="$(cat "$chemin/queue/rotational" 2>/dev/null)"
# L'usure, recalculée ici : cette boucle est distincte de celle du
# relevé et ne voit pas ses variables.
usure="$(printf '%s' "$sortie" | awk '/Percentage Used:/{gsub(/[^0-9]/,"",$3); print $3; exit}')"
if [ -z "$usure" ]; then
usure="$(printf '%s' "$sortie" | awk '
/Media_Wearout_Indicator|Wear_Leveling_Count|SSD_Life_Left|Percent_Lifetime_Remain/ {
if ($4 ~ /^[0-9]+$/ && $4 <= 100) { print 100 - $4; exit }
}')"
fi
# Un disque mécanique se signale toujours, et pas seulement quand il
# est vieux. C'est le premier frein d'une machine par ailleurs
# correcte : remplacer un plateau par un SSD fait plus pour elle que
# n'importe quel réglage, et c'est le genre de conseil qu'on donne
# pendant qu'on a la machine ouverte devant soi.
# Les heures de marche, dites en heures et en années de fonctionnement.
# « 477 j 15 h » se lit mal : on croit à un disque épuisé alors que
# c'est une année et quelques mois de marche, ce qui est peu.
marche=""
case "$heures" in case "$heures" in
''|*[!0-9]*) ;; ''|*[!0-9]*) ;;
*) if [ "$rotatif" = "1" ] && [ "$heures" -gt 43800 ]; then *) marche="$heures h"
note 1 " ${O}!${Z} /dev/$nom : disque mécanique de $(( heures / 8760 )) ans. if [ "$heures" -ge 8760 ]; then
${D}Un SSD changerait tout sur cette machine.${Z}" marche="$marche, soit $(( heures / 8760 )),$(( (heures % 8760) * 10 / 8760 )) an de marche"
fi ;; fi ;;
esac esac
if [ "$rotatif" = "1" ]; then
# Un disque mécanique se fatigue en tournant. Les constructeurs
# annoncent 300 000 à 600 000 heures de MTBF, mais le retour du
# terrain est plus sobre : au-delà de 30 000 heures — trois ans et
# demi de marche continue — les pannes deviennent sensiblement plus
# fréquentes, et à 45 000 on est dans le sursis.
gravite_disque=1
supplement=""
case "$heures" in
''|*[!0-9]*) ;;
*) if [ "$heures" -ge 45000 ]; then
gravite_disque=2
supplement="
${R}Au-delà de 45 000 heures : sauvegarder avant toute chose.${Z}"
elif [ "$heures" -ge 30000 ]; then
supplement="
${O}Plus de 30 000 heures de marche : il a fait son temps.${Z}"
fi ;;
esac
note "$gravite_disque" " ${O}!${Z} /dev/$nom est un ${B}disque mécanique${Z}${marche:+ · $marche}.
${D}Le remplacer par un SSD ferait plus pour cette machine que
tout le reste réuni — démarrage, ouverture des programmes, réactivité.${Z}$supplement"
else
# Un SSD ne s'use pas en tournant mais en écrivant. Les heures de
# marche ne disent rien de son état : c'est l'usure qu'on regarde.
case "$usure" in
''|*[!0-9]*)
[ -n "$marche" ] && note 0 " ${V}·${Z} /dev/$nom est un SSD · $marche.
${D}Usure non déclarée par ce modèle.${Z}" ;;
*) if [ "$usure" -ge 90 ]; then
note 2 " ${R}✗${Z} /dev/$nom : SSD usé à ${B}${usure} %${Z} — il approche de sa fin.
${R}Sauvegarder, et prévoir son remplacement.${Z}"
elif [ "$usure" -ge 70 ]; then
note 1 " ${O}!${Z} /dev/$nom : SSD usé à ${usure} %${marche:+ · $marche}.
${D}Encore utilisable, mais il faudra y penser.${Z}"
else
note 0 " ${V}·${Z} /dev/$nom : SSD usé à ${usure} % seulement${marche:+ · $marche}."
fi ;;
esac
fi
if [ "$taille" -lt 32000000000 ]; then if [ "$taille" -lt 32000000000 ]; then
note 1 " ${O}!${Z} /dev/$nom ne fait que $(( taille / 1000000000 )) Go — c'est juste." note 1 " ${O}!${Z} /dev/$nom ne fait que $(( taille / 1000000000 )) Go — c'est juste."
fi fi
@ -378,10 +628,61 @@ if [ "$CHECK" = 1 ]; then
2) printf " %s%s NE PAS INSTALLER EN L'ÉTAT %s\n" "$B$R" "✗" "$Z" ;; 2) printf " %s%s NE PAS INSTALLER EN L'ÉTAT %s\n" "$B$R" "✗" "$Z" ;;
esac esac
echo echo
if [ -n "$TABLE_DISQUES" ]; then
printf ' %s' "$D"
colonne "Disque" 7; printf ' '
colonne "Modèle" 20; printf ' '
colonne "Type" 10; printf ' '
colonne "Taille" 10 droite; printf ' '
colonne "SMART" 8; printf ' '
colonne "Marche / usure" 16; printf ' '
printf 'Secteurs R/P/I%s\n' "$Z"
printf '%s' "$TABLE_DISQUES" | sed "s/^/ /"
printf " %sR : remplacés · P : illisibles en attente · I : perdus%s\n" "$D" "$Z"
echo
fi
[ -n "$REMARQUES" ] && printf "%s\n" "$REMARQUES" [ -n "$REMARQUES" ] && printf "%s\n" "$REMARQUES"
[ "$GRAVITE" = 2 ] && printf " %sEn parler au propriétaire avant de toucher à quoi que ce soit.%s\n\n" "$D" "$Z"
# Une pause, sans quoi tout cela défile et personne ne le lit. Sa durée
# suit la gravité, et l'on n'attend jamais indéfiniment : le script tourne
# aussi sans personne devant l'écran, appelé par install.sh.
if [ -t 0 ]; then
case "$GRAVITE" in
2) printf " %sEn parler au propriétaire AVANT de toucher à quoi que ce soit.%s\n" "$D" "$Z"
printf " %sEntrée pour continuer malgré tout%s " "$B" "$Z"
read -r -t "${ALPI_PAUSE_ALERTE:-120}" _ || echo ;;
1) printf " %sEntrée pour continuer (reprise automatique dans %ss)%s " \
"$D" "${ALPI_PAUSE:-20}" "$Z"
read -r -t "${ALPI_PAUSE:-20}" _ || echo ;;
*) sleep "${ALPI_PAUSE_OK:-3}" ;;
esac
echo
fi
fi fi
# Ce que l'on vient de dire à la personne part avec la fiche.
#
# Sans cela, alpicache rejugeait à partir des seuls champs reçus — et ne voyait
# pas les secteurs en attente, qui ne lui étaient pas envoyés. Il affichait
# « sain » un disque que ce script venait de déclarer à remplacer. Deux juges,
# deux verdicts : il n'y en a plus qu'un, et c'est celui-ci.
VERDICT="ok"
case "${GRAVITE:-0}" in
2) VERDICT="alerte" ;;
1) VERDICT="attention" ;;
esac
MOTIFS_JSON="["
premier=1
while IFS= read -r ligne; do
[ -n "$ligne" ] || continue
[ "$premier" = 0 ] && MOTIFS_JSON="$MOTIFS_JSON,"
premier=0
MOTIFS_JSON="$MOTIFS_JSON$(printf '%s' "$ligne" \
| sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$/"/')"
done <<< "${MOTIFS:-}"
MOTIFS_JSON="$MOTIFS_JSON]"
RAPPORT="${RAPPORT%\}},$(champ verdict "$VERDICT"),\"motifs\":$MOTIFS_JSON}"
if command -v curl >/dev/null 2>&1; then if command -v curl >/dev/null 2>&1; then
reponse="$(printf '%s' "$RAPPORT" | curl -s --max-time 15 \ reponse="$(printf '%s' "$RAPPORT" | curl -s --max-time 15 \
-H 'Content-Type: application/json' --data-binary @- "$SERVEUR/fiche")" -H 'Content-Type: application/json' --data-binary @- "$SERVEUR/fiche")"

View file

@ -359,11 +359,32 @@ configuration_apt() {
# GRUB : sélection automatique de la dernière entrée utilisée # # GRUB : sélection automatique de la dernière entrée utilisée #
############################################################### ###############################################################
modif_grub() { modif_grub() {
# Rien à faire si c'est déjà en place.
#
# update-grub lance os-prober, qui part sonder toutes les partitions de la
# machine à la recherche d'autres systèmes, puis régénère la configuration
# entière : vingt à trente secondes qu'on ne rattrape pas, et qu'on payait
# jusqu'ici à chaque exécution, y compris quand il n'y avait rien à
# changer. Sur une install party de quinze machines, cela se voit.
if grep -q '^GRUB_DEFAULT=saved' /etc/default/grub \
&& grep -q '^GRUB_SAVEDEFAULT=true' /etc/default/grub; then
echo -e "==> GRUB est déjà configuré, rien à changer\n"
return 0
fi
echo -e "==> Modification de GRUB\n" echo -e "==> Modification de GRUB\n"
# On comment la ligne "GRUB_DEFAULT=0" et on ajoute les "bonnes" options # On commente la ligne d'origine, puis on ajoute les nôtres si elles
sed -i '/^GRUB_DEFAULT=0/ i#GRUB_DEFAULT=0\ # manquent. Les ajouter plutôt que les insérer règle deux choses : le
GRUB_DEFAULT=saved\ # fichier ne se retrouve plus avec des lignes indentées — GRUB les accepte,
GRUB_SAVEDEFAULT=true' /etc/default/grub # mais elles trompent la lecture quand on vient déboguer —, et la fonction
# fait toujours son travail lorsque « GRUB_DEFAULT=0 » a disparu, ce qui
# arrive dès qu'un autre outil est passé avant nous.
sed -i 's/^GRUB_DEFAULT=0/#&/' /etc/default/grub
grep -q '^GRUB_DEFAULT=saved' /etc/default/grub \
|| echo 'GRUB_DEFAULT=saved' >> /etc/default/grub
grep -q '^GRUB_SAVEDEFAULT=true' /etc/default/grub \
|| echo 'GRUB_SAVEDEFAULT=true' >> /etc/default/grub
# On met à jour GRUB # On met à jour GRUB
update-grub update-grub
} }

View file

@ -58,6 +58,7 @@ Lors de nos **Install Party**, les bénévoles d'**Alpinux** installent Linux av
## 🧰 Après l'installation ## 🧰 Après l'installation
- 🩹 [**Trousse de premiers secours Linux Mint**](../guides/linux-mint-trousse.md) — les réflexes utiles des premiers jours. - 🩹 [**Trousse de premiers secours Linux Mint**](../guides/linux-mint-trousse.md) — les réflexes utiles des premiers jours.
- 🖧 [**Le serveur qu'on emporte**](../technique/serveur-install-party.md) — le réseau de la salle, le cache de paquets, et ce qu'un bénévole doit en savoir.
- 🗣️ [**Ateliers et rencontres**](evenements.md) — pour progresser et échanger avec la communauté. - 🗣️ [**Ateliers et rencontres**](evenements.md) — pour progresser et échanger avec la communauté.
--- ---

23
docs/deploiement.md Normal file
View file

@ -0,0 +1,23 @@
# wiki.alpinux.org
Documentation publique Alpinux — MkDocs Material.
## Déploiement
```bash
cd org.alpinux.owni/wiki
mkdocs build --strict
rsync -rlcz --delete site/ alpinux.org:/var/www/wiki.alpinux.org/web/
```
## Développement local
```bash
pip install mkdocs-material
mkdocs serve # http://localhost:8000
```
## Notes
- Pas de service systemd — site statique servi directement par Apache
- Les docs publiques sont dans `wiki/docs/technique/`

View file

@ -104,10 +104,6 @@ Clic droit sur **Démarrer** → *Terminal (administrateur)*, puis :
powercfg /hibernate off powercfg /hibernate off
``` ```
!!! tip "Le dernier arrêt de Windows"
Au moment d'éteindre Windows pour insérer la clé USB, maintenez **Maj (Shift)**
enfoncée en cliquant sur *Démarrer → Arrêter*. Cela force un arrêt complet.
### Gestion de l'alimentation de la carte Wi-Fi ### Gestion de l'alimentation de la carte Wi-Fi
Certaines cartes Wi-Fi (puces Realtek ou Broadcom notamment) restent dans l'état de basse Certaines cartes Wi-Fi (puces Realtek ou Broadcom notamment) restent dans l'état de basse
@ -188,6 +184,8 @@ Linux. Il faut le basculer sur **AHCI**, dans la section *Storage*, *SATA Config
conserver Windows, faites le changement avec un bénévole. Si Windows est de toute conserver Windows, faites le changement avec un bénévole. Si Windows est de toute
façon remplacé, la bascule est sans conséquence. façon remplacé, la bascule est sans conséquence.
--- ---
## 2. Préparer son support d'installation ## 2. Préparer son support d'installation
@ -246,8 +244,11 @@ Avec [Ventoy](ventoy.md), la préparation tient en un copier-coller :
### Branchements ### Branchements
- Insérez la clé Ventoy dans un **port USB de la machine**, en évitant les hubs. - Insérez la clé Ventoy dans un **port USB de la machine**, en évitant les hubs.
- **Branchez un câble Ethernet.** Mint pourra télécharger mises à jour, codecs et paquets - **Branchez un câble Ethernet.** Le script install.sh de Alpinux effectue des tests.
de langue pendant l'installation — cela évite beaucoup de réglages ensuite.
!!! tip "Le dernier arrêt de Windows - Comment arrêter Windows pour démarrer sur la clé USB"
Au moment d'éteindre Windows pour insérer la clé USB, maintenez **Maj (Shift)**
enfoncée en cliquant sur *Démarrer → Arrêter*. Cela force un arrêt complet.
### Accéder au menu de démarrage ### Accéder au menu de démarrage
@ -341,16 +342,25 @@ fatigué. On ne le découvre pas au milieu du partitionnement.
En session live, taper les commandes une à une est fastidieux. Un script d'Alpinux fait En session live, taper les commandes une à une est fastidieux. Un script d'Alpinux fait
l'inventaire et rend un verdict : l'inventaire et rend un verdict :
**Sur le réseau de l'install party**, où les scripts sont servis par
[le serveur qu'Alpinux emporte](../technique/serveur-install-party.md) :
```bash ```bash
wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-wiki/raw/branch/main/code/linux/linux-mint/verif-disque.sh wget http://alpicache.lan/verif-disque.sh && chmod +x verif-disque.sh && ./verif-disque.sh
chmod +x verif-disque.sh
./verif-disque.sh
``` ```
Sur le réseau de l'install party, plus court : !!! tip "Si le nom ne répond pas"
Le serveur répond aussi à `alpicache`, `apt-proxy` et `10.0.0.1` — cette
dernière adresse fonctionne même quand la résolution de noms n'est pas encore
en place :
`wget http://10.0.0.1/verif-disque.sh`
**Ailleurs, depuis Internet :**
```bash ```bash
wget http://10.0.0.1/verif-disque.sh && chmod +x verif-disque.sh && ./verif-disque.sh wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux.scripts/raw/branch/stable/poste/verif-disque.sh
chmod +x verif-disque.sh
./verif-disque.sh
``` ```
Il **ne modifie rien** — il lit, il affiche, il conseille. Il demande le mot de passe pour Il **ne modifie rien** — il lit, il affiche, il conseille. Il demande le mot de passe pour
@ -375,9 +385,17 @@ matérielle** — modèle, processeur, mémoire et ses connecteurs, disques et l
et l'envoie au serveur de l'association. et l'envoie au serveur de l'association.
```bash ```bash
wget http://10.0.0.1/alpi-fiche.sh && chmod +x alpi-fiche.sh && sudo ./alpi-fiche.sh --check wget http://alpicache.lan/alpi-fiche.sh && chmod +x alpi-fiche.sh && sudo ./alpi-fiche.sh --check
``` ```
Hors réseau de l'install party, il se prend sur Internet :
```bash
wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux.scripts/raw/branch/stable/poste/alpi-fiche.sh
```
Il n'aura alors aucun serveur à qui remettre la fiche : il l'affiche, et c'est tout.
Lancé depuis la session live, il rend en plus un verdict en trois états : **bon pour Lancé depuis la session live, il rend en plus un verdict en trois états : **bon pour
l'installation**, **possible avec des réserves**, ou **ne pas installer en l'état** — un l'installation**, **possible avec des réserves**, ou **ne pas installer en l'état** — un
disque qui se déclare défaillant, des secteurs réalloués, moins de 2 Go de mémoire, un disque qui se déclare défaillant, des secteurs réalloués, moins de 2 Go de mémoire, un
@ -594,25 +612,34 @@ Le système est installé ; quelques réglages le rendent réellement utilisable
### Le script de post-installation Alpinux ### Le script de post-installation Alpinux
Il automatise ce qui manque presque toujours après une installation standard. Ouvrez un Il automatise ce qui manque presque toujours après une installation standard. Ouvrez un
terminal (`Ctrl + Alt + T`) et récupérez-le — **sur le réseau local de l'Install Party** : terminal (`Ctrl + Alt + T`) et récupérez-le — **sur le réseau local de l'Install Party**,
où [le serveur d'Alpinux](../technique/serveur-install-party.md) le sert et met en cache
tout ce que la machine téléchargera ensuite :
```bash ```bash
wget http://10.0.0.1/install.sh wget http://alpicache.lan/install.sh http://alpicache.lan/alpi-fiche.sh
``` ```
**ou depuis Internet :** **ou depuis Internet :**
```bash ```bash
wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux-wiki/raw/branch/main/code/linux/linux-mint/install.sh wget https://gitea.alpinux.org/alpinux.cedrica5l/alpinux.scripts/raw/branch/stable/poste/install.sh \
https://gitea.alpinux.org/alpinux.cedrica5l/alpinux.scripts/raw/branch/stable/poste/alpi-fiche.sh
``` ```
Puis, dans les deux cas : Puis, dans les deux cas :
```bash ```bash
chmod +x install.sh chmod +x install.sh alpi-fiche.sh
./install.sh ./install.sh
``` ```
!!! note "Pourquoi deux fichiers"
`install.sh` commence par relever la fiche matérielle, et il ne le fait **que s'il
trouve `alpi-fiche.sh` à côté de lui** — il ne va rien chercher sur le réseau de
lui-même. Téléchargé seul, il s'installera très bien, simplement sans relevé. En
install party, prenez les deux.
Le mot de passe est demandé au passage (`alpinux73` en Install Party) : les caractères ne Le mot de passe est demandé au passage (`alpinux73` en Install Party) : les caractères ne
s'affichent pas, c'est normal. s'affichent pas, c'est normal.

View file

@ -109,16 +109,31 @@ Les **Préférences** s'organisent en trois onglets :
!!! tip "Le piège du `/boot` plein" !!! tip "Le piège du `/boot` plein"
Les anciens noyaux s'accumulent et finissent par saturer la partition de démarrage, Les anciens noyaux s'accumulent et finissent par saturer la partition de démarrage,
ce qui bloque toute nouvelle mise à jour. L'onglet *Automatisation* permet de ce qui bloque toute nouvelle mise à jour. L'onglet *Automatisation* permet de
programmer leur suppression ; à défaut, retirez-les de temps en temps depuis programmer leur suppression ; à défaut, passez de temps en temps par
l'*Analyseur de noyaux* du gestionnaire. **Affichage → Noyaux Linux**, qui les liste et permet de retirer les plus anciens.
!!! warning "Changer de noyau n'est pas anodin"
La même fenêtre *Noyaux Linux* s'ouvre sur un avertissement qu'il vaut la peine de
lire : un noyau plus récent peut faire disparaître le Wi-Fi, l'accélération graphique,
ou donner un écran noir au démarrage — surtout avec des pilotes propriétaires.
La sortie de secours tient en quatre gestes, à connaître **avant** d'en installer un :
redémarrer, maintenir **Maj** pour afficher le menu GRUB, choisir *Advanced options*
puis un noyau antérieur, et désinstaller le plus récent une fois revenu.
### Activer le pare-feu ### Activer le pare-feu
Le pare-feu est installé, mais **désactivé par défaut**. Pour un ordinateur portable qui Le pare-feu est installé, mais **désactivé par défaut**. Pour un ordinateur portable qui
se connecte à des réseaux publics, il vaut mieux l'allumer : se connecte à des réseaux publics, il vaut mieux l'allumer :
**Paramètres du système → Pare-feu** (famille *Administration*), puis basculez **État** sur *Activé*. Le profil *Public* convient : **Paramètres du système → Pare-feu** (famille *Administration*). L'ouverture demande votre
il bloque les connexions entrantes et laisse passer tout ce que vous initiez. mot de passe, puis il suffit de basculer **État** sur *Activé*.
Le profil proposé par défaut, **Domestique**, convient : les deux lignes en dessous
annoncent la règle appliquée — *Entrant : Refuser*, *Sortant : Autoriser*. Autrement dit,
rien ne rentre sans y avoir été invité, tout ce que vous lancez sort normalement. Les
profils *Bureau* et *Public* servent à mémoriser d'autres jeux de règles ; sans besoin
précis, n'y touchez pas.
### Vérifier ses pilotes ### Vérifier ses pilotes

View file

@ -0,0 +1,169 @@
---
description: Le serveur qu'Alpinux emporte en install party — partage de connexion, réseau local, cache de paquets APT, page de santé, et ce qu'un bénévole doit en savoir sur place.
---
# Le serveur qu'on emporte en install party
Quinze ordinateurs qui s'installent le même matin, c'est quinze fois les mêmes
cinq cents mégaoctets tirés par la ligne de la salle — quand il y en a une. Alpinux
apporte donc sa propre machine, **alpicache**, qui partage l'accès à Internet, sert un
réseau local aux postes en cours d'installation, et **garde en cache les paquets déjà
téléchargés**.
!!! note "Pour qui est cette page"
Pour les bénévoles qui installent, et pour qui prépare la salle. La configuration
complète de la machine — interfaces, services, dépannage détaillé — vit dans son
propre dépôt, `alpinux.alpicache`, et non ici.
---
## Le réseau de la salle
```mermaid
flowchart LR
A[Prise murale<br/>ou box de la salle] --> B[alpicache<br/>10.0.0.1]
B --> C[Switch]
C --> D[Poste 1]
C --> E[Poste 2]
C --> F[Poste n]
```
La machine tient les deux bouts : d'un côté elle demande un accès à la salle, de l'autre
elle distribue un réseau en **10.0.0.x** aux postes branchés sur le switch. Les rôles ne
sont pas figés à l'avance : elle désigne comme sortie la première prise où on lui répond,
et sert le réseau local sur l'autre.
!!! warning "Les postes se branchent sur le switch, jamais sur la box"
Un poste branché directement sur la box de la salle reçoit une adresse de la salle :
il ne voit plus le cache, ne trouve plus les scripts, et fait tomber les compteurs à
zéro. C'est l'erreur la plus fréquente, et elle ne se voit pas tout de suite.
---
## Ce que la machine offre, une fois branchée
| Adresse | À quoi ça sert |
| --- | --- |
| **<http://alpicache.lan/>** | La page de santé : réseau, disques, machines servies, cache |
| **`http://apt-proxy:3142`** | Le cache de paquets, à déclarer comme mandataire |
| **`http://10.0.0.1/`** | Les scripts d'Alpinux, servis sur place — dont `verif-disque.sh` et `install.sh` |
La page de santé se rafraîchit seule ; c'est le tableau de bord de la journée. Quatre
cartes à surveiller :
| Carte | Ce qu'on veut y voir |
| --- | --- |
| **Réseau** | une sortie *et* un réseau local nommés, « Internet joignable » |
| **Disques** | le disque du cache présent, avec de la place |
| **Machines servies** | le nombre grandit à mesure que les postes arrivent |
| **Cache de paquets** | « Économisé » qui monte au fil de la matinée |
**« Machines servies » qui reste à zéro** alors que des postes sont branchés, c'est le
signe que le réseau local ne distribue pas d'adresses : prévenez la personne qui tient la
machine plutôt que de chercher sur le poste du participant.
---
## Faire passer une installation par le cache
C'est là que tout se joue, et le geste n'est pas le même selon le système.
### Debian
L'installateur demande un mandataire à l'écran **« Configurer le miroir de l'archive
Debian »**. Saisissez-y :
```
http://apt-proxy:3142
```
C'est **le seul moment** où on peut le faire, et c'est celui qui compte : toute
l'installation passe alors par le cache.
### Linux Mint et Ubuntu
Leur installateur ne demande pas de mandataire : l'installation elle-même sortira sur
Internet. Le gain arrive juste après — sur les mises à jour et les logiciels ajoutés,
c'est-à-dire sur l'essentiel du volume.
Une fois la machine redémarrée sur son nouveau système :
```bash
sudo apt install auto-apt-proxy
```
Ce paquet cherche un cache sur le réseau local et s'en sert quand il en trouve un — sans
rien à configurer, et sans gêner la machine une fois rentrée chez son propriétaire.
!!! tip "Le script de post-installation le fait déjà"
Le [script d'Alpinux](../guides/linux-mint-depuis-windows.md#le-script-de-post-installation-alpinux)
installe `auto-apt-proxy` parmi ses réglages : si vous le lancez, c'est fait.
---
## Ce qui coince, et la parade
**La salle n'a pas de réseau.** Un téléphone Android en partage de connexion USB fait
l'affaire : branché sur la machine, il devient la sortie. Prévoyez le câble.
**Le disque du cache n'est pas vu.** Il doit être branché **avant** d'allumer la machine.
Après coup, le cache démarre sans rien dire et ne garde rien — la carte *Disques* de la
page de santé le montre tout de suite.
**Un poste n'obtient pas d'adresse.** Vérifiez d'abord le câble et le switch, puis la
carte *Machines servies*. Une adresse en `169.254.x.x` signifie que le poste n'a reçu
aucune réponse : il s'en est inventé une.
**`apt` renvoie des « 503 Connection closed » en série.** Le cache accepte la requête mais
ne sait pas où aller la chercher — c'est arrivé le 24/09/2026, et une installation Mint
s'y est arrêtée. Le piège est qu'**interroger le cache directement répond parfaitement** :
les deux chemins ne suivent pas la même route à l'intérieur du serveur. Ne cherchez donc
pas sur la machine du participant : prévenez la personne qui tient le serveur.
---
## Pour préparer une install party
La veille, la machine s'allume chez quelqu'un, sur une ligne rapide, et l'on garnit le
cache avec ce qu'on va installer — si la version de Mint a changé depuis la dernière
sortie, autant la tirer maintenant.
!!! warning "Le cache ne sert que ce qu'il connaît"
Le pré-chargement vise des versions nommées, et une version absente de la liste ne
profite à personne. Le 24/09/2026, la première Mint 22.3 de la soirée a tiré **1,3 Go
d'Internet pour 82 Mo servis par le cache** : le pré-chargeur couvrait encore les
versions précédentes.
Avant chaque sortie, vérifiez donc que la liste des versions pré-chargées correspond à
celle que vous allez réellement installer. C'est par le **nom de code** que le
pré-chargement les désigne, et un décalage d'un cran suffit à garnir le cache de la
mauvaise version :
| Version | Nom de code |
|---|---|
| Mint 22 | `wilma` |
| Mint 22.1 | `xia` |
| Mint 22.2 | `zara` |
| Mint 22.3 | `zena` |
Pour mémoire, la série précédente : `vanessa` (21), `vera` (21.1), `victoria` (21.2),
`virginia` (21.3).
Sur place, l'ordre de branchement n'est pas une superstition : le disque externe d'abord,
puis le câble Internet **seul**, puis la machine, et seulement ensuite le switch et les
postes. Brancher la sortie seule d'abord, c'est ôter à la machine toute occasion de se
tromper de rôle.
La procédure complète — ce qu'on emporte, les vérifications, le dépannage, la fiche à
cocher pour chaque participant et l'affiche à scotcher près du switch — est dans le dépôt
`alpinux.alpicache`. Demandez-la à un membre du bureau avant une sortie.
---
## Voir aussi
- [Install Party](../alpinux/install-party.md) — les dates, et comment y participer
- [Installer Linux Mint depuis Windows](../guides/linux-mint-depuis-windows.md) — le guide
suivi sur place
- [Préparation d'un serveur Debian 13](serveur-debian-13.md) — pour la machine, la base
système est la même

View file

@ -119,6 +119,7 @@ nav:
- technique/matrix.md - technique/matrix.md
- technique/arduino-ide.md - technique/arduino-ide.md
- technique/serveur-debian-13.md - technique/serveur-debian-13.md
- technique/serveur-install-party.md
- technique/bigbluebutton.md - technique/bigbluebutton.md
- technique/ateliers.md - technique/ateliers.md
- Communication: - Communication: