lid's Wiki

Introduction

tux.jpg

Historique

Dans le courant des années 60, plusieurs développements ont commencé afin de fournir des systèmes d'exploitation permettant aux utilisateurs de gérer leurs fichiers, de partager le temps de la machine pour l'exécution des processus lancés par ces mêmes utilisateurs. En effet, à l'époque les utilisateurs soumettaient des /batch jobs/ aux opérateurs des ordinateurs de l'époque, et, pour simplifier, revenaient le lendemain - ou la semaine suivante - pour obtenir leurs résultats. Ce qui n'était pas très pratique.

Dès lors, plusieurs systèmes furent imaginés: CTSS (/Compatible Time Sharing System/) du MIT, en 1961, qui proposait déjà du courrier électronique (entre utilisateurs du système), du traitement de texte, etc. Son successeur était censé être /MultiCS/, projet très ambitieux - et difficilement réalisable avec les moyens techniques de l'époque - lancé en 1964. Cependant, au vu du retard pris dans le développement de MultiCS, le concept même de système d'exploitation a failli être abandonné (pour revenir aux /batch jobs/). MultiCS était un OS multiutilisateur, multitâche préemptif avec gestion des priorités entre les processus, et disposant d'un système de fichiers hiérarchique proche des systèmes de fichiers que l'on connaît aujourd'hui.

Cependant, les ressources qu'il demandait (en temps de travail des développeurs) ont conduit un des principaux contributeurs, Bell Labs, à se retirer du projet. Deux ingénieurs, Dennis Ritchie et Ken Thompson, qui travaillaient sur MultiCS décidèrent de développer leur propre OS, qu'ils nommèrent (d'une façon un peu facétieuse) UNICS (/UNiplexed Information and Computing Service/), dont la première version opérationnelle date de la fin 1969 (c'est pour ça que le temps informatique (timestamp UNIX) date du 1er janvier 1970)), qui devint UNIX. Dans la foulée, Dennis Ritchie inventa le langage C, en 1971, lors de la première réécriture d'UNIX.

./dennisandken.jpg

Dans le courant des années 70 et 80, UNIX devint le système d'exploitation dominant, son modèle Mainframe/"clients légers" (Terminaux physiques, par exemple le légendaire DEC VT100) s'adaptant particulièrement bien aux besoins des entreprises de l'époque.

Il fut le socle sur lequel se construisirent Internet (ARPANet à l'époque) et les différents protocoles encore en cours d'utilisation de nos jours (notamment SMTP (mails), DNS, NNTP (newsgroups), IRC, (S)FTP, etc), les outils de typographie encore utilisés aujourd'hui (TeX/LaTeX dont PDF n'est qu'un dérivé), les éditeurs de texte comme Emacs ou Vi (puis Vim), et il donna le jour à une importante descendance (BSD UNIX, AT&T UNIX, SGI IRIX, Sun Solaris, IBM AIX, macOS, Plan 9 From Bell Labs/9Front - qui était censé devenir son remplaçant avec pleins d'idées novatrices pour l'époque (chaque processus est isolé des autres dans un quasi-container, tout est vraiment fichier, même la carte son, axé réseau (tout est distribuable, du système de fichiers aux CPUs, sur le réseau)), MINIX pour les étudiants).

Cependant, avant l'arrivée des BSD libres et surtout gratuits au début des années 90 (NetBSD, FreeBSD, OpenBSD...), le prix prohibitif des licenses en interdisaient purement et simplement l'acquisition par les particuliers et les petites entreprises, ce qui entraîna le succès d'un certain IBM PC et d'une petite entreprise nommée Microsoft dans le milieu des petites entreprises à la fin des années 80 et dans les années 90, UNIX se retrouvant "cantonné" dans les grandes entreprises qui avaient besoin d'un OS fiable et capable de gérer des milliers voire millions d'utilisateurs au sein de réseaux TCP/IP complexes.

En 1991 (le 25 août pour être précis), un jeune étudiant du nom de Linus Torvalds qui travaillait sur un noyau de système d'exploitation posta sur Usenet (newsgroups, sur le groupe /comp.os.minix/) un message devenu culte:

./torvalds1991.jpg

"Hello everybody out there using minix - I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones. This has been brewing since april, and is starting to get ready. I'd like any feedback on things people like/dislike in minix, as my OS resembles it somewhat (same physical layout of the file-system (due to practical reasons) among other things). I've currently ported bash(1.08) and gcc(1.40), and things seem to work. This implies that I'll get something practical within a few months, and I'd like to know what features most people would want. Any suggestions are welcome, but I won't promise I'll implement them 😃 Linus (torvalds at kruuna.helsinki.fi) PS. Yes – it's free of any minix code, and it has a multi-threaded fs. It is NOT portable (uses 386 task switching etc), and it probably never will support anything other than AT-harddisks, as that's all I have 😦."

./nvidiafu.jpeg

Le noyau qui ne devait pas devenir "professionnel" finira par être utilisé partout, de la cafetière connectée aux smartphones, en passant par les ordinateurs (desktop et laptops), et les super-calculateurs. Vous vous en servez tous les jours sans le savoir: dans votre *box, dans votre smartphone, en utilisant la plupart des sites Web, en envoyant un mail, en discutant sur Discord, lorsque vous jouez à des jeux en ligne...

./debian.jpg

Cependant, il est bon de noter que Linux (le noyau, qui devait s'appeler Freax selon le souhait de Linus Torvalds) n'est pas un noyau UNIX (comme le sont Mach ou le kernel "bsd" d'OpenBSD), mais un noyau de type UNIX. Il peut donc proposer une API différente (mais globalement compatible) de l'API d'un kernel UNIX "standard".

Architecture générale du système

Le noyau Linux

Le noyau (/kernel/) Linux est un noyau de système d'exploitation multitâche préemptif et multi-utilisateurs. C'est un logiciel principalement libre (mais qui peut être complété par des /blobs/ propriétaires (drivers et firmwares non-libres)). Il est développé principalement en langage C par des dizaines de milliers de contributeurs (salariés ou bénévoles).

Un /kernel/ est le coeur d'un OS. Il est en charge de fournir une API permettant aux logiciels de communiquer avec le matériel. Il a été porté sur de nombreuses architectures: m68k (abandonné), ARM, SPARC, MIPS, POWER, x86/amd64, RISC-V...

Il respecte les normes POSIX. C'est un noyau dit /monolithique/, par opposition aux micro-noyaux (GNU Hurd, MINIX, Mach...). Il est modulaire depuis sa version 2.0, c'est à dire qu'on peut ajouter ou supprimer des fonctionnalités du kernel "à la volée", par exemple:

sudo -s
rmmod nvidia
modprobe nvidia
exit; startx

Ce qui rapproche son comportement d'un micro-noyau où les différents drivers sont exécutés dans l'espace utilisateur, bien qu'ils soient, ici, exécutés dans l'espace noyau.

Le kernel 1.0, en 1994, comptait environ 177.000 lignes de code. Il en compte désormais 27.8 millions (ce qui inclus, bien évidemment, les différentes architectures et pilotes de périphériques disponibles. Le /kernel/ que vous faites tourner sur vos machines (x86/amd64 ou ARM (Raspberry Pi par exemple)) n'en utilise qu'une partie lors de sa compilation pour produire l'exécutable correspondant à votre matériel (enfin, plutôt un exécutable correspondant à la plupart (générique) des différents périphériques et CPUs que nous utilisons. Dans l'embarqué, on peut avoir des kernels qui, une fois compilés, pèseront moins de 2Mo, là où par exemple le kernel utilisé par ma machine pèse ~20Mo compressé et ~60Mo décompressé en RAM - mais il inclut des drivers qui ne sont pas nécessaires pour l'utilisation de ma machine, et donc non-utilisés. L'avantage étant que je peux prendre mon SSD, l'installer dans une autre machine avec un équipement différent (par exemple une carte graphique AMD au lieu d'un GPU Intel), et démarrer directement dessus sans configuration particulière). Par exemple, le kernel décompressé de Raspbian (distribution GNU/Linux basée sur Debian spécialisée pour Raspberry Pi) fait 15Mo.

L'espace utilisateur et les outils GNU/Linux

./stignucius.jpg

Bien sûr, un /kernel/ tout seul ne permet pas de faire grand chose au commun des mortels (c'est à dire nous!). Il lui faut un ensemble d'utilitaires (l'espace utilisateur) permettant à des opérateurs humains d'interagir avec le matériel, pour, par exemple, regarder une vidéo de chatons qui se cassent la figure sur Youtube® ou envoyer des likes sur Instagram à un ou une influenceur ou influenceuse dont le seul but est de vous faire acheter des trucs inutiles, même si on peut faire des choses bien plus intéressantes avec sa machine.

Plus sérieusement, l'/userland/ va nous permettre de manipuler nos fichiers, d'établir des connexions avec d'autres machines (en réseau local ou sur Internet), de configurer nos périphériques (interfaces réseau, carte graphique, disques durs), d'afficher des caractères sur l'écran, ou des fenêtres avec des caractères dedans, etc.

Quand on parle de distribution Linux, on fait un petit abus de langage: on oublie cet /userland/. Dans le cas des distributions Linux que nous utilisons au jour le jour, il s'agit de l'userland GNU (GNU is Not Unix), projet lancé en 1983 par Richard Stallman, afin de réécrire entièrement l'/userland/ UNIX en remplaçant tous les utilitaires par des utilitaires dont le code source est libre. Par exemple la commande UNIX ls et la commande GNU ls font, à la base, la même chose: afficher le contenu du répertoire courant. Cependant, leurs options (ls -al par exemple) peuvent différer, et l'une ou l'autre version peuvent proposer des options spécifiques afin d'en améliorer - ou pas - le fonctionnement.

On parle de /distribution/ GNU/Linux: il s'agit de l'OS formé par le kernel, l'userland GNU, et les outils spécifiques de la distribution. Par exemple, une distribution Debian GNU/Linux (et ses dérivés: Ubuntu, Mint, etc) utilise le logiciel /apt/ pour installer ou supprimer des logiciels, là où une distribution CentOS GNU/Linux (et ses dérivées: Fedora, etc) utilisera l'utilitaire /yum/. Cependant la base du système (le kernel et les outils GNU) restent identique: le logiciel grep est identique sur Debian ou sur CentOS, par exemple, mais pas forcément sur Alpine, qui n'inclut pas les outils GNU par défaut (elle utilise les outils Busybox, mais propose les outils GNU dans son /gestionnaire de paquets/).

./alpine.png

De même, on peut aussi distinguer des distributions axées desktop, comme Ubuntu ou Fedora, ou /power-users/ comme Archlinux ou Gentoo.

./arch.jpeg

Pour les serveurs, on préfèrera les distributions proposant du support à long terme (LTS, /Long Term Support/) comme Debian, Ubuntu LTS, Rocky ou Alma Linux (version communautaire de RedHat, dérivée de CentOS avant que CentOS devienne une rolling release, jusqu'à dix ans de mises à jour!), RHEL (RedHat Enterprise Linux - support payant), qui permettent de se préparer entre chaque version majeure aux changements de configurations et /upgrades/ nécessaires (par exemple en cas de montée de version majeure du logiciel de bases de données utilisé (I'm looking at you, PostgreSQL)) sur plusieurs années, tout en assurant un support de sécurité sur le long - voire très long - terme nécessaire dans les grandes entreprises ou administrations (les "mammouths" mettent du temps à démarrer). En effet, on ne veut pas casser notre base de données de production, ou notre serveur Web, sur une simple mise à jour normale du système.

./centos.jpeg

On pourrait aussi parler de distributions comme ProxmoxVE ou XCP-NG axées virtualisation, haute-disponibilité et /clustering/, ou NixOS, GuixSD axée reproductibilité de l'environnement mais c'est en dehors du contexte de ce cours.

./proxmox.png

Au final, suivant les besoins, on peut utiliser une distribution "générique" comme Debian, Ubuntu (LTS), CentOS, pour la stabilité et le large choix d'outils disponibles, ou des distributions spécialisées comme Proxmox (rien ne vous empêche d'installer les outils de Proxmox sur Debian, cependant), ou Alpine, ou NixOS pour avoir rapidement le /tooling/ nécessaire disponible tout en se fondant sur une base éprouvée, stable, et maintenue (donc relativement sûre).

L'important est d'utiliser le bon outil par rapport au cahier des charges, au budget, et au temps disponible. C'est aussi cette versatilité qui fait la force de GNU/Linux, n'en déplaise aux détracteurs^Wtrolls que vous pourrez rencontrer sur les divers réseaux sociaux (reddit, hackernews, mastodon, twitter) qui ont tendance à se plaindre de la diversité de l'écosystème Linux et UNIX car le seul truc qui les intéresse c'est leur desktop et leurs jeux vidéos, ce qui n'a aucun rapport avec nos besoins professionnels 😃 (fin du troll). Que vous travailliez sur des serveurs Web, de la virtualisation, des orchestrateurs de containers, de l'embarqué, il y a toujours une distribution "clefs en main".

(et en vrai, si vous voulez jouer/bidouiller/etc sous GNU/Linux: Ubuntu si vous n'êtes pas à l'aise, Archlinux si vous voulez le tout dernier driver nvidia. Et pour la bidouille potentiellement destructrice, KVM (inclu dans le kernel) vous permet de créer rapidement des machines virtuelles pour tester avant de tout casser. Une VM, ça se casse, ça se remplace, c'est mieux que Carglass (je suis déjà dehors).)

Les processus

Définition

Un processus est un programme en cours d'exécution. Une application peut être composée de plusieurs processus: par exemple un navigateur Web peut créer un processus par onglet, puis avoir d'autres processus lancés pour interpréter (ou compiler à la volée (JIT)) du javascript, etc.

On parle de processus enfant pour un processus qui a été lancé par un autre processus (son parent). Sous UNIX, il est nécessaire de "tuer" tous les processus enfants d'un processus parent avant de tuer le parent, sinon, les processus enfants deviendront des processus "zombies". La classe, hein? (ou flippant, au choix 😃)

Sous GNU/Linux ou sous UNIX, chaque processus dispose d'un numéro de processus l'identifiant: c'est son PID (/Process IDentifier/).

Le kernel n'a pas de numéro de processus. le processus de PID 1 est le parent de tous les processus, il s'agit en général du processus d'initialisation du système, qu'on appelle /init/. C'est lui qui est en charge de lancer, stopper, redémarrer, allouer des ressources aux services (ensembles de processus) que l'utilisateur lancera (ou qui seront lancés automatiquement au démarrage par /init/).

Par exemple, le serveur Web Apache est un ensemble de processus (un /service/), que l'on voudra lancer au boot sur un serveur: c'est le "boulot" d'un /init/. Si l'administrateur veut stopper, relancer ou recharger la configuration d'Apache, il le "demandera" à l'init en utilisant une commande précise, par exemple, sous Debian (ou ubuntu, etc):

systemctl stop apache2
# pour le relancer au lieu de le stopper:
systemctl restart apache2
# dans le cas d'un changement de configuration
systemctl reload apache2

Dans le cas de la plupart des distributions GNU/Linux ce PID 1 est /systemd/. Mais il existe d'autres /inits/: par exemple la distribution Alpine utilise OpenRC. Il existe aussi sysvinit (init System V UNIX), ou runit. Des fous furieux utilisent aussi Emacs comme init. Dans ce cours on se focalisera sur systemd, vu qu'il s'agit de l'init utilisé par la plupart des distributions GNU/Linux que nous utiliserons.

On ne peut - normalement - pas tuer le PID 1 sous GNU/Linux, là où sous BSD (et macOS) cela va soit rebooter la machine, soit l'éteindre.

Exemple: pstree

La commande /pstree/ permet d'afficher l'ensemble des processus - ainsi que leurs liens de "parenté" - tournant sur le système, et constitue une bonne représentation de la notion que nous venons d'aborder:

# sortie abrégée pour lisibilité
# en vrai il y a bien plus de processus lancés
$ pstree -T -p -A
systemd(1)-+-ModemManager(1164)
           |-NetworkManager(1064)
           |-accounts-daemon(1057)
           |-acpid(1058)
           |-at-spi-bus-laun(1416)---dbus-daemon(1421)
           |-at-spi-bus-laun(2819)
           |-at-spi2-registr(1455)
           |-avahi-daemon(1060)---avahi-daemon(1122)
           |-bluetoothd(1357)
           |-colord(1585)
           |-cron(1061)
           |-cups-browsed(1158)
           |-cupsd(1062)
           |-dbus-daemon(1063)
           |-dbus-daemon(1874)
           |-dbus-launch(1873)
           |-dconf-service(4336)
           |-snapd(1101)
           |-ssh(2212)
           |-ssh(2427)
           |-ssh(13369)
           |-ssh(19621)
           |-ssh-agent(2109)
           |-switcheroo-cont(1107)
           |-systemd(1214)-+-(sd-pam)(1215)
           |               |-dbus-daemon(1231)
           |               |-goa-daemon(1310)
           |               |-goa-identity-se(1327)
           |               |-gvfs-afc-volume(1343)
           |               |-gvfs-goa-volume(1304)
           |               |-gvfs-gphoto2-vo(1334)
           |               |-gvfs-mtp-volume(1338)
           |               |-gvfs-udisks2-vo(1278)
           |               |-gvfsd(1255)
           |               |-gvfsd-fuse(1270)
           |               |-pulseaudio(1226)
           |               `-tracker-miner-f(1228)
           |-tmux: server(2403)-+-bash(2404)
           |                    |-bash(2414)---miskatonic.sh(2422)---ssh(2423)
           |                    |-bash(2447)---mosh-client(2480)
           |                    `-bash(2495)---pstree(23527)
           |-udisksd(1110)
           |-unattended-upgr(1195)
           |-upowerd(1358)
           |-whoopsie(1683)
           |-wmii(1878)
           |-wmiirc(1876)-+-witray(1906)
           |              |-wmiir(2035)
           |              |-wmiirc(2009)---sleep(23524)
           |-wpa_supplicant(1111)
           `-xdg-permission-(1442)

Les utilisateurs et l'accès au système

Accès local

L'accès local à la machine se fait via votre couple login/mot de passe, soit directement en console, soit, si une interface graphique a été installée ainsi qu'un /gestionnaire de login/ (LightDM, etc), via une interface graphique.

Accès distant (SSH)

L'accès par SSH (Secure SHell, aka OpenBSD OpenSSH) se fait soit par login/mot de passe (A EVITER A TOUT PRIX!!!!!) soit en utilisant un couple de clefs asymétriques (une clef privée à conserver de façon sécurisée et de préférence individuelle, et une clef publique librement distribuable).

Sur la machine client, pour générer un couple de clefs:

# la clef par défaut s'appelle id_algodechiffrement
# ex: id_rsa, id_ed25519, etc. Attention, si vous avez déjà
# un couple de clefs id_rsa et id_rsa.pub à ne pas l'overwrite!
# ici, un couple de clefs RSA de 4096 bits de taille.
# Par défaut 2048 bits, considéré "suffisant" mais faible
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/maclef
$ ssh-copy-id -i ~/.ssh/maclef user@machine_distante
# avec une phrase de passe, c'est mieux ;)
# Ou:
$ scp ~/.ssh/maclef.pub user@machine_distante
# Puis sur le serveur:
$ cat maclef.pub >> ~/.ssh/authorized_keys

Il faudra ensuite configurer le serveur SSH pour ne pas autoriser l'authentification par login/mot de passe. On reviendra là dessus en détail dans la partie LAMP.

Typiquement, on décommentera la ligne:

# on édite le fichier /etc/sshd/sshd_config
PasswordAuthentification Yes
# et on remplace Yes par No:
PasswordAuthentification No
# Dans la foulée, si ce n'est pas déjà fait,
# On désactive l'accès superutilisateur distant:
PermitRootLogin No
# on sauvegarde et on quitte
# puis on relance le service sshd:
$ sudo systemctl restart sshd

Les fichiers sous UNIX et GNU/Linux: "Tout est fichier".

Répertoire de connexion ($HOME)

Tout d'abord, lorsqu'on se connecte à son compte utilisateur, on se retrouve dans son répertoire utilisateur, en général situé dans:

$ pwd
/home/mon_utilisateur
# par exemple dans mon cas:
$ pwd
/home/lidstah

NOTE: le répertoire de l'utilisateur root, le super-utilisateur, est situé dans /root

Votre répertoire personnel est aussi référencé par la /variable/ $HOME. Où que vous soyez dans l'arborescence, si vous tapez:

# cd signifie Change Directory.
/home/lidstah/documents/cours/ $ cd $HOME
# qui peut simplement s'abréger ~:
/home/lidstah/documents/cours/ $ cd ~
# ou plus simplement:
/home/lidstah/documents/cours/ $ cd 

Vous serez immédiatement "transportés" dans votre répertoire utilisateur personnel.

Ce répertoire sert à stocker toutes vos données utilisateur personnelles:

Tous ces fichiers ne sont, par défaut, modifiables que par vous même, et le super-utilisateur root.

Répertoires

Bien évidemment, on peut créer des répertoires et sous répertoires dans notre répertoire utilisateur. Globalement, les répertoires sous GNU/Linux ou UNIX sont similaires à ce que vous pouvez utiliser sous Windows®© ou macOS®© (qui reste un UNIX). Sous UNIX, GNU/Linux ou macOS, un répertoire est toujours exécutable.

Pour créer un nouveau répertoire, on utilise la commande mkdir: (la commande pwd signifie Print Working Directory, et elle affichera dans quel répertoire vous vous trouvez):

$ mkdir test
$ cd test
$ pwd
$ cd
$ pwd

Bien sûr, on peut vouloir créer directement un répertoire, et un sous-répertoire de ce répertoire, pour cela on utilisera l'option -p:

$ cd
$ mkdir -p test2/folder
$ cd test2/folder
$ pwd

On peut aussi vouloir créer plusieurs sous-répertoires d'un coup:

$ cd
$ mkdir -p test3/{a,b,c}
$ ls -l test3
total 12
drwxrwxr-x 2 lidstah lidstah 4096 oct.  20 19:26 a
drwxrwxr-x 2 lidstah lidstah 4096 oct.  20 19:26 b
drwxrwxr-x 2 lidstah lidstah 4096 oct.  20 19:26 c
# on supprime notre répertoire et ses sous-répertoires:
# ATTENTION avec cette commande: rm signifie ReMove ;)
$ rm -r test3

Chemins absolus et relatifs

On peut indiquer le chemin d'un fichier - par exemple notre répertoire test de tout à l'heure, de plusieurs façons différentes. Soit de façon absolue:

$ cd /home/lidstah/test
# qu'on peut abréger:
$ cd ~/test

soit de façon relative par rapport à notre position dans le système de fichiers. Si je suis dans mon répertoire test2:

$ cd test2
$ pwd
$ cd ../test 
$ pwd

On peut donc considérer que le chemin absolu représente la position exacte du fichier ou du répertoire que l'on veut ouvrir, éditer, etc sur nos disques, là où le chemin relatif représente la position du répertoire ou du fichier que l'on veut atteindre par rapport à notre position actuelle.

Types de fichiers

Il y a plusieurs types de fichiers sous UNIX et GNU/Linux:

Tout fichier possède comme information son nom, et son numéro d'/inode/.

Nous allons regarder la commande file qui nous permet de connaître le type d'un fichier:

$ file .bashrc
.bashrc: ASCII text
$ file .config
.config: directory
$ file /dev/sda
/dev/sda: block special (8/0)

On peut aussi facilement déterminer le type d'un fichier en regardant par exemple le résultat de la commande ls -l:

$ ls -al
drwx------ 29 lidstah lidstah   12288 oct.  20 21:25  Downloads
-rw-rw-r--  1 lidstah lidstah   10136 févr. 14  2020 .emacs

Le premier caractère nous indique le type du fichier. Ici, Downloads est un répertoire (Directory, indiqué par d) et .emacs un fichier (caché) régulier (indiqué par -).

Pour résumer:

Caractère Type de fichier
d répertoire
- fichier régulier
l lien symbolique
s socket UNIX
p named pipe (FIFO)
c périphérique caractère
b périphérique bloc

Le super-utilisateur (born to be root)

root est le super-utilisateur sous GNU/Linux et UNIX. Il dispose de tous les droits, sur tous les fichiers, tous les groupes, tous les utilisateurs. Dès lors il est fortement déconseillé de se /logger/ constamment en root: la moindre erreur peut avoir des effets catastrophiques. Par exemple, rien n'empêche root d'écrire directement dans un fichier de périphérique de type bloc ou caractère, pouvant potentiellement /briquer/ une machine (rien ne vous empêche en tant que root d'écrire n'importe quoi dans l'UEFI d'une machine... la transformant potentiellement en coûteux cale-porte).

Plus sérieusement, lorsqu'en tant qu'utilisateur on désire apporter des modifications au système, par exemple pour modifier un fichier de configuration, il est préférable d'utiliser une /élévation de privilèges/ temporaire via la commande sudo (bien sûr votre utilisateur doit faire partie du groupe correspondant pour avoir ces droits, ou être renseigné manuellement dans le fichier /sudoers/). On peut facilement différencier dans un terminal si on est loggé en tant que root ou en tant qu'utilisateur avec le dernier caractère du /prompt/:

# prompt d'un utilisateur standard (si le prompt $PS1 n'a pas été modifié):
$
# prompt root, un dièse:
# 

De même, il est conseillé de ne jamais lancer de service ou logiciel en tant que root. Par exemple, un serveur web sera, suivant les distributions, lancé en tant qu'utilisateur /www-data/, ou /httpd/, MariaDB ou MySQL en tant qu'utilisateur /mysql/, postgreSQL en tant qu'utilisateur /postgres/, etc. Le but étant ici de limiter les dégâts si un attaquant gagne l'accès au système via un de ces logiciels.

Cependant, il peut être nécessaire de se logger temporairement en tant qu'utilisateur root, pour ce faire:

# taper VOTRE mot de passe pour vous logger en root
# avec votre shell de login
$ sudo -i
# ou avec le shell spécifié par la variable d'environnement $SHELL
$ sudo -s
# ou directement en root, avec le mdp root
$ su -

sudo signifie /Summon User DO/

su signifie simplement /Summon User/

Les commandes de base

Présentation

Si vous êtes amenés à travailler sur des serveurs GNU/Linux ou UNIX, vous interagirez avec ces machines principalement en mode texte. Dès lors il est important de bien comprendre les concepts derrière l'interface en ligne de commande (/CLI/) sous ces OS. Toutes les commandes répondent à ce synopsis:

commande [options] arguments
# ex:
$ ls -al /etc

L'utilitaire /man/ vous permet de consulter les pages de manuel d'une commande, par exemple:

# pour consulter la page de manuel de man:
$ man man

Je vous encourage fortement, lorsque vous voyez une commande sur Internet dont vous ne savez pas ce qu'elle fait exactement, à lire la /manpage/ correspondante afin de comprendre ce que la commande, les options et les arguments font avant de copier/coller n'importe quoi depuis Stack Overflow 😃

Commandes de manipulation des fichiers

$ ls
$ ls /etc
# afficher une liste et les métadonnées des fichiers
$ ls -l /etc
# afficher les fichiers cachés
$ ls -al ~
# du plus récent au plus ancien
$ ls -lt
# du plus ancien au plus récent
$ ls -lrt
$ cp fichier repertoire/de/destination
# copier un fichier dans le répertoire courant
$ cp /etc/profile .
# copier tous les fichiers d'un répertoire dans un autre:
$ cp repertoire1/* repertoire2/
# copier récursivement (y compris les sous-répertoires)
$ cp -r repertoire1/* repertoire2/
# man cp ;)
# déplacer/renommer un fichier:
$ mv fichier fichier2
# déplacer les fichiers d'un répertoire dans un autre
# (y compris les sous-répertoires)
$ mv repertoire/* repertoire2/
# man mv 8)
$ rm fichier
# supprimer un répertoire
$ rm -r repertoire
# supprimer plusieurs répertoires
$ rm -r repertoire repertoire2 repertoire3...
# forcer la suppression /!\
$ rm -rf repertoire
# demander une confirmation (faites un alias, cf plus bas)
$ rm -i fichier
$ rm -ir repertoire
# man rm ;)
# afficher le contenu d'un fichier
$ cat fichier
# concaténer le contenu de deux fichiers
# et sauvegarder le résultat dans un 3è
$ cat fichier1 fichier2 > fichier3

Pour commencer, on utilisera nano afin que vous ne soyez pas trop perdus 😉

$ nano fichier
# ou avec élévation de privilèges:
$ sudo nano /etc/hosts

Les commandes séquentielles, regroupement et imbrication de commandes

On peut bien sûr enchaîner les commandes sur une même ligne:

$ ls; who; id

Ou enchaîner une commande si la première a réussi:

$ ls && who

À l'inverse, enchaîner une commande si la première a échoué:

$ ls || who

On peut aussi envoyer le résultat d'une commande dans l'entrée standard d'une autre commande, en utilisant l'opérateur /pipe/ (|) - vous vous en servirez souvent, trèèèèès souvent 😃 :

$ ls -al | grep conf

On peut aussi regrouper des commandes en les mettant entre parenthèses:

$ (ls;who) > fichier

Et enfin, on peut aussi imbriquer des commandes en utilisant $() (plus récent) ou `` (/backticks/, historique):

$ echo "Nous sommes à "$(date +%s)" secondes depuis le 1/01/1970"
$ echo "Nous sommes à "`date +%s`" secondes depuis le 1/01/1970"

Avec la syntaxe $(), on peut imbriquer des commandes dans des commandes, i.e:

$ VAR=$($(commande);$(autre commande))

Les alias

On peut aussi créer un alias pour une commande utilisée souvent:

$ alias gp=git pull

Et le conserver en l'ajoutant à son fichier de configuration bash: .bashrc

Redirections des entrées et sorties

Sous UNIX et GNU/Linux (et sous les autres OS du même style comme Plan9), on peut rediriger la sortie d'une commande vers un fichier. Comme tout est fichier, on peut tout à fait faire (en partant du principe que la configuration sonore de l'OS est correcte):

$ cat music.wav > /dev/audio

Ici, /cat/ envoie sa sortie, c'est à dire le contenu de music.wav au fichier de périphérique audio.

On peut aussi concaténer des fichiers, comme montré plus haut.

On peut bien sûr rediriger la /sortie standard/ (stdout) de toute commande vers un fichier, ainsi que sa sortie d'erreur (stderr), ou rediriger l'entrée standard (stdin) d'une commande depuis un fichier. Ici, on redirige le stdout de la commande ls vers un fichier :

$ ls -al > liste
$ cat liste

Maintenant, que se passe-t-il si je fais:

$ echo "coucou" > bonjour
$ cat bonjour
$ echo "comment va?" > bonjour
$ cat bonjour

La sortie de la seconde commande, redirigée dans le fichier "bonjour", a écrasé la sortie de la première commande. Il a donc réécrit le fichier. Si on veut ajouter (/append/) la sortie d'une commande à un fichier déjà existant, on utilisera l'opérateur >>:

$ echo "coucou" > bonjour
$ cat bonjour
$ echo "comment va?" >> bonjour
$ cat bonjour

De même, on peut vouloir rediriger la sortie d'erreur (stderr) d'une commande vers un fichier, par exemple (on ne peut pas créer de répertoire dont le nom est vide, la commande va donc générer une erreur):

$ mkdir '' 2> erreur
$ cat erreur
# bien sur on peut aussi "append" :)
$ find '' 2>>erreur
$ cat erreur

On peut bien évidemment rediriger le contenu d'un fichier sur l'entrée standard d'une commande:

$ head < fichier
# on peut aussi simplement faire:
$ head fichier

Plus rigolo, convertir un fichier en ALL CAPS PARCEQUE MOI AUSSI JE PEUX ECRIRE COMME TRUMP:

$ echo "gnu/linux rules!" > fichier
$ tr a-z A-Z < fichier
GNU/LINUX RULES!

Bien évidemment, je peux aussi vouloir sauvegarder mon oeuvre dans un nouveau fichier:

$ tr a-z A-Z < fichier > fichier2
$ cat fichier2
GNU/LINUX RULES!

On peut - on l'a vu précédemment - rediriger la sortie d'une commande vers l'entrée standard d'une commande, via l'opérateur /pipe/ |. On peut faire des choses assez sympa:

$ tail -100000 /var/log/haproxy.log | awk '{ print $6 }' | sed 's/:.*$//g' \
  | sort -n | uniq -c | sort -nr | head -50 > potential_abuse

Les filtres ("Globs")

Bash (le shell par défaut sur la plupart des distributions GNU/Linux) ne supporte pas les expressions régulières POSIX, contrairement à beaucoup de langages de programmation et d'utilitaires du système (grep, sed, awk, vim, etc) ou logiciels (nginx, apache, haproxy, etc). À la place il utilise un mécanisme qu'on appelle /globbing/ afin de lui permettre de proposer des fonctionnalités équivalentes.

Tout d'abord, tout comme pour les regexes, un petit tableau récapitulatif:

caractère signification exemple
? /matche/ n'importe quel caractère tout seul ls ??.c
* /matche/ zéro ou plusieurs caractère(s) ls b*.sh
A-Z /matche/ le caractère s'il est dans l'intervalle ls a-z??.sh
^ début de ligne grep '^[a-d]' fichier
! idem que ^ mais dans le range grep '[!a-d]' fichier
$ fin de ligne
{pat1,pat2,...} /matche/ les noms de fichiers correspondant aux patterns rm \{*.doc,???.xlsx\}
| applique une ou plusieurs conditions au glob pattern exemple plus bas 😉
$ ls a*+(.c|.sh|.ksh)

#!/bin/bash

echo "Quelle opération voulez vous faire?"
read reponse
case $reponse in
  1 | R ) echo "Reboot";;
  2 | P ) echo "Poweroff";;
  *) echo "nope nope nope";;
esac

Autres commandes

Parmi les commandes les plus utiles qu'on peut trouver sous GNU/Linux:

# Afficher les adresses IPs de toutes les interfaces réseau
$ ip address show
# assigner une IP à une interface:
$ sudo ip addr add 10.10.10.1/24 dev interfaceréseau
#supprimer une IP
$ sudo ip addr del 10.10.10.1/24 dev interfaceréseau
#afficher la table de routage
$ ip route show
#ajouter une route
$ sudo ip route add 10.10.10.0/24 via 192.168.42.1 dev eth0
#supprimer une route
$ sudo ip route del 10.10.10.0/24 via 192.168.42.1 dev eth0
#couper une interface
$ sudo ip link set dev eth0 down
#inversement:
$ sudo ip link set dev eth0 up

grep permet de sélectionner toutes les lignes contenant un pattern:

$ ip addr show | grep inet
#sélectionne toutes les lignes commençant par if
$ grep ^if /etc/bash.bashrc
# sélectionner toutes les lignes commençant par if
# dans un répertoire, récursif
$ grep -R ^if /etc/

Je vous invite fortement à lire la /manpage/ de grep ainsi que les tutos en ligne que vous pourrez trouver. Ainsi que les manpages des utilitaires suivants...

/head/ et /tail/ permettent respectivement d'afficher la première et la dernière ligne d'un fichier, ou les /n/ premières ou /n/ dernières lignes d'un fichier:

# les 50 dernières lignes de syslog
$ tail -50 /var/log/syslog
# les 50 premières lignes de syslog
$ head -50 /var/log/syslog
# les lignes 80 à 100 de syslog:
$ head -100 /var/log/syslog | tail -20

tail peut aussi être utilisé pour suivre (/follow/) un fichier au fur et à mesure qu'il se remplit:

$ tail -f /var/log/syslog

cut permet de sélectionner un élément ou plusieurs d'une ligne en fonction d'un séparateur. Par exemple un fichier csv où chaque champ de chaque ligne sont séparés par ";", pour sélectionner le 4è élément:

$ cut -d";" -f4 fichier.csv
# pour sélectionner les champs 1 et 2:
$ cut -d";" -f1,2 fichier.csv
# pour sélectionner les champs à partir du 4ème
$ cut -d";" -f4- fichier.csv

Dans certains cas, si les champs sont séparés "aléatoirement" par des espaces et des tabulations par exemple (fichiers de log, etc), awk permet de facilement contourner ce problème:

# pour sélectionner les champs 1 et 3:
$ awk '{ print $1" "$3 }' fichier.csv

sort permet de réorganiser le contenu d'un fichier suivant des règles définies (par ordre alphabétique, numérique, alphabétique ou numérique inverse, random (mélanger), par numéro de version, etc.

uniq permet de compter les lignes identiques, ou de les omettre, ou de n'afficher que les lignes uniques d'un fichier (ou de son entrée standard, c'est la même chose au final).

Ces deux utilitaires combinés permettent de faire beaucoup de choses sympa:

$ kubectl get svc -A | awk '{ print $5 }' | egrep -v "(EXTER|none)"
192.168.1.230
192.168.1.137
192.168.1.131
192.168.1.226
192.168.1.132
192.168.42.236
192.168.1.227
192.168.42.235
192.168.1.138
192.168.1.223
192.168.1.228
192.168.1.130
192.168.1.224
192.168.1.133
192.168.1.136
192.168.1.135
192.168.1.221
192.168.1.222

Pas très lisible?

$ kubectl get svc -A | awk '{ print $5 }' | egrep -v "(EXTER|none)" | sort -n
192.168.1.130
192.168.1.131
192.168.1.132
192.168.1.133
192.168.1.135
192.168.1.136
192.168.1.137
192.168.1.138
192.168.1.221
192.168.1.222
192.168.1.223
192.168.1.224
192.168.1.226
192.168.1.227
192.168.1.228
192.168.1.230
192.168.42.235
192.168.42.236

Mieux, non?

wc /Word Count/ permet de compter les caractères, mots et lignes d'un fichier:

$ wc .bashrc
 124  540 3959 .bashrc
#le fichier .bashrc contient donc 124 lignes, 540 mots et 3959 caractères.
$ wc -l .bashrc
124 .bashrc
$ wc -w .bashrc
540 .bashrc
$ wc -c .bashrc
3959 .bashrc
$ grep CRON /var/log/syslog | wc -l
144

l'utilitaire column permet d'organiser en colonnes "humainement lisibles" son entrée standard (ou un fichier).

Enfin, l'utilitaire sed /Stream EDitor/ permet de modifier, remplacer, supprimer des lignes ou des /patterns/ dans un fichier, ou dans plusieurs fichiers récursivement. Il est un peu trop complexe pour ce cours, ceci dit 😃

Manipulation des processus

kill

La commande /kill/ permet d'envoyer un /signal/ à un processus - et pas nécessairement pour le stopper (le "tuer").

Sa syntaxe est du type:

$ kill -[signal] PID

Et les différents signaux que l'on peut lui envoyer sont:

Numéro Nom Description
1 SIGHUP Fin de session
2 SIGINT Interruption
3 SIGQUIT Instruction QUIT
4 SIGILL Illegal Instruction
5 SIGTRAP Trap
6 SIGABRT Annulation
7 SIGBUS Bus error
8 SIGFPE Exception FPU
9 SIGKILL Termine le processus salement
10 SIGUSR1 Signal Utilisateur (si prévu)
11 SIGSEGV Segmentation fault
12 SIGUSR2 Signal Utilisateur 2
13 SIGPIPE PIPE Error
14 SIGALRM Alarme Horloge
15 SIGTERM Termine proprement le processus
16 SIGSTKFLT Erreur de pile
17 SIGCHLD Modification du statut d'un processus enfant
18 SIGCONT Reprise du processus
19 SIGSTOP Demande de suspension forcée
20 SIGTSTP Stop depuis le clavier
21 SIGTTIN lecture terminal en arrière-plan
22 SIGTTOU entrée terminal en arrière-plan
23 SIGURG évènement urgent sur socket
24 SIGXCPU Temps CPU maximum écoulé
25 SIGXFSZ Taille maximale de fichier atteinte
26 SIGVTALRM Alarme
27 SIGPROF Profilage de l'horloge alarme
28 SIGWINCH changement de la taille de fenêtre
29 SIGPOLL occurence d'un évènement attendu
30 SIGIO I/O possible
31 SIGSYS Erreur d'appel système
32 SIGUNUSED

Alors, en général, lorsqu'on veut "tuer" un processus, on va d'abord essayer de le tuer proprement, en lui envoyant le signal SIGTERM (pour qu'il puisse "tuer" tous ses "enfants" avant de se tuer (dit comme ça c'est un peu glauque 😃). Si jamais SIGTERM ne fonctionne pas, on utilisera alors SIGKILL:

$ kill -15 1234
$ kill -9 1234

Bien sûr, on peut utiliser la commande /pgrep/ en l'imbriquant pour tuer un processus en utilisant son nom plutôt que son numéro de PID:

$ kill -15 $(pgrep vim)

top, htop

On peut aussi visualiser en temps réel les processus en cours d'exécution, la RAM et le temps CPU qu'ils consomment, etc, via la commande /top/ (intégrée) ou la commande /htop/ (à installer):

$ top
# q pour quitter

Pour installer htop:

$ sudo apt install htop
$ htop
#q pour quitter

ps

La commande ps nous permet de lister les processus en cours d'exécution par notre utilisateur, ou par tous les utilisateurs du système selon les options que l'on va lui fournir.

$ ps
$ ps aux
# grep est notre ami:
$ ps aux|grep systemd

Bien évidemment je vous invite fortement à lire la /manpage/ de ps 😉

pstree

pstree nous indique les relations entre les processus (qui est parent, qui est enfant, etc) sous forme d'arbre. Vous en avez un exemple en début de cours 😉

nice et renice

nice et renice nous permettent de gérer la /priorité/ d'un processus par rapport aux autres processus. C'est à dire le temps CPU qui lui sera alloué.

Gestion des paquets: Mises à jour, installation et suppression de logiciels avec apt

Contrairement à certains systèmes propriétaires que je ne citerai pas, sous UNIX et GNU/Linux, on évite généralement d'installer des logiciels en provenance de n'importe où. On les installe via un gestionnaire de paquets, qui va aller récupérer nos logiciels ainsi que leurs /dépendances/ (bibliothèques de fonctions ou autres logiciels nécessaires au bon fonctionnement du logiciel que l'on installe) depuis les dépôts de notre distribution, qui stockent les paquets (logiciels et bibliothèques de fonction) de la distribution, et qui les signe cryptographiquement afin d'être sûr que nous téléchargeons les bons paquets depuis les bons serveurs.

Typiquement, les gens sur Internet qui se plaignent que c'est "difficile d'installer les drivers Nvidia" tentent de les installer à la sauce Windows: ils vont aller télécharger les drivers sur le site de Nvidia et essayer de les installer via le script (moisi) fourni. Ce qui est une erreur. Sous Debian ou Ubuntu, on installera les drivers propriétaires Nvidia en activant les dépôts non libres (non-free).

# mettre à jour la base de données des paquets:
$ sudo apt update
# sous centos:
$ sudo yum update
# mettre à jour le système et les paquets installés:
$ sudo apt upgrade
# mettre à jour le système en supprimant les paquets non-utiles:
$ sudo apt dist-upgrade

Typiquement, dans un environnement critique, qui doit rester stable (au hasard: serveur de bases de données) on préfèrera utiliser upgrade, sinon on utilisera (desktop, environnement peu critique (preprod, etc)): dist-upgrade

Bien sûr, on veut aussi parfois supprimer des paquets, dont on ne se sert plus, ou installer de nouveaux paquets. Par exemple, nous allons installer l'éditeur de texte joe, et le supprimer ensuite (je n'ai rien contre /joe/ qui est un très bon éditeur de texte, méconnu):

$ sudo apt install joe
...
$ sudo apt remove joe

On peut aussi vouloir chercher des paquets dont le nom ou la description correspondent à un certain pattern, par exemple PHP:

# pas besoin d'élévation de privilège:
$ apt search php

Le(s) système(s) de fichiers

Introduction

Contrairement à certains systèmes d'exploitation propriétaires, les systèmes d'exploitation GNU/Linux permettent d'utiliser un grand nombre de systèmes de fichiers différents. Par exemple:

Arborescence des répertoires

lidstah@deb-RAID0:~$ tree -L 1 /
/
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── initrd.img -> boot/initrd.img-4.19.0-12-amd64
├── initrd.img.old -> boot/initrd.img-4.19.0-10-amd64
├── lib -> usr/lib
├── lib32 -> usr/lib32
├── lib64 -> usr/lib64
├── libx32 -> usr/libx32
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
├── var
├── vmlinuz -> boot/vmlinuz-4.19.0-12-amd64
└── vmlinuz.old -> boot/vmlinuz-4.19.0-10-amd64
Répertoire Utilisation
bin Utilitaires système
boot bootloader et kernels
dev périphériques
etc fichiers de configuration
home répertoires utilisateurs
lib bibliothèques de fonctions
media points de montage pour médias amovibles
mnt points de montage
opt logicels optionnels (peu utilisé)
proc processus
root répertoire super-utilisateur
run pids, sockets
sbin Exécutables pour administrateurs
srv Serveurs (ftp, etc. Historique)
sys FS Kernel (manipulation des paramètres du kernel)
tmp fichiers temporaires
usr exécutables, bibliothèques de fonctions installés par l'utilisateur
var logs, données de BDD, mailboxes, etc

les distributions GNU/Linux et UNIX en général suivent (à peu près) le /Filesystem Hierarchy Standard/ (FHS):

https://fr.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

À la différence de nombreux autres systèmes d'exploitation, les partitions et disques ne sont pas indiqués par un nom spécifique (C:, D:, MacintoshHD, etc) mais leurs fichiers de périphérique sont montés sur des répertoires du système de fichiers.

Par exemple, la partition contenant la racine du système d'exploitation est montée sur /.

La partition contenant le kernel et le bootloader est elle montée sur le répertoire /boot.

Assez souvent, une troisième partition est montée sur le répertoire /home.

Plus précisément, on peut monter n'importe quelle partition de n'importe quel disque où bon nous semble (attention, le répertoire de montage doit être vide). On pourrait par exemple vouloir monter un ensemble de disques configurés en RAID-5 sur /srv afin de stocker nos données FTP ou autres sur ce disque.

On va voir comment faire en ajoutant un disque à notre VM Linux:

mount: "monter" des périphériques de stockage et umount ("démonter")

partitionner et formater un nouveau disque

Tout d'abord, on va vouloir identifier le(s) disque(s) déjà montés sur notre VM:

$ mount | grep "/dev"
udev on /dev type devtmpfs (rw,nosuid,relatime,size=747660k,nr_inodes=186915,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
mqueue on /dev/mqueue type mqueue (rw,relatime)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
/dev/sdb1 on /home/raid0 type ext4 (rw,noatime)
$ df -h
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
udev               731M       0  731M   0% /dev
tmpfs              149M    460K  149M   1% /run
/dev/sda1           39G    2,8G   34G   8% /
tmpfs              745M       0  745M   0% /dev/shm
tmpfs              5,0M       0  5,0M   0% /run/lock
tmpfs              745M       0  745M   0% /sys/fs/cgroup
/dev/sdb1          1,8T    160G  1,5T  10% /home/raid0
tmpfs              149M       0  149M   0% /run/user/1000

Normalement, vous ne devriez avoir que des partitions du périphérique sda (Sata Disk A) montées sur vos machines (minus les points de montage mémoire comme udev, tmpfs, etc) et typiquement uniquement la partition sda1. On va donc regarder la liste des périphériques de stockage connectés à notre machine:

$ sudo fdisk -l
Disque /dev/sdb : 1,8 TiB, 1904817995776 octets, 3720347648 secteurs
Modèle de disque : QEMU HARDDISK   
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : gpt
Identifiant de disque : C285FA67-D48E-5D49-A3A2-8D7AB8F8DBE0

Périphérique Début        Fin   Secteurs Taille Type
/dev/sdb1     2048 3720347581 3720345534   1,7T Système de fichiers Linux


Disque /dev/sda : 40 GiB, 42949672960 octets, 83886080 secteurs
Modèle de disque : QEMU HARDDISK   
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets
Type d'étiquette de disque : dos
Identifiant de disque : 0x9d80190a

Périphérique Amorçage    Début      Fin Secteurs Taille Id Type
/dev/sda1    *            2048 81788927 81786880    39G 83 Linux
/dev/sda2             81790974 83884031  2093058  1022M  5 Étendue
/dev/sda5             81790976 83884031  2093056  1022M 82 partition d'échange Linux / Solaris




Disque /dev/sdc : 4 GiB, 4294967296 octets, 8388608 secteurs
Modèle de disque : QEMU HARDDISK   
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 512 octets
taille d'E/S (minimale / optimale) : 512 octets / 512 octets

$ sudo dmesg | tail -10
[503471.949683] Btrfs loaded, crc32c=crc32c-generic
[503471.970591] fuse init (API version 7.27)
[3957953.844366] scsi 2:0:0:2: Direct-Access     QEMU     QEMU HARDDISK    2.5+ PQ: 0 ANSI: 5
[3957953.846326] sd 2:0:0:2: Power-on or device reset occurred
[3957953.849414] sd 2:0:0:2: [sdc] 8388608 512-byte logical blocks: (4.29 GB/4.00 GiB)
[3957953.849497] sd 2:0:0:2: [sdc] Write Protect is off
[3957953.849500] sd 2:0:0:2: [sdc] Mode Sense: 63 00 00 08
[3957953.849624] sd 2:0:0:2: [sdc] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[3957953.852100] sd 2:0:0:2: Attached scsi generic sg3 type 0
[3957953.854567] sd 2:0:0:2: [sdc] Attached SCSI disk

Ici, on voit que mon périphérique sdc n'est pas partitionné, et qu'il vient juste d'être "branché" à chaud.

Je vais donc le partitionner. Pour cela, on va utiliser l'utilitaire /cfdisk/ - on pourrait aussi utiliser fdisk, mais cfdisk est plus /user-friendly/.

$ sudo cfdisk /dev/sdc

Puis on va formater notre partition en EXT4:

$ sudo mkfs.ext4 /dev/sdc1

montage et démontage manuel

Et on va pouvoir monter cette partition, par exemple sur /mnt:

$ sudo mount /dev/sdc1 /mnt
$ df -h
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
udev               731M       0  731M   0% /dev
tmpfs              149M    476K  149M   1% /run
/dev/sda1           39G    2,8G   34G   8% /
tmpfs              745M       0  745M   0% /dev/shm
tmpfs              5,0M       0  5,0M   0% /run/lock
tmpfs              745M       0  745M   0% /sys/fs/cgroup
/dev/sdb1          1,8T    160G  1,5T  10% /home/raid0
tmpfs              149M       0  149M   0% /run/user/1000
/dev/sdc1          3,9G     16M  3,7G   1% /mnt

On va maintenant la démonter proprement:

$ sudo umount /mnt
$ df -h
#/mnt ne devrait plus être présent

fstab: persistence du montage des périphériques au boot

On va dire que notre nouvelle partition va nous servir à stocker les données de notre base de données MariaDB/MySQL. Par défaut sous Debian, les données de MariaDB ou MySQL sont stockées dans le répertoire:

/var/lib/mysql

On va déjà vérifier que ce répertoire n'existe pas, et le créer le cas échéant:

$ ls -al /var/lib|grep mysql
#ne devrait rien renvoyer
$ sudo mkdir /var/lib/mysql

Maintenant, ça peut être utile que la partition que nous avons créée soit montée au boot sur ce répertoire, histoire que notre base de données ne se plante pas au démarrage 😃. Pour cela, on va modifier le fichier fstab qui se trouve dans le répertoire /etc:

$ sudo nano /etc/fstab

Surtout, on ne supprime pas les autres entrées de ce fichier. Dans votre cas, cette nouvelle partition doit être sdb1, dans mon cas, c'est sdc1:

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda1 during installation
UUID=c78dabc3-85a3-4697-8d60-52d8de57f591 /               ext4    errors=remount-ro 0       1
# swap was on /dev/sda5 during installation
UUID=271218ac-fa47-4067-b0ae-5c315d1ea253 none            swap    sw              0       0
/dev/sr0        /media/cdrom0   udf,iso9660 user,noauto     0       0

/dev/sdb1       /home/raid0     ext4    async,noatime,acl       0 0
# J'ajoute ma partition sdc1:
/dev/sdc1       /var/lib/mysql  ext4    defaults 0 0

Une fois sauvegardé, on peut soit rebooter pour que les modifications soient prises en comptes, soit simplement exécuter:

$ sudo mount -a
$ df -h

Pour parcourir le contenu de fstab à nouveau et monter tout périphérique n'étant pas déjà monté.

Les droits d'accès

Notion d'utilisateur

Tout comme sous Windows, macOS, ou tout autre UNIX, GNU/Linux dispose de la notion d'utilisateur. Un utilisateur peut être un humain utilisateur de la machine, ou un utilisateur créé pour un service (par exemple, l'utilisateur www-data pour les serveurs web apache2, nginx, etc, ou l'utilisateur mysql pour MySQL/MariaDB.). Un utilisateur dispose de droits définis lors de sa création, que l'on peut ensuite modifier si besoin.

Les informations concernant un utilisateur sont accessibles de plusieurs façons:

$ id
uid=1000(lidstah) gid=1000(lidstah) groupes=1000(lidstah),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)
$ grep lidstah /etc/passwd
lidstah:x:1000:1000:lidstah,,,:/home/lidstah:/bin/bash
$ grep lidstah /etc/shadow
lidstah:hash_mdp:18111:0:99999:7:::

Regardons plus en détail la structure d'un utilisateur dans le fichier passwd:

user login x user id group id username répertoire $HOME shell de login
lidstah x 1000 1000 lidstah,,, /home/lidstah /bin/bash

Et du fichier shadow:

username hash mdp dernier changement de mdp (en jours depuis le 1/1/1970) nb jours entre changement de mdp Warning Inactif expire
lidstah hash_mdp 18111 0 99999

Notion de groupe

Afin de gérer au mieux les droits de nos utilisateurs, sans avoir à les assigner sur une base individuelle, on utilise des groupes d'utilisateurs, qui leur permette d'accéder à des fichiers ou ressources auxquels leur utilisateur seul n'a pas forcément accès. Lorsqu'on crée un utilisateur, on crée aussi sous Debian un groupe portant le nom de cet utilisateur. Sous d'autres UNIX ou distributions GNU/Linux, un nouvel utilisateur sera peut-être membre du groupe /users/. Un utilisateur peut bien sûr être membre de plusieurs groupes!

Par exemple, un utilisateur membre du groupe /sudo/ possède donc les droits nécessaires pour utiliser la commande sudo.

Catégories d'utilisateurs

Pour simplifier, on peut résumer les catégories d'utilisateurs sous UNIX et GNU/Linux en deux grands groupes:

Notion de propriété

Sous UNIX et GNU/Linux, tout - ou presque - est fichier. Ces fichiers (répertoires, périphériques, etc) appartiennent à un utilisateur et à un groupe précis.

Notion de permissions

Chaque fichier se voit assigné une /triade/ de droits: Les droits pour l'utilisateur auquel il appartient, les droits pour le groupe auquel il appartient, et le droit pour les Autres (c'est à dire n'importe qui d'autre).

lidstah@deb-RAID0:~$ ls -l
total 133592
-rw-r--r-- 1 lidstah lidstah      3392 oct.   1 12:00 iptables.rules
-rw-r--r-- 1 lidstah lidstah         0 sept.  9 19:27 masque
drwxr-xr-x 2 lidstah lidstah      4096 sept. 16 18:40 nc
drwxr-xr-x 2 lidstah lidstah      4096 sept. 12 11:28 regex
-rw-r--r-- 1 lidstah lidstah 136777573 oct.  20  2017 solr-5.5.5.tgz
drwxr-xr-x 2 lidstah lidstah      4096 nov.  24  2019 tor

Par exemple pour le fichier solr-5.5.5.tgz du listing ci-dessus, on peut voir:

type Utilisateur Groupe Autres Utilisateur propriétaire Groupe propriétaire
- rw- r-- r-- lidstah lidstah

Il s'agit d'un fichier normal, lisible, modifiable, mais pas exécutable pour l'utilisateur auquel il appartient (lidstah), et en lecture seule pour son groupe et les Autres.

Dès lors, pour modifier les droits d'un fichier, il est important de connaître:

NOTE: un répertoire doit toujours être exécutable!

Modification des permissions d'un fichier

#Changer, pour l'utilisateur courant, les droits du 
#fichier en read, write, execute
$ chmod u+rwx fichier
#Changer, pour l'utilisateur courant, les droits du 
#fichier en rwx, et enlever tous les droits au 
#groupe et aux Autres, deux méthodes:
$ chmod u+rwx,g-rwx,o-rwx fichier
#Ou plus simplement:
$ chmod 700 fichier
#On peut aussi directement affecter les droits avec a
$ chmod a+rw fichier

En effet, chmod permet d'utiliser une notation "humaine" et une notation "octale" pour la définition des droits.

Un petit tableau sur les valeurs octales et leur signification:

Valeur Droits
4 Read
2 Write
1 Execute
0 None

Et donc, pour les droits rwx: 4+2+1 = 7, rw: 4+2 = 6, read-only (read): 4, read et execute: 4+1 = 5... etc. On va pouvoir rapidement mettre ça en pratique 😃

Je vous incite fortement à lire les /manpages/ correspondantes 😃

Modification du propriétaire d'un fichier

#Changer l'owner et le groupe d'un fichier:
$ chown user:group fichier
#Changer de façon récursive l'utilisateur et le groupe 
#d'un répertoire et de son contenu:
$ chown -R user:group repertoire

La gestion des utilisateurs

Gestion des comptes utilisateurs

Créer un compte pour un nouvel utilisateur

Pour créer un nouvel utilisateur (humain), il faut:

Pour que cet utilisateur soit activé, il faut aussi qu'il ait un mot de passe 😃

Pour cela, on peut utiliser les commandes useradd ou adduser, au choix 😃

# créer l'utilisateur bidule, avec un répertoire /home/bidule
# et bash comme shell de login
$ sudo useradd -ms /bin/bash bidule
# avec adduser:
$ sudo adduser --shell /bin/bash bidule2
# adduser est plus complet, vous serez amené à choisir mot de passe,
# nom, etc de l'utilisateur lors de sa création

Le répertoire utilisateur est construit en se basant sur le contenu du répertoire:

/etc/skel/
ls -al /etc/skel

Tout fichier ou répertoire créé dans le répertoire skel sera copié dans le répertoire $HOME de l'utilisateur que nous créons. Ainsi, il est facile de provisionner des configurations toutes prêtes pour tel ou tel logiciel (éditeur de texte, shell, etc).

Attribuer ou modifier un mot de passe

Alors notre utilisateur "bidule" est créé, cependant, il n'a pas de mot de passe. On peut modifier son mot de passe, ou le mot de passe d'un utilisateur (si on dispose des droits suffisants) avec la commande passwd.

#pour modifier son mot de passe:
$ passwd
# pour modifier le mot de passe de l'utilisateur bidule:
$ sudo passwd bidule

Supprimer le compte d'un utilisateur

Là aussi, deux commandes: userdel et deluser

# -r pour supprimer le répertoire home de l'utilisateur
$ sudo userdel -r bidule
# la même version deluser:
$ sudo deluser --remove-home bidule2

Modifier le compte d'un utilisateur

On peut bien sûr modifier le compte d'un utilisateur: lui donner un nouveau home, l'ajouter à des groupes, le verrouiller, etc. La commande utilisée est usermod. Par exemple, recréons notre utilisateur /bidule/, puis modifions le pour l'ajouter au groupe "sudo":

$ sudo useradd -ms /bin/bash bidule
$ sudo passwd bidule
#ici, on veut l'ajouter (append) au groupe sudo
# pas remplacer les groupes auquel il appartient
# par le groupe sudo, d'où le "-a" pour append
$ sudo usermod -aG sudo bidule

On peut aussi vouloir déplacer son $HOME vers un autre répertoire:

$ sudo usermod -d /home/pwet -m bidule

Bien évidemment, je vous invite à lire la /manpage/ de usermod 😃

Les groupes

Créer un nouveau groupe

C'est très simple, il suffit d'utiliser la commande addgroup:

$ sudo addgroup nom_du_groupe

Supprimer un groupe

De même, pour supprimer un groupe, il suffit d'utiliser la commande delgroup:

$ sudo delgroup nom_du_groupe

Monter un serveur LAMP

Présentation

L'acronyme /LAMP/ signifie Linux, Apache, MySQL, et finalement PHP (mais ça marcherait aussi avec Python 😄), c'est à dire:

C'est une des utilisations les plus classiques de ces logiciels. Bien sûr, en (grosse) production, on y ajoutera des services supplémentaires, comme du load-balancing et du cache Web, et on utilisera des machines (physiques ou virtuelles) dédiées pour chaque logiciel, idéalement, redondantes.

Mais, que ce soit pour un petit site Web à faible trafic, pour un intranet de PME, pour une préproduction, ou pour développer un applicatif PHP, une VM "LAMP" nous fournira tout le nécessaire.

On va donc commencer par installer une nouvelle VM (bridgée SVP) Debian GNU/Linux, mais cette fois ci sans interface graphique: lors du choix des p aquets à installer, on décochera (en appuyant sur espace) "Environnement de bureau" et on cochera "serveur SSH" ainsi qu'"Utilitaires de base du système".

Configuration recommandée: 1 vCPU, 1Go RAM, 20Go disque.

On se connectera à cette VM via notre précédente VM "environnement de bureau" (qui doit donc être, si possible, elle aussi bridgée)

Une fois notre nouvelle VM installée, la première chose que nous allons faire est de sécuriser notre accès SSH à cette VM.

Sécurisation de l'accès distant par SSH

ATTENTION: CETTE ETAPE EST VITALE ET CE SUR TOUTE MACHINE ACCESSIBLE A DISTANCE

La première étape, sur notre client, est de générer notre couple de clefs asymétriques. On peut utiliser différents algorithmes comme RSA, ED25519, etc. Dans notre cas nous allons utiliser l'algorithme RSA, 4096 bits:

Sur notre VM cliente (i.e. notre VM "environnement de bureau"):

$ ssh-keygen -t rsa -b 4096

On ne va pas mettre de /passphrase/, et les noms des deux fichiers de notre couple de clefs seront /id_rsa/ (la clef privée qui ne doit jamais être transmise) et /id_rsa.pub/ (la clef publique que vous pouvez communiquer à tout le monde).

Si on avait voulu créer un couple de clefs dont le nom est "maclefperso" (et maclefperso.pub), on aurait utilisé la commande:

$ ssh-keygen -t rsa -b 4096 -f maclefperso

Dans mon cas, j'utilise un couple de clefs différent par client. Nos couples de clefs sont stockés dans ~/.ssh/ par défaut.

Maintenant, on va envoyer notre clef publique à notre VM "LAMP", depuis notre client:

$ ssh-copy-id -i ~/.ssh/id_rsa utilisateur@ip_vm_lamp

Cette clef est concaténée, côté VM LAMP dans le fichier:

~/.ssh/authorized_keys

On va vérifier que tout est OK sur notre VM LAMP:

$ cat .ssh/authorized_keys

On peut donc désormais se connecter à notre VM en utilisant notre couple de clefs, sans rentrer de mot de passe. Depuis notre VM "Desktop":

$ ssh utilisateur@ip_vm_lamp

Nous voilà donc, depuis notre VM Desktop, connectés à notre VM LAMP. On va en profiter pour modifier la configuration du serveur OpenSSH sur notre VM LAMP, en éditant le fichier:

# vous avez bien installé et configuré sudo comme sur notre 
# VM Desktop? :) 
$ sudo nano /etc/ssh/sshd_config
# On va chercher cette ligne:
PasswordAuthentification Yes
# on la décommente, et on remplace Yes par No:
PasswordAuthentification No
# Dans la foulée, si ce n'est pas déjà fait,
# On désactive l'accès superutilisateur distant:
PermitRootLogin No
# on sauvegarde et on quitte
# puis on relance le service sshd:
$ sudo systemctl restart sshd

Maintenant, on ne peut plus se connecter en SSH à notre VM LAMP qu'avec la bonne clef privée. Et plus avec un login/mot de passe. C'est littéralement la première chose que vous devriez faire sur chaque VM linux que vous créez 😃. Et c'est la première chose qu'on fait en production (enfin, c'est la première chose que nos recettes font en production).

Installer un service sous GNU/Linux et gestions des services (systemd)

Alors, ce qu'on entend par /service/, ici, et qu'on appelle aussi, dans le cas de systemd, une /unité/ systemd, c'est un élément de configuration déterminant les paramètres de lancement de notre applicatif, et permettant de le lancer automatiquement au démarrage, de le lancer manuellement, de le stopper, de le relancer, ou de l'obliger à recharger sa configuration après modification.

Sous Debian GNU/Linux, comme sous beaucoup d'autres distributions Linux (mais aucun UNIX, et pas certaines distributions GNU/Linux comme Devuan, Alpine, Void Linux ou Gentoo), on utilise systemd et donc l'utilitaire systemctl pour la gestion de ces services.

Les commandes de base de systemctl sont:

Lancer un service:

$ sudo systemctl start nom_du_service

Stopper un service:

$ sudo systemctl stop nom_du_service

Recharger la configuration d'un service sans le relancer (pratique pour ne pas couper le service):

$ sudo systemctl reload nom_du_service

Obtenir des informations sur le statut d'un service:

$ sudo systemctl status nom_du_service

Activer un service pour qu'il se lance automatiquement au démarrage de la machine:

$ sudo systemctl enable nom_du_service

Inversement, si on veut empêcher un logiciel de se lancer au démarrage:

$ sudo systemctl disable nom_du_service

Bien sûr, on a beaucoup d'autres commandes (masquage d'unités systemd, etc) disponibles mais elles sortent du sujet de ce cours. Cependant je vous invite fortement à consulter la documentation de systemd, notamment concernant:

Configuration d'Apache2

Installation

On ne peut plus simple:

$ sudo apt install apache2

Une fois installé, on peut vérifier le bon fonctionnement d'apache2 en se connectant à http://ip_de_notre_VM_LAMP

Vous remarquerez que par défaut, Debian active notre service et le lance. Ce qui n'est pas forcément une bonne idée, un service non configuré pouvant présenter une faille de sécurité.

On va donc, pour le moment, stopper notre serveur apache2 - en production, s'il n'était pas utilisé, on le désactiverait.

# on vérifie s'il tourne ou pas:
$ sudo systemctl status apache2
# on le stoppe:
$ sudo systemctl stop apache2
# on checke qu'il est bien stoppé:
$ sudo systemctl status apache2

Les fichiers de configuration

L'ensemble des fichiers de configuration d'apache2 se trouve dans les répertoires suivants:

# éléments de configuration générale:
/etc/apache2
# configurations disponibles:
/etc/apache2/conf-available
# configurations activées:
/etc/apache2/conf-enabled
# modules disponibles:
/etc/apache2/mods-available
# modules activés:
/etc/apache2/mods-enabled
# vhosts (sites web) disponibles:
/etc/apache2/sites-available/
# vhosts actifs:
/etc/apache2/sites-enabled/

Regardons maintenant les fichiers de configuration dans le répertoire de base:

$ ls /etc/apache2
apache2.conf  conf-available  conf-enabled  envvars  magic  mods-available  mods-enabled  ports.conf  sites-available  sites-enabled

Les fichiers qui nous intéressent sont:

le fichier "magic" concerne un module supplémentaire pour les types MIME et ne nous intéresse pas dans le cadre de ce cours 😃

Regardons maintenant le contenu du répertoire sites-enabled:

$ ls -al /etc/apache2/sites-enabled
total 8
drwxr-xr-x 2 root root 4096 sept. 16 14:21 .
drwxr-xr-x 8 root root 4096 sept. 16 14:21 ..
lrwxrwxrwx 1 root root   35 sept. 16 14:20 000-default.conf -> ../sites-available/000-default.conf

Ici, on voit que le fichier 000-default.conf (qui contient la configuration du site web par défaut d'apache2) est un lien symbolique vers:

/etc/apache2/sites-available/000-default.conf

Qu'est ce qu'il se passe si je désactive ce site. Tout d'abord, pour désactiver un site web avec apache2, on a deux solutions:

Comme on aime bien faire les choses proprement:

# on va relancer apache2 ;)
$ sudo systemctl start apache2
# on désactive la config
$ sudo a2dissite 000-default
# on reload la config d'apache2
$ sudo systemctl reload apache2

à l'inverse, pour réactiver notre site web par défaut, on utilisera la commande a2ensite (ou on créera un lien symbolique manuellement):

$ sudo a2ensite 000-default
$ sudo systemctl reload apache2

De même, pour activer ou désactiver un élément de configuration:

$ sudo a2enconf nom_de_laconfig
$ sudo a2disconf nom_de_laconfig

Et pour activer ou désactiver un module apache2:

$ sudo a2enmod nom_du_module
$ sudo a2dismod nom_du_module

On va en profiter pour activer le module rewrite qui permet de réécrire des URLs, et dont nous allons avoir besoin pour notre installation de Wordpress:

$ sudo a2enmod rewrite

Fonctionnement

Dans notre cas (configuration simple), le seul fichier que nous modifierons sera le vhost de notre installation de Wordpress:

$ sudo nano /etc/apache2/sites-available/wordpress.conf
<VirtualHost *:80>
  ServerAdmin yolo@yolopetlaprod.com
  DocumentRoot /var/www/wordpress
  ServerName _

  <Directory /var/www/wordpress>
     Options FollowSymlinks
     AllowOverride All
     Require all granted
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/wordpress.error.log
  CustomLog ${APACHE_LOG_DIR}/wordpress.access.log combined

</VirtualHost>
#on sauvegarde et on quitte :)

Configuration de MariaDB/MySQL

Bien évidemment, pour notre installation de Wordpress, on va avoir besoin d'une base de données, qui stockera nos articles, nos rubriques, nos paramètres utilisateurs, les paramètres de nos plugins, etc... On va utiliser une des plus connues, le /fork/ de MySQL nommé MariaDB.

Installation

L'installation est triviale:

$ sudo apt install mariadb-server mariadb-client

Les fichiers de configuration

Les fichiers de configuration de MariaDB se trouvent dans:

/etc/mysql

Ses fichiers de données se trouvent eux dans:

/var/lib/mysql

Le fichier de configuration principal de MariaDB se trouve dans:

/etc/mysql/mariadb.conf.d/50-server.cnf

On va l'ouvrir avec notre éditeur préféré:

# sans sudo, on ne veut rien modifier pour le moment
$ nano /etc/mysql/mariadb.conf.d/50-server.cnf

Les paramètres importants, actuellement (on ne va pas rentrer dans le /tuning/ des performances de MariaDB, il faudrait un module à lui tout seul pour ça), sont:

Fonctionnement

On va d'abord se connecter (en root, c'est mal) à notre base de données pour créer une base de données que Wordpress pourra utiliser:

$ sudo mysql
# on liste les databases:
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.000 sec)

#on va maintenant créer notre base de données Wordpress
MariaDB [(none)]> create database wordpress;
# Puis donner les droits à l'utilisateur wordpress
# qu'on va créer dans la foulée:
MariaDB [(none)]> grant all privileges on wordpress.* to \
    'wordpress'@'localhost' identified by 'supermotdepasse';
MariaDB [(none)]> quit;

On va maintenant vérifier qu'on peut se connecter en local à la base wordpress avec notre utilisateur wordpress et son supermotdepasse:

$ mysql -uwordpress -p wordpress
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 52
Server version: 10.3.25-MariaDB-0+deb10u1 Debian 10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [wordpress]> show tables;
Empty set (0.001 sec)

MariaDB [wordpress]> quit;

Configuration de PHP

Installation

Ici, on va avoir besoin, pour notre installation de Wordpress, d'installer les bibliothèques PHP requises, ainsi que le module apache2 PHP8.2, ce qui se fait facilement:

$ sudo apt install apache2 php8.2 libapache2-mod-php8.2 \
   php8.2-common php8.2-mbstring php8.2-xmlrpc \
   php8.2-soap php8.2-gd php8.2-xml php8.2-intl \
   php8.2-mysql php8.2-cli php8.2-ldap php8.2-zip \
   php8.2-curl

PHP-FPM

On pourrait utiliser PHP-FPM (asynchrone) au lieu de libapache2-mod-php7.3 afin d'obtenir de meilleures performances. Je ne vais pas trop m'étendre là-dessus car ce n'est pas trop l'objectif du cours.

Configuration de Wordpress

Enfin, on va pouvoir configurer Wordpress! On va tout d'abord récupérer la dernière version de Wordpress sur notre VM LAMP:

$ wget -c https://wordpress.org/latest.tar.gz

On va décompresser notre archive, ce qui va nous permettre de faire un mini tuto sur tar. En effet notre archive est compressée en tar.gz, c'est à dire un fichier d'archive tar compressé en gzip. Un fichier d'archive tar possède un avantage: il permet de conserver les droits, permissions, propriétaires, liens symboliques de ce qui est archivé. Ainsi, ces différents paramètres seront rétablis au décompactage de l'archive tar.

Pour décompresser un fichier tar.gz:

$ tar xvzf fichier.tar.gz

Pour créer une archive à partir d'un répertoire:

$ tar cvzf archive.tar.gz repertoire/

Dans notre cas:

# on veut décompresser latest.tar.gz:
$ tar xvzf latest.tar.gz

On va ensuite vouloir déplacer le répertoire wordpress à l'endroit pointé dans notre vhost, dans mon cas:

$ sudo mv wordpress /var/www/
# je veux aussi lui donner les bons droits, 
# le répertoire et son contenu:
$ sudo chown -R www-data:www-data /var/www/wordpress

Il nous reste juste à lancer apache2 pour terminer la configuration de Wordpress depuis un confortable navigateur Web:

$ sudo systemctl start apache2

Puis, se connecter à l'adresse IP de notre VM LAMP depuis notre VM Desktop en utilisant Firefox. Et ne toucher à rien avant que j'y sois aussi 😃

TODO TP: Montons un site autre que Wordpress!