Paillasse/portail/public/js/contenus-2.js

91 lines
18 KiB
JavaScript
Raw Normal View History

// Cours complets · lot 2 : tubes, réseaux (OSI), SQL
window.CONTENUS_PRO = (window.CONTENUS_PRO || []).concat([
{ id: 'tubes', match: /redirection|tubes|grep|filtres|sed|awk/i,
titre: 'Redirections, tubes et filtres de texte', duree: '4 h (CM 1 h · TD 1 h 30 · TP 1 h 30)', niveau: 'BTS SIO · BTS CIEL · BUT R&T · TSSR',
prerequis: ['Le terminal Linux'],
competences: ['BTS SIO · Bloc 1 · Exploiter des journaux', 'BUT R&T · Compétence « Administrer » · automatiser'],
intro: 'Un administrateur passe beaucoup de temps à lire des journaux de plusieurs milliers de lignes. Plutôt que de les lire à l’œil, on enchaîne de petites commandes spécialisées. C’est la philosophie Unix : chaque outil fait une chose, et bien.',
cm: [
{ t: 'Les trois flux standard', d: '10 min', html: 'Chaque processus dispose de trois flux : <b>stdin (0)</b> l’entrée, <b>stdout (1)</b> la sortie normale, <b>stderr (2)</b> les erreurs. Les séparer permet de garder les résultats propres et d’isoler les erreurs.' },
{ t: 'Rediriger', d: '15 min', html: 'On envoie un flux vers un fichier ou on lit un fichier comme entrée.', table: [['Opérateur', 'Effet'], ['>', 'stdout vers un fichier (écrase)'], ['>>', 'stdout ajouté à la fin'], ['2>', 'stderr vers un fichier'], ['&> ou > f 2>&1', 'les deux flux dans le même fichier'], ['<', 'le fichier devient stdin'], ['> /dev/null', 'jeter la sortie']], exemple: 'find / -name "*.conf" > resultats.txt 2> /dev/null' },
{ t: 'Le tube', d: '10 min', html: 'Le tube <code>|</code> branche la sortie d’une commande sur l’entrée de la suivante, sans fichier intermédiaire. On construit une chaîne de traitement de gauche à droite.', exemple: 'cat /var/log/auth.log | grep "Failed password" | wc -l' },
{ t: 'La boîte à outils', d: '20 min', html: '', table: [['Commande', 'Rôle', 'Exemple'], ['grep', 'garder les lignes qui correspondent', 'grep -i erreur syslog'], ['cut', 'extraire des colonnes', 'cut -d: -f1,7 /etc/passwd'], ['sort', 'trier', 'sort -n, sort -rn'], ['uniq -c', 'compter les lignes identiques consécutives', 'sort | uniq -c'], ['wc -l', 'compter les lignes', ''], ['head / tail', 'début / fin', 'tail -f pour suivre en direct'], ['awk', 'traiter par colonnes', "awk '{print $1}'"], ['sed', 'remplacer', "sed 's/http/https/g'"]], attention: 'uniq ne regroupe que les lignes consécutives : il faut presque toujours trier avant avec sort.' },
{ t: 'Un cas réel : repérer une attaque SSH', d: '15 min', html: 'Objectif : trouver les adresses IP qui ont le plus échoué à se connecter.', exemple: "grep 'Failed password' /var/log/auth.log \\\n | awk '{print $(NF-3)}' \\\n | sort | uniq -c | sort -rn | head -5\n\n 412 203.0.113.42\n 87 198.51.100.7\n 12 192.0.2.19" }],
synthese: ['> écrase, >> ajoute, 2> capture les erreurs', '| enchaîne les traitements', 'sort | uniq -c | sort -rn : le classement le plus utile de l’administrateur', 'tail -f pour suivre un journal en direct'],
qcm: [
['Où va l’erreur de ls /inexistant > sortie.txt ?', ['Dans sortie.txt', 'À l’écran', 'Nulle part', 'Dans /dev/null'], 1, '> ne redirige que stdout ; stderr s’affiche.'],
['Comment jeter à la fois la sortie et les erreurs ?', ['> /dev/null', '2> /dev/null', '&> /dev/null', '| null'], 2, '&> redirige les deux flux.'],
['Que fait cut -d: -f1 /etc/passwd ?', ['Supprime la ligne 1', 'Affiche la 1re colonne séparée par :', 'Compte les lignes', 'Trie'], 1, '-d = séparateur, -f = champ.'],
['Pourquoi trier avant uniq -c ?', ['Pour aller plus vite', 'uniq ne regroupe que les lignes consécutives', 'Ce n’est pas utile', 'Pour supprimer les doublons'], 1, 'Sans tri, les doublons dispersés ne sont pas regroupés.'],
['Quelle commande suit un journal en temps réel ?', ['head -f', 'tail -f', 'cat -f', 'less -r'], 1, 'tail -f affiche les nouvelles lignes au fil de l’eau.'],
['Que fait sed "s/a/b/g" f.txt ?', ['Supprime a', 'Remplace tous les a par b à l’affichage', 'Modifie le fichier sur disque', 'Compte les a'], 1, 'Sans -i, sed ne modifie pas le fichier.']],
td: [
{ n: 'Échauffement', c: 'Enregistrer la liste de /etc dans liste.txt, puis y ajouter celle de /var.', r: 'ls /etc > liste.txt && ls /var >> liste.txt' },
{ n: 'Application', c: 'Afficher les comptes qui utilisent /bin/bash, avec seulement leur nom.', r: 'grep "/bin/bash$" /etc/passwd | cut -d: -f1' },
{ n: 'Application', c: 'Dans acces.log (format Apache), classer les 10 pages les plus demandées.', r: "awk '{print $7}' acces.log | sort | uniq -c | sort -rn | head -10" },
{ n: 'Approfondissement', c: 'Compter les erreurs 404 par heure dans acces.log.', r: "awk '$9 == 404 {print substr($4, 14, 2)}' acces.log | sort | uniq -c" }],
tp: { type: 'IDE Bash', url: 'apercu-ide.html?ex=bash-tp', desc: 'Scripts Bash sur de vrais journaux, vérifiés par des tests.', etapes: ['Compter les connexions échouées', 'Classer les IP suspectes', 'Écrire un rapport dans un fichier', 'Bonus : alerte si plus de 100 échecs'] },
plusLoin: [['Le jeu OverTheWire Bandit (niveaux 10 à 20)', 'https://overthewire.org/wargames/bandit/'], ['Défis « Linux Shell » sur HackerRank', 'https://www.hackerrank.com/domains/shell']] },
{ id: 'osi', match: /OSI|TCP\/IP|modèle en couches|encapsulation|Internet : IP/i,
titre: 'Modèles OSI et TCP/IP, encapsulation', duree: '4 h (CM 1 h 30 · TD 1 h · TP 1 h 30)', niveau: 'SNT · BTS SIO · BTS CIEL · BUT R&T S1',
prerequis: ['Binaire et hexadécimal'],
competences: ['BTS SIO · Bloc 1 · Exploiter les éléments d’un réseau', 'BTS CIEL · C03 · Analyser un réseau', 'BUT R&T · Compétence « Connecter »'],
intro: 'Quand un réseau tombe en panne, l’administrateur raisonne couche par couche : le câble est-il branché ? le switch voit-il la carte ? l’adresse IP est-elle bonne ? le service écoute-t-il ? Le modèle en couches est d’abord une méthode de diagnostic.',
cm: [
{ t: 'Pourquoi un modèle en couches', d: '10 min', html: 'Communiquer suppose de régler beaucoup de problèmes : transmettre des bits, les adresser, les acheminer, les remettre en ordre, les présenter à l’application. Chaque couche règle un problème et offre un service à la couche du dessus, sans connaître le détail des autres.' },
{ t: 'Les 7 couches OSI', d: '20 min', html: '', table: [['N°', 'Couche', 'Rôle', 'Unité', 'Exemples'], ['7', 'Application', 'service rendu à l’utilisateur', 'données', 'HTTP, DNS, SSH, SMTP'], ['6', 'Présentation', 'format, chiffrement', 'données', 'TLS, UTF-8'], ['5', 'Session', 'dialogue', 'données', 'RPC'], ['4', 'Transport', 'bout en bout, ports', 'segment', 'TCP, UDP'], ['3', 'Réseau', 'adressage logique, routage', 'paquet', 'IP, ICMP'], ['2', 'Liaison', 'accès au support, MAC', 'trame', 'Ethernet, Wi-Fi'], ['1', 'Physique', 'signal', 'bit', 'RJ45, fibre, radio']] },
{ t: 'Le modèle TCP/IP', d: '10 min', html: 'Le modèle réellement implémenté compte 4 couches : <b>Accès réseau</b> (OSI 1-2), <b>Internet</b> (3), <b>Transport</b> (4), <b>Application</b> (5-7).' },
{ t: 'L’encapsulation', d: '20 min', html: 'À l’émission, chaque couche ajoute son en-tête aux données reçues de la couche supérieure. À la réception, chaque couche lit et retire le sien.', exemple: '[ HTTP : GET /index.html ]\n[ TCP : port src 51234 → dst 443 ][ HTTP … ]\n[ IP : 192.168.10.65 → 93.184.216.34 ][ TCP … ][ HTTP … ]\n[ Eth : MAC src → MAC passerelle ][ IP … ][ TCP … ][ HTTP … ][ FCS ]' },
{ t: 'Les équipements par couche', d: '10 min', html: '<b>Hub</b> : couche 1, répète le signal. <b>Switch</b> : couche 2, commute selon les adresses MAC. <b>Routeur</b> : couche 3, achemine selon les adresses IP. <b>Pare-feu</b> : couches 3-4, filtre IP et ports (voire 7 pour un pare-feu applicatif).' },
{ t: 'Diagnostiquer couche par couche', d: '15 min', html: 'On part du bas : <code>ip link</code> (lien actif ?), <code>ip addr</code> (adresse ?), <code>ping</code> la passerelle (couche 3), <code>ss -tlnp</code> (le service écoute-t-il ?), <code>curl</code> (l’application répond-elle ?).', attention: 'Un ping qui échoue ne prouve pas que la machine est éteinte : ICMP est souvent filtré par les pare-feux.' }],
synthese: ['OSI 7 couches, TCP/IP 4 couches', 'bit → trame → paquet → segment → données', 'MAC couche 2, IP couche 3, port couche 4', 'On diagnostique toujours de bas en haut'],
qcm: [
['À quelle couche travaille un switch classique ?', ['1', '2', '3', '4'], 1, 'Il commute selon les adresses MAC.'],
['Quelle est l’unité de la couche Transport ?', ['Trame', 'Paquet', 'Segment', 'Bit'], 2, 'TCP et UDP manipulent des segments (datagrammes pour UDP).'],
['Le port 443 est une information de couche :', ['2', '3', '4', '7'], 2, 'Les ports sont gérés par la couche Transport.'],
['Quel protocole n’est PAS de couche application ?', ['DNS', 'SSH', 'ICMP', 'SMTP'], 2, 'ICMP accompagne IP, couche 3.'],
['Dans une trame Ethernet, l’adresse MAC de destination est celle :', ['du serveur web distant', 'de la passerelle ou du voisin direct', 'du DNS', 'du switch'], 1, 'La MAC change à chaque saut, l’IP de destination reste la même.'],
['Combien de couches compte le modèle TCP/IP ?', ['3', '4', '5', '7'], 1, 'Accès réseau, Internet, Transport, Application.'],
['Un poste a une IP mais n’accède pas à Internet. Première vérification ?', ['Réinstaller', 'ping la passerelle', 'Changer le câble', 'Vider le cache DNS'], 1, 'On teste la couche 3 vers la passerelle avant d’aller plus haut.']],
td: [
{ n: 'Échauffement', c: 'Classer par couche OSI : HTTP, IP, switch, TCP, câble RJ45, routeur, TLS, Wi-Fi.', r: '7 · 3 · 2 · 4 · 1 · 3 · 6 · 1-2' },
{ n: 'Application', c: 'Dessiner l’encapsulation d’une requête DNS du poste 192.168.1.20 vers 1.1.1.1.', r: 'DNS (requête) → UDP (port src aléatoire → 53) → IP (192.168.1.20 → 1.1.1.1) → Ethernet (MAC poste → MAC box)' },
{ n: 'Application', c: 'Un utilisateur ne peut pas ouvrir intranet.lycee.fr. Proposer une démarche de diagnostic en 5 commandes, de bas en haut.', r: 'ip link · ip addr · ping passerelle · nslookup intranet.lycee.fr · curl -I https://intranet.lycee.fr' },
{ n: 'Approfondissement', c: 'Expliquer pourquoi l’adresse MAC de destination change à chaque routeur traversé alors que l’adresse IP de destination reste la même.', r: 'La couche 2 ne sert qu’à atteindre le voisin direct ; chaque routeur ré-encapsule dans une nouvelle trame. La couche 3 porte l’adresse finale.' }],
tp: { type: 'Lab VM', url: 'apercu-labs.html', desc: 'Capturer du trafic avec tcpdump et reconnaître chaque en-tête.', etapes: ['Lancer tcpdump sur eth0', 'Faire un curl vers un site', 'Identifier Ethernet, IP, TCP, HTTP', 'Comparer avec une requête DNS en UDP'] },
plusLoin: [['Cisco Networking Academy · cours gratuits', 'https://www.netacad.com/'], ['RFC 1122 (Requirements for Internet Hosts)', 'https://www.rfc-editor.org/rfc/rfc1122']] },
{ id: 'sql', match: /SQL|SELECT|requête|bases de données relationnelles|jointure/i,
titre: 'SQL : interroger une base de données relationnelle', duree: '6 h (CM 2 h · TD 2 h · TP 2 h)', niveau: 'NSI Terminale · BTS SIO SLAM · BUT Informatique · MIAGE',
prerequis: ['Notion de tableau de données'],
competences: ['NSI Tle · Bases de données : langage SQL', 'BTS SIO SLAM · Bloc 2 · Concevoir et exploiter une base de données', 'BUT Info · Compétence « Gérer des données »'],
intro: 'Presque toutes les applications stockent leurs données dans une base relationnelle : un ENT, un site marchand, Syllabus elle-même. SQL est le langage standard pour les interroger. Il se lit presque comme une phrase.',
cm: [
{ t: 'Le modèle relationnel', d: '20 min', html: 'Une base est un ensemble de <b>tables</b> (relations). Chaque ligne est un enregistrement, chaque colonne un attribut typé. La <b>clé primaire</b> identifie une ligne de façon unique ; une <b>clé étrangère</b> référence la clé primaire d’une autre table.', table: [['eleves', 'id (PK)', 'nom', 'prenom', 'classe_id (FK)'], ['', '1', 'Martin', 'Léa', '3'], ['', '2', 'Kaci', 'Inès', '3']] },
{ t: 'Sélectionner : SELECT … FROM', d: '15 min', html: 'On choisit les colonnes, puis la table. <code>*</code> sélectionne toutes les colonnes, <code>DISTINCT</code> supprime les doublons, <code>AS</code> renomme.', exemple: 'SELECT nom, prenom FROM eleves;\nSELECT DISTINCT ville FROM eleves;\nSELECT nom AS "Nom de famille" FROM eleves;' },
{ t: 'Filtrer et trier', d: '20 min', html: '<code>WHERE</code> filtre avec =, <>, <, >, BETWEEN, IN, LIKE (% = n’importe quelle suite), IS NULL, combinés par AND, OR, NOT. <code>ORDER BY</code> trie (ASC, DESC), <code>LIMIT</code> restreint.', exemple: "SELECT nom, moyenne FROM eleves\nWHERE classe_id = 3 AND moyenne >= 10\nORDER BY moyenne DESC\nLIMIT 5;" },
{ t: 'Agréger : COUNT, AVG, GROUP BY', d: '20 min', html: 'Les fonctions d’agrégat calculent sur un ensemble de lignes : COUNT, SUM, AVG, MIN, MAX. <code>GROUP BY</code> forme des groupes, <code>HAVING</code> filtre les groupes (WHERE filtre les lignes avant).', exemple: 'SELECT classe_id, COUNT(*) AS effectif, AVG(moyenne) AS moy\nFROM eleves\nGROUP BY classe_id\nHAVING COUNT(*) > 20;', attention: 'Toute colonne du SELECT qui n’est pas agrégée doit figurer dans le GROUP BY.' },
{ t: 'Joindre des tables', d: '25 min', html: 'La jointure relie deux tables par leurs clés. <b>INNER JOIN</b> garde les lignes qui ont une correspondance des deux côtés ; <b>LEFT JOIN</b> garde toutes les lignes de gauche, avec NULL s’il n’y a pas de correspondance.', exemple: 'SELECT e.nom, c.libelle\nFROM eleves e\nJOIN classes c ON e.classe_id = c.id;\n\n-- Classes sans aucun élève :\nSELECT c.libelle FROM classes c\nLEFT JOIN eleves e ON e.classe_id = c.id\nWHERE e.id IS NULL;' },
{ t: 'Modifier les données', d: '15 min', html: '<code>INSERT INTO</code> ajoute, <code>UPDATE … SET … WHERE</code> modifie, <code>DELETE FROM … WHERE</code> supprime.', attention: 'Un UPDATE ou un DELETE sans WHERE touche toutes les lignes. On teste toujours d’abord le WHERE avec un SELECT.' },
{ t: 'Sécurité : l’injection SQL', d: '10 min', html: 'Construire une requête en collant du texte saisi par l’utilisateur permet de détourner la requête (<code>\' OR 1=1 --</code>). On utilise toujours des <b>requêtes préparées</b> avec paramètres.' }],
synthese: ['SELECT colonnes FROM table WHERE condition ORDER BY tri', 'WHERE filtre les lignes, HAVING filtre les groupes', 'JOIN … ON relie clé étrangère et clé primaire', 'Jamais de DELETE ni d’UPDATE sans WHERE', 'Requêtes préparées contre l’injection'],
qcm: [
['Quelle clause filtre les groupes après un GROUP BY ?', ['WHERE', 'HAVING', 'ORDER BY', 'LIMIT'], 1, 'HAVING s’applique aux groupes.'],
['Que renvoie SELECT COUNT(*) FROM eleves WHERE moyenne IS NULL ?', ['Les élèves sans moyenne', 'Le nombre d’élèves sans moyenne', 'Une erreur', '0 toujours'], 1, 'COUNT compte les lignes retenues.'],
['Quelle jointure garde les classes sans élève ?', ['INNER JOIN', 'LEFT JOIN depuis classes', 'CROSS JOIN', 'Aucune'], 1, 'LEFT JOIN conserve toutes les lignes de la table de gauche.'],
['LIKE "Ma%" correspond à :', ['Ma exactement', 'tout texte commençant par Ma', 'tout texte finissant par Ma', 'tout texte contenant %'], 1, '% remplace n’importe quelle suite de caractères.'],
['Que se passe-t-il avec DELETE FROM eleves; ?', ['Rien', 'Toutes les lignes sont supprimées', 'La table est supprimée', 'Erreur de syntaxe'], 1, 'Sans WHERE, toutes les lignes partent. La table reste.'],
['Quel est le rôle d’une clé étrangère ?', ['Chiffrer', 'Référencer une ligne d’une autre table', 'Accélérer les tris', 'Rendre une colonne unique'], 1, 'Elle garantit l’intégrité référentielle.'],
['Comment se protéger de l’injection SQL ?', ['Masquer les erreurs', 'Requêtes préparées', 'Mettre des guillemets', 'Utiliser HTTPS'], 1, 'Les paramètres ne sont jamais interprétés comme du SQL.'],
['Classer les élèves du meilleur au moins bon :', ['ORDER BY moyenne', 'ORDER BY moyenne DESC', 'SORT BY moyenne', 'GROUP BY moyenne'], 1, 'DESC = décroissant.']],
td: [
{ n: 'Échauffement', c: 'Afficher nom et prénom des élèves de la classe 3, triés par nom.', r: 'SELECT nom, prenom FROM eleves WHERE classe_id = 3 ORDER BY nom;' },
{ n: 'Application', c: 'Afficher l’effectif et la moyenne de chaque classe, avec son libellé.', r: 'SELECT c.libelle, COUNT(e.id), AVG(e.moyenne)\nFROM classes c LEFT JOIN eleves e ON e.classe_id = c.id\nGROUP BY c.libelle;' },
{ n: 'Application', c: 'Lister les élèves qui n’ont rendu aucun devoir (tables eleves, rendus).', r: 'SELECT e.nom FROM eleves e\nLEFT JOIN rendus r ON r.eleve_id = e.id\nWHERE r.id IS NULL;' },
{ n: 'Approfondissement', c: 'Afficher les classes dont la moyenne est supérieure à la moyenne générale.', r: 'SELECT classe_id, AVG(moyenne) FROM eleves GROUP BY classe_id\nHAVING AVG(moyenne) > (SELECT AVG(moyenne) FROM eleves);' },
{ n: 'Approfondissement', c: 'Réécrire en requête préparée (PHP PDO) : "SELECT * FROM users WHERE login = \'" . $login . "\'"', r: '$st = $pdo->prepare("SELECT * FROM users WHERE login = ?");\n$st->execute([$login]);' }],
tp: { type: 'IDE SQL', url: 'apercu-ide.html?ex=sql-select', desc: 'Une base SQLite dans le navigateur, requêtes vérifiées automatiquement.', etapes: ['Explorer les tables', '8 requêtes SELECT progressives', '3 jointures', '2 requêtes d’agrégat', 'Défi : le palmarès par classe'] },
plusLoin: [['SQLBolt · exercices interactifs', 'https://sqlbolt.com/'], ['Défis SQL sur HackerRank', 'https://www.hackerrank.com/domains/sql'], ['DataCamp · Introduction to SQL', 'https://www.datacamp.com/courses/introduction-to-sql']] }
]);