RSS Julia Evans

Le site web personnel de Julia Evans est un trésor de contenu éclairé et captivant, principalement axé sur la technologie, l'ingénierie logicielle et l'apprentissage. Evans, une ingénieure logicielle renommée, utilise sa plateforme pour partager son vaste savoir-faire à travers des billets de blog détaillés, des illustrations captivantes et des anecdotes personnelles. Son style d'écriture est accessible et humoristique, rendant même les sujets techniques complexes compréhensibles pour un large public. Le site web propose des articles sur divers sujets, y compris les mécanismes internes de Linux, les langages de programmation et les techniques de débogage. La passion d'Evans pour la technologie et sa capacité à expliquer clairement les concepts complexes brillent à travers son travail, inspirant et éduquant les lecteurs. Que vous soyez un développeur expérimenté ou que vous venez de commencer votre parcours de codage, le site web de Julia Evans offre des perspectives précieuses et une vision rafraîchissante du monde de l'ingénierie logicielle.

Fil de notes

L'auteur a publié un nouveau zine intitulé "The Secret Rules of the Terminal" (Les règles secrètes du terminal) qui explique le fonctionnement du terminal et propose des conseils et astuces pour utiliser les programmes en ligne de commande. L'auteur utilise le terminal quotidiennement depuis 20 ans, mais avait encore de nombreuses incompréhensions sur son fonctionnement. Le terminal présente de nombreuses petites incohérences, comme parfois permettre l'utilisation des touches fléchées pour se déplacer et parfois non. Les "règles" du fonctionnement du terminal sont difficiles à comprendre car il est composé de nombreux logiciels différents. Le zine explique comment les quatre composantes du terminal (shell, émulateur de terminal, programmes et pilote TTY) s'articulent et présente les conventions fondamentales du fonctionnement du terminal. L'auteur a beaucoup appris en écrivant le zine, notamment comment configurer son shell et comprendre les codes d'échappement. Le zine est disponible à l'achat en version PDF ou imprimée, et un lot de 15 zines de l'auteur est également proposé. L'auteur a reçu l'aide de nombreuses personnes, dont un réviseur technique qui a écrit PuTTY et une personne qui comprend le fonctionnement interne du terminal. La version imprimée sera expédiée en août, et l'auteur doit attendre les commandes pour déterminer le nombre d'exemplaires à imprimer. Le zine est disponible pour 12 $, et l'auteur espère qu'il aidera les lecteurs à mieux comprendre et utiliser le terminal.
"Le tamponnage est courant dans les programmes de terminal pour améliorer les performances en regroupant la sortie jusqu'à ce qu'un certain seuil de taille soit atteint. Cela peut causer des problèmes lorsque les données sont ajoutées lentement à un tube, car les programmes peuvent tamponner leur sortie et jamais l'écrire.Grep et des programmes similaires utilisent par défaut le tamponnage par blocs lors de l'écriture dans des tubes, mais utilisent le tamponnage par lignes lors de l'écriture dans les terminaux, ce qui explique pourquoi la commande "tail -f /some/log/file | grep thing1 | grep thing2" peut ne pas afficher de sortie.Plusieurs commandes tamponnent leur sortie, y compris grep, sed, awk, tcpdump et jq, tandis que les commandes comme tail, cat et tee ne le font pas.Les langages de programmation comme C, Python, Ruby et Perl peuvent également tamponner la sortie, avec diverses méthodes pour désactiver le tamponnage.Lorsque Ctrl-C est pressé sur un tube, le buffer de sortie du programme peut être perdu, car le signal est reçu avant que le buffer ne puisse être vidé.Le tamponnage se produit également lors de la redirection vers un fichier, mais il se comporte généralement comme attendu, avec le contenu du buffer étant écrit avant que le programme ne se termine.Pour éviter le tamponnage, on peut exécuter un programme qui se termine rapidement, utiliser le drapeau "--line-buffered" avec grep, réécrire la commande en utilisant awk, utiliser stdbuf, ou utiliser unbuffer pour forcer le programme à se comporter comme s'il écrivait dans un terminal.La solution idéale dépend de la situation spécifique, avec unbuffer étant un choix fiable pour son comportement cohérent.Bien que le tamponnage ne soit généralement pas un problème courant, il peut survenir lorsque les données sont ajoutées lentement à un tube. Une variable d'environnement pour désactiver le tamponnage pourrait être utile, mais sa conception et sa mise en œuvre présentent des défis."
L'auteur explore le concept de codes de contrôle dans le terminal, tels que Ctrl-A, Ctrl-C et Ctrl-W, et leur fonctionnement. Il existe 33 caractères de contrôle ASCII, qui peuvent être catégorisés en codes gérés par le pilote de terminal du système d'exploitation, codes correspondant à des pressions de touches littérales et codes utilisés par readline. L'auteur note qu'il n'y a pas de structure réelle pour déterminer quels codes sont dans quelle catégorie, car ils ont évolué de manière organique. Il n'y a que 33 codes de contrôle, ce qui signifie que si vous voulez utiliser Ctrl-1 comme raccourci clavier, cela n'a pas de sens, car c'est la même chose que de presser 1. L'auteur note également que Ctrl+Maj+C n'est pas un code de contrôle et que son comportement dépend de l'émulateur de terminal. Les noms officiels ASCII pour les codes de contrôle ne sont pas très utiles, car ils ont été initialement définis pour les machines à télégraphe et ont depuis été réaffectés. L'auteur trouve difficile d'utiliser Ctrl-M et Ctrl-I comme raccourcis clavier, car ils sont équivalents à Entrée et Tabulation, respectivement. L'auteur fournit un script Python pour identifier quels codes de contrôle sont envoyés lors de la pression de différentes combinaisons de touches. L'auteur note que certains codes de contrôle, tels que Ctrl-W et Ctrl-U, peuvent être gérés différemment en fonction de si le terminal est en mode canonique ou non canonique. Enfin, l'auteur reconnaît qu'il y a de nombreux cas particuliers et conflits lorsqu'il s'agit de codes de contrôle, et que toutes ces informations ne sont pas nécessairement utiles en pratique.
L'auteur du billet de blog a décidé de mettre à niveau sa version de Hugo de 0.40 à 0.135, malgré le bon fonctionnement de l'ancienne version. Il a documenté les changements qu'il a dû effectuer pendant le processus de mise à niveau, notamment le remplacement des appels de modèle, la mise à jour des références de page et l'inversion du sens de « suivant » et « précédent » dans son thème. L'auteur a également dû mettre à jour ses fichiers Markdown pour qu'ils fonctionnent avec le nouveau moteur de rendu Goldmark, qui a remplacé l'ancien moteur de rendu Blackfriday. Cela impliquait de modifier la façon dont il écrivait Markdown, notamment en mélangeant HTML et Markdown, en utilisant des guillemets et en mettant en retrait les listes imbriquées. L'auteur a également dû configurer le moteur de rendu Goldmark pour désactiver la coloration syntaxique et utiliser l'ancienne méthode pour générer les ID d'en-tête. Il a écrit un script pour comparer la sortie des moteurs de rendu Blackfriday et Goldmark et l'a utilisé pour identifier et corriger les problèmes de ses fichiers Markdown. L'auteur note que le processus de mise à niveau a pris du temps et a présenté des difficultés, mais estime finalement que cela valait la peine d'avoir un moteur de rendu Markdown plus évolutif. Il mentionne également qu'il devra probablement effectuer des changements similaires lors de la mise à niveau de son autre site, wizardzines.com, qui utilise toujours une ancienne version de Hugo.
Jouer avec DNS est une plateforme d'apprentissage de la fonctionnalité DNS en créant et en éditant des enregistrements. La mise en œuvre originale du DNS avait des limitations, y compris des noms de domaine interdits avec des tirets, absence de support pour les enregistrements CNAME, et absence de types d'enregistrements SVCB et HTTPS.Pour résoudre ces problèmes, l'auteur a intégré PowerDNS, un serveur DNS open source avec une API HTTP, remplaçant la précédente mise en œuvre du DNS. Cela a présenté des défis pour intercepter les requêtes DNS et concevoir une API qui répondait aux besoins du frontend.Pour la gestion des erreurs, l'auteur a adapté les messages d'erreur pour les utilisateurs pour fournir des informations plus claires, en gérant les réponses d'erreur de l'API PowerDNS et en effectuant une validation d'entrée basique. SQLite a remplacé Postgres pour la gestion de la base de données en raison de kills OOM (Out of Memory) expérimentés avec Postgres.La bibliothèque Vue.js a été mise à jour vers la version 3, accompagnée d'une transition vers l'utilisation d'outils de validation de formulaire intégrés au navigateur et de la mise en œuvre d'un magasin d'état global pour la gestion frontend.Le projet a été divisé en phases pour une mise en œuvre gérable, y compris la mise à jour de Vue, la création d'un magasin d'état, la révision de l'API backend et l'intégration de PowerDNS. Le site web mis à jour a été publié et fonctionne bien, résolvant les problèmes DNS précédemment signalés par les utilisateurs.
L'auteur, un programmeur Go occasionnel, a rencontré un bug qui a révélé une méconception fondamentale de la manière dont les structs sont copiés pendant l'attribution en Go. Cette méconception provenait du fait que les structs sont copiés à l'attribution, et non référencés, ce qui a conduit à un comportement inattendu lors de la modification d'un struct après l'avoir attribué à une autre variable. L'auteur a été surpris par ce comportement, car son expérience avec d'autres langages l'avait amené à croire que les variables étaient généralement passées par référence. Cette erreur de conception a été encore compliquée par la compréhension de l'auteur sur le passage par valeur et le passage par référence dans les arguments de fonction, qu'il n'avait pas étendu aux attributions de variables. L'auteur a également découvert que les sous-tranches dans Go partagent le même tableau de base que la tranche originale, ce qui signifie que l'ajout à une sous-tranche peut modifier involontairement la tranche originale. En outre, l'auteur a acquis une clarté sur la différence entre les récepteurs de valeur et les récepteurs de pointeur dans les méthodes Go, comprenant que les récepteurs de pointeur sont nécessaires lorsque une méthode doit modifier le struct sur lequel elle est appelée. L'auteur a également loué la ressource "100 Go Mistakes" pour son format clair et concis, qui lui a permis d'identifier et d'apprendre rapidement des pièges courants en Go. Enfin, l'auteur a énuméré d'autres ressources Go précieuses, y compris "Go by Example", "go.dev/play" et des outils d'analyse statique comme "staticcheck" et "golangci-lint."
Le concept de 'branche actuelle' dans Git, bien qu'apparemment simple, présente une certaine ambiguïté lorsqu'il est examiné de près. Alors que le glossaire Git le définit comme le contenu du fichier .git/HEAD, d'autres interprétations existent, y compris la sortie de "git status", la dernière branche vérifiée et la invite de shell. Ces interprétations s'alignent souvent mais divergent dans des scénarios spécifiques comme les états de tête détachés, les balises vérifiées et les situations de rebase en cours. Par exemple, la vérification d'une balise entraîne le stockage de l'ID de commit dans .git/HEAD tandis que "git status" affiche le nom de la balise pour convenance utilisateur. De même, pendant un rebase, "git status" met en évidence l'état de rebase tandis que l'invite de shell peut indiquer la branche d'origine. Même "git init" introduit une nuance où la "branche actuelle" est automatiquement définie sans vérification explicite. Des complexités supplémentaires surgissent avec les dépôts nus où "git status" et "git checkout" sont inopérants. Ces incohérences mettent en évidence les limites de la définition rigide de "branche actuelle" et soulignent l'importance de la compréhension contextuelle. La définition de "branche actuelle" comme cible pour les nouveaux commits, bien qu'elle soit généralement vraie, faiblit pendant un rebase où le commit atterrit finalement sur la branche d'origine. L'idée de "branche actuelle" représentant le contexte pour les opérations Git a du mérite, mais des disparités existent, comme "git status" se comportant différemment dans les dépôts nus. En fin de compte, la compréhension des nuances de "branche actuelle" nécessite de reconnaître sa nature dépendante du contexte et de se fier à une combinaison d'indicateurs tels que .git/HEAD, la sortie de "git status" et la dernière action de vérification pour une compréhension exhaustive.
- Gestion des tirages : pull.ff only ou pull.rebase true pour éviter de créer des commits de fusion lorsque la branche en amont diverge. - Lisibilité des conflits de fusion : merge.conflictstyle zdiff3 améliore la visibilité des conflits de fusion en affichant le code original au milieu. - Modification de commit automatisée : rebase.autosquash true combine les commits fixup! avec leurs cibles pendant le rebase. - Empilage automatique : rebase.autostash true exécute git stash avant et après le rebase. - Automatisation de la poussée : push.default current ou push.default simple pousse la branche actuelle vers une branche distante correspondante ; push.autoSetupRemote true configure le suivi pour la première poussée. - Branche par défaut : init.defaultBranch main crée une branche main au lieu de master dans les nouveaux dépôts. - Amélioration des messages de commit : commit.verbose true affiche la différence de commit dans l'éditeur de message de commit. - Automatisation de la résolution des conflits : rerere.enabled true se souvient et automatise les résolutions de conflits de fusion. - Autocorrection : help.autocorrect 10 permet à Git d'exécuter des autocorrections après un délai spécifié. - Visualisation des différences : core.pager delta utilise un visualisateur de différences avec mise en évidence syntaxique ; diff.algorithm histogram améliore la visibilité de la réorganisation des fonctions. - Fichier gitignore global : core.excludesfile spécifie un fichier gitignore global. - Configurations Git séparées : includeIf permet des configurations différentes pour les dépôts personnels et professionnels. - Prévention de la corruption des données : transfer.fsckobjects et les paramètres associés détectent et préviennent la corruption des données. - Autres options notables : Ignorer les blames, tri des branches, paramètres de couleur, sélection de l'éditeur, nettoyage des commits, paramètres de base, outils de différence, paramètres de fusion, pousser les tags suivants, sécurité du rebase, format de date des logs.
L'auteur, initialement sceptique quant aux flocons Nix, a entrepris un voyage pour comprendre leur utilité, en tirant des parallèles avec les conteneurs Docker pour clarifier le concept. Alors qu'il reconnaissait la supériorité des flocons en matière de reproductibilité et de gestion des dépendances, l'auteur a cherché à les utiliser pour maintenir une liste centralisée des paquets système, recherchant des avantages dans la configuration du système et la désinstallation des logiciels. Au cours d'un processus d'essai et d'erreur, l'auteur a navigué les défis tels que les fichiers non suivis dans les dépôts Git, l'intégration de paquets non libres et la résolution des problèmes de chemins relatifs avec les dépendances des flocons. En utilisant 'nix develop' et 'buildEnv', l'auteur a réussi à créer un répertoire de liens symboliques représentant les paquets souhaités. Cependant, le processus n'a pas été sans obstacles, rencontrant une erreur liée aux hooks de construction qui a entravé le progrès. Malgré les difficultés, l'auteur est resté persévérant dans son exploration des flocons, cherchant une approche plus fluide et plus gérable pour son flux de travail de gestion des paquets Nix. L'auteur a trouvé les explications existantes des flocons difficiles à saisir, s'appuyant plutôt sur des analogies et des expériences pratiques pour développer sa compréhension. Bien que la première incursion de l'auteur dans les flocons ait présenté des défis, son engagement à maîtriser cet aspect de Nix met en évidence un désir d'expérience de gestion de paquets plus solide et plus efficace.
L'auteur, initialement méconnaissant git cherry-pick comme simple application d'un patch, explore réellement son fonctionnement, révélant un processus plus nuancé impliquant un "merge à trois volets". La méconception est apparue lors de la tentative de résolution des conflits de fusion en utilisant la méthode de patch, qui a échoué, contrairement au comportement attendu de git cherry-pick. Des recherches supplémentaires dans le code source de git ont révélé que cherry-pick utilise un merge à trois volets, un concept inconnu de l'auteur à l'époque. Cela a incité à explorer les merges à trois volets, qui, en substance, consistent à fusionner deux fichiers en les comparant à leur version originale (la base). Ce concept s'étend à l'application des patches dans git, où les versions du fichier avant et après le commit, ainsi que le fichier actuel, constituent les trois versions utilisées dans le merge. Cherry-pick, rebase et revert utilisent tous cette stratégie de merge à trois volets, se distinguant principalement par l'ordre et l'interprétation des versions de base et cible. L'auteur forge le terme "patch à trois volets" pour décrire cette technique, mettant en avant son avantage de fournir plus de contexte pour la fusion par rapport aux patches traditionnels. Alors que git apply gère généralement les patches traditionnels, il offre également un drapeau --3way pour effectuer des merges à trois volets. Cette exploration met en évidence l'intelligence de l'utilisation des merges à trois volets pour appliquer des patches dans git, offrant une approche unifiée pour diverses opérations tout en restant transparent pour les utilisateurs qui peuvent se contenter du concept familier d'"application d'un patch". L'auteur reconnaît la complexité de la fusion dans git, évoquant des concepts tels que les merges récursifs et les algorithmes de fusion multiples, avec le livre "Building Git" suggéré pour une exploration plus approfondie. Enfin, l'auteur exprime son admiration pour la conception élégante du mécanisme de patching de git, louant son intuitivité et son efficacité.