Quand JavaScript sort du navigateur
\n\nLa plupart des développeurs perçoivent JavaScript comme un langage pour « animer » des pages web. Mais si je vous disais qu'avec JavaScript, vous pouvez écrire des scripts pour contrôler le système d'exploitation, travailler avec le système de fichiers à bas niveau et même créer des démons réseau ? Cela semble irréel ? Pourtant, c'est bien réel. Grâce à des environnements d'exécution comme Node.js et Deno, JavaScript pour la programmation système est devenu non seulement possible, mais aussi un outil parfaitement efficace. Dans cet article, nous analyserons des exemples de code concrets et verrons comment JS gère des tâches autrefois réservées à C, Rust ou Python.
\n\nPourquoi JavaScript ? Avantages et pièges à éviter
\n\nAvant de plonger dans le code, faisons un état des lieux honnête. La programmation système avec Node.js a ses forces et ses faiblesses.
\n\nAvantages :
\n- \n
- Stack technologique unifié — si vous êtes développeur front-end, pas besoin d'apprendre un nouveau langage pour écrire des utilitaires en ligne de commande. \n
- Communauté immense — npm propose des milliers de packages pour interagir avec le système. \n
- Asynchrone par défaut — les entrées-sorties non bloquantes sont idéales pour le réseau et les fichiers. \n
- Prototypage rapide — un script JS s'écrit en quelques minutes. \n
Inconvénients :
\n- \n
- Performances — JS est plus lent que C ou Rust pour les tâches computationnelles. \n
- Accès matériel limité — pas d'accès direct à la mémoire ou aux ports d'entrée-sortie (bien qu'il existe des solutions de contournement). \n
- Consommation mémoire — V8 n'est pas le moteur le plus léger. \n
Néanmoins, pour 80 % des tâches d'administration système et d'automatisation, JavaScript pour la programmation système est parfaitement adapté. Passons à la pratique.
\n\nManipulation du système de fichiers : module fs
\n\nCommençons par les bases — la manipulation de fichiers avec JavaScript. Le module fs de Node.js propose des méthodes synchrones et asynchrones pour interagir avec le système de fichiers.
Lecture et écriture de fichiers (version asynchrone)
\n\nconst fs = require('fs').promises;\nconst path = require('path');\n\nasync function processLogFile(filePath) {\n try {\n // Lecture du fichier\n const data = await fs.readFile(filePath, 'utf-8');\n const lines = data.split('\\n');\n \n // Filtrage des lignes d'erreur uniquement\n const errors = lines.filter(line => line.includes('ERROR'));\n \n // Écriture du résultat\n const outputPath = path.join(__dirname, 'errors.log');\n await fs.writeFile(outputPath, errors.join('\\n'), 'utf-8');\n \n console.log(`Traitement de ${lines.length} lignes, ${errors.length} erreurs trouvées`);\n } catch (err) {\n console.error('Erreur lors du traitement du fichier :', err);\n }\n}\n\nprocessLogFile('/var/log/application.log');\n\nCe script est un exemple typique de script système en JavaScript. Il lit un gros fichier journal, filtre les données et écrit le résultat. La version asynchrone ne bloque pas la boucle d'événements, ce qui est crucial pour les applications serveur.
\n\nSurveillance des modifications du système de fichiers
\n\nL'une des fonctionnalités puissantes est la surveillance en temps réel des fichiers :
\n\nconst fs = require('fs');\n\nconst watcher = fs.watch('/etc/config', { recursive: true });\n\nwatcher.on('change', (eventType, filename) => {\n console.log(`Modification détectée : ${filename} (${eventType})`);\n \n // Rechargement automatique de la configuration\n if (filename.endsWith('.conf')) {\n const config = fs.readFileSync(`/etc/config/${filename}`, 'utf-8');\n console.log('Nouvelle configuration chargée');\n }\n});\n\nconsole.log('Surveillance des configurations démarrée');