Archives mensuelles : avril 2021

Sur les traces de Strace…

J’avance toujours sur la playlist ansible avec la 125ème vidéo dédiée au développement de votre propre module. C’est sympa ansible mais ça fait pas tout. C’est un outil parmi tant d’autres à découvrir et à connaître. Et si vous me suivez régulièrement, j’aime explorer des outils récents et d’autres un peu moins récents… mais tout aussi nécessaire… voir plus.

Strace fait partie de cette classe d’outil sur lequel vous pouvez vous investir durablement et en profondeur. Et cela sans que cette connaissance ne puisse être remise en cause par une nième technologie qui vient mettre au placard ce que vous avez appris.

C’est pour cela qu’apprendre les rudiments du système demeurent et resteront longtemps valables. D’autant plus que celui-ci n’évolue pas si vite et ne va pas disparaitre ou changer complètement du jour au lendemain. C’est donc un placement sûr et durable. Et il faut toujours garder cela en tête… Et comme les vieux langages reprennent de la valeur avec le temps, je suis persuadé que des bases solides en système reprendront de la valeur quand cette compétence se fera plus rare avec l’émergence des clouds et autres couches permettant parfois de réduire les connaissances du système.

J’ai donc décidé de commencer cette formation strace sous forme de playlist. Certains n’y apprendront rien je m’en doute mais ce que je veux c’est initier des réflexes dans l’approche du troubleshooting et du debug. Et à travers celà renforcer et consolider ses bases en système.

Les origines de Strace

J’aime revenir aux sources avant de commencer à apprendre à utiliser une technologie. Cela permet de se mettre dans le bain tranquillement.

Alors Strace commence initialement en 1991 du côté de SunOS avant de rejoindre Linux en 1992. Donc on peut considérer que ce projet a plus de 30 ans !!! c’est magnifique tout de même.

Le site officiel : https://strace.io/

Le dépôt github : https://github.com/strace/strace

Maintenant il est embarqué sur la plupart des distributions Linux. Il faut dire qu’il se base sur un syscall un peu dédié à savoir ptrace (le comble pour un outil qui trace les syscalls).

Mais alors comment résumer un syscall ? Un appel système c’est le moyen de communiquer avec le kernel (noyau), à partir du user mode. Ce dernier c’est ce que nus utilisons au quotidien, là où tourne : les applications, le terminal, votre navigateur….

Un syscall est une fonction avec un objectif bien défini pour utiliser le kernel. Sur linux on compte environ 300 syscalls. D’ailleurs on ne les utilise pas souvent en direct on passe souvent par la LibC. Et pour les trouver rien de plus simple, il suffit de se rendre dans le chapitre 2 du man pour y découvrir leur documentation à commencer par :

man 2 syscall

Eh oui pas besoin d’en faire des tonnes.

Et vous pouvez y retrouver le fameux ptrace :

man 2 ptrace

et notamment la manière de l’utiliser en C :

       #include <sys/ptrace.h>
       long ptrace(enum __ptrace_request request, pid_t pid,
                   void *addr, void *data);

Et là on voit que l’on va travailler principalement avec les PID et donc les processus. Donc strace trace les processus via leurs syscalls.

Tout le monde ne peut pas tracer

On en entend pas souvent parler mais tout le monde ne peut pas tracer. Généralement on passe un petit coup de sudo et on en parle plus mais c’est plus fin que cela tout de même.

Un paramètre du kernel Linux permet de fixer cela dans :

/proc/sys/kernel/yama/ptrace_scope

Avec les valeurs :

0 : même UID
1 : ascendance (sinon élévation de privilèges)
2 : admin seulement
3 : interdit

Donc on peut faire évoluer ce paramètre temporairement avec un :

sudo sysctl -w kernel.yama.ptrace_scope=3

on vient d’interdire temporairement l’utilisation de strace.

Ou encore de manière permanente :

sudo echo 0 > /proc/sys/kernel/yama/ptrace_scope

Car il faut le rappeler strace va nuire à la performance du processus sur lequel il va s’attacher. Oui c’est le terme à employer car vous allez le voir il ne lui lache pas les baskets.

Alors vous pouvez fair votre première trace d’un simple ls par exemple :

strace ls

Et l’output calme un peu au début, voir va en convaincre quelques uns de ne plus le réutiliser. Mais le bon réflexe c’est de se dire que ce n’est rien que des choses qu’il faut débrousailler petits morceaux après petits morceaux. Et chacun de ces morceaux apporte terriblement en connaissance du fonctionnement du système. En effet, pour chacun on peut creuser profondémment les choses.

Quelques options pour débuter tranquillement

Pour ne pas prendre peur, on va commencer par 3 options très simples :

  • s : permet de définir la longueur de la ligne d’output (si on résume). Par défaut à 32, on peut déjà utiliser un 80 voi run 1024 pour vraiment ne rien manquer.
  • p : très important car nous n’allons pas toujours avoir la chance de lancer un process via strace comme nous venons de le faire pour ls. Alors nous allons nous attacher à un processus qui tourne déjà grâce à l’option -p suivie du pid du process (attention aux forks on verra cela après).
  • o : l’output de strace n’est pas si évident que cela à capturer en effet il faut rediriger la sortie stderr vers stdout 2>&1, c’est pas très classe alors avec -o vous pourrez spécifier un fichier de sortie.

Donc une ligne de commande complète pour commencer gentillement serait :

strace -p <pid_du_process> -s 1024 -o strace.log

Voilà pour débuter avec strace. Bien sûr on ne va pas s’arrêter là car on a pratiquement rien découvert mais il faut bien commencer.

N’hésitez pas à rejoindre la chaine pour ne pas manquer les prochaines vidéos.

Les boucles with avec ansible

Continuons sur notre formation ansible. Alors que j’ai tourné la 123ème d’un cours qui sera assez complet sur ansible, je vous propose de continuer progressivement après notre article sur stat et register. Pour les personnes qui souhaitent accéder à ces vidéos sans attendre, elles sont déjà disponibles pour les membres VIP de la chaine xavki qui la soutiennent.

En matière de formation, je pense qu’il faut être progressif et patient. C’est pour cela que je préfère aborder quelques notions au début mais sans brûler les étapes.

Aujourd’hui nous allons nous former à l’utilisation des boucles dans ansible. Les principales sont faciles à retenir car elles commencent par : with_*. La plus répandu étant with_items.

Avant de commencer, il me semble nécessaire de préciser que ansible est en cours d’évolutions dans ce domaine. L’objectif est de basculer à loop et remplacer potentiellement les with_*. Pour le moment nous n’en sommes pas là et les with_* sont plus faciles à aborder et retenir pour commencer. La documentation précise bien que cette migration ne se fait pas rapidement et que with_* possède encore de beaux jours devant lui, on est loin de le voir déprécier.

Les différentes boucles possible avec with

Si loop ne remplace pas encore les with, c’est essentiellement car il en existe de nombreux et que chacun dispose de boucler sur une fonctionnalité particulière :

  • with_items : sur une liste de dictionnaire (ensemble de clefs/valeurs)
  • with_nested : sur une liste de listes
  • with_dict : parcourir un dictionnaire
  • with_fileglob : sur une liste de fichiers de répertoire avec ou sans pattern mais non récursif
  • with_filetree : sur une liste de fichier d’une arborescence (recursif) et avec pattern
  • with_together : permet de croiser 2 listes
  • with_sequence : pour parcourir un range (interval)
  • with_random_choice : tirage aléatoire dans une liste
  • with_first_found : sur le premier élément trouvé d’une liste
  • with_lines : pour parcourir chaque ligne d’un programme (exemple : shell)
  • with_ini : pour parcourir un fichier au format ini
  • with_inventory_hostnames : pour récupérer et parcourir des éléments d’un inventaire

On a donc du choix, mes préférés étant with_items et with_fileglob principalement.

Comment utiliser with_* avec ansible ?

C’est très simple. Les éléments d’entrées sont définis dans le with_* et en sortie sont utilisable par une variable « item ». En cas d’éléments si disposant de plusieurs clefs ont les utilisera avec « item.clef1 », « item.clef2″…

Dans le cas le plus simple nous pouvons commencer par parcourir une simple lite d’éléments :

  - name: boucle création de répertoire
    file:
      path: /tmp/xavki/{{ item }}
      state: directory
      recurse: yes
    with_items:
    - xavki1
    - xavki2
    - xavki3
    - xavki4

Ou encore, dans un playbook, nous pouvons faire un test avec une liste de dictionnaires :

  - name: création de fichiers
    file:
      path: /tmp/xavki/{{ item.dir }}/{{ item.file }}
      state: touch
    with_items:
    - { dir: "xavki1", file: "fichierA"}
    - { dir: "xavki2", file: "fichierB"}
    - { dir: "xavki3", file: "fichierC"}
    - { dir: "xavki4", file: "fichierD"}

Nos clefs sont « dir » et « file » et donc nous allons les utiliser avec item.dir et item.file. Ansible fait le reste pour parcourir la boucle. C’est assez facile pour débuter !!! ou encore en passant par une variable.

  vars:
    fichiers:
    - { dir: "xavki1", file: "fichierA"}
    - { dir: "xavki2", file: "fichierB"}
    - { dir: "xavki3", file: "fichierC"}
    - { dir: "xavki4", file: "fichierD"}
  tasks:
  - name: création de fichiers
    file:
      path: /tmp/xavki/{{ item.dir }}/{{ item.file }}
      state: touch
    with_items:
    - "{{ fichiers }}"

Alors maintenant imaginons que nous souhaitions parcourir les machines composant un groupe de notre inventaire. Le premier réflexe en méconnaissant les boucles serait de faire la chose suivante :

 with_items:
    - "{{ groups['all'] }}"

C’est fonctionnel car on pourra bien récupérer la liste des machines avec la variable « item » de notre with_items. Mais nous l’avons vu , il existe un with dédié à cette tâche with_inventory_hostnames. Ainsi nous pouvons le faire de cette manière :

  - name: création de fichiers
    file:
      path: /tmp/{{ item }}
      state: touch
    with_inventory_hostnames:
    - all

Les boucles un outil indispensable

Clairement nous ne verrons pas d’exemples dans cet article. L’idéal pour manipuler les boucles c’est la pratique d’exemples réels. Cela fera l’objet des TP.

Ainsi les boucles vont nous permettre de définir des variables de types dictionnaires de manière à être en mode descriptif et avoir des blocs qui représentent notre infrastructure. Le with_fileglob nécessite un peu plus de pratique et de recul sur la manière d’organiser un code d’infra as code. Ainsi, nous allons pouvoir nous en servir pour sépcifier un répertoire contenant des usitsateurs : clefs ssh, login… Et une fois cela réalisé il ne restera qu’à récupérer les variables contenues dans ces fichiers. Ce point est l’un de mes préférés sur ansible donc nous n’y couperons pas.

Si vous souhaitez ne pas manquer les prochaines vidéos, vous pouvez vous abonner. Et pour m’aider encore plus vous pouvez éventuellement liker les vidéos.