20 Nov 2019, 00:00

Sed

https://www.grymoire.com/Unix/Sed.html#uh-61

Début et fin de ligne

^ représente le début de ligne,
$ représente la fin de ligne.

Substitution

Lorsqu’on encadre la regex avec des apostrophes, son contenu est envoyé littéralement à sed.
Lorsqu’on l’encadre avec des guillements, les variables sont déployées par bash avant passage à sed.

L’option -r ou -E (POSIX) sert à passer en syntaxe d’expression régulières étendues. La seule différence est que, en mode étendu, les caractères ?+(){} servent par défaut de caractères spéciaux, et qu’ils faut les échapper pour les considérer en caractères littéraux.
Source

Un groupe encadré par des parenthèses signifie “cette suite de caractères précisément”.
On peut également accéder à ce contenu dans la partie remplacement. Le contenu des premières parenthèses sera accessible par \1, le contenu des deuxièmes par \2 etc (backreferences)
Par exemple,
echo azerty | sed -r 's/a(ze)r(ty)/\1 \2/'
renverra ze ty.

Un groupe de caractères entre crochet signifie “un caractère parmi ceux-là”. Le point doit être échappé pour y être placé. Si on souhaite placer les crochets eux-même dans ce groupe, il semble qu’il faille les mettre en premier, crochet fermant d’abord. On peut aussi y placer [:space:] pour inclure les espaces et tabulations. De même, il semble qu’il faille les mettre juste après les crochets (inclus dans les crochets).
Par exemple :
sed 's/[][[:space:](){}\._-]//g'

On peut choisir le nombre d’occurences d’un motif grâce à plusieurs opérateurs:
* : 0 ou + occurences
? : 0 ou 1 occurence
+ : 1 et + occurences
{m} : m occurences
{m,n} : entre m et n occurences
{m,} : m occurences et plus

Suppression de lignes

Se fait avec la syntaxe sed '/PATTERN/d' qui supprimera les lignes qui contiennent le motif “PATTERN”.
À l’inverse, sed '/PATTERN/!d' supprimera les lignes qui ne contiennent PAS le motif “PATTERN”. Dans ce cas, les simples apostrophes semblent nécessaires, sinon le motif “!d” est transformé en la commande “date”.

Délimiteur via motif

On peut spécifier 2 motifs qui définiront l’intervalle d’action de sed.
sed '/startpattern/,/endpattern/ <sed-commands>' file

05 Nov 2019, 00:00

Let's encrypt / Certbot

Visualiser les certificats existants :

cerbot certificates

Il vaut mieux créer un certificat par domaine, plutôt qu’un pour tous les domaines (ce qui est le cas par défaut si non précisé) Pour créer un nouveau certificat pour un domaine précis :

sudo certbot --apache -d example.com --rsa-key-size 4096

Les fichiers se retrouvent dans /etc/letsencrypt/archive/ et sont linkés dans /etc/letsencrypt/live/

Pour rajouter un domaine à un certificat existant :

certbot --expand -d example.com,new.example.com

Pour supprimer un certificat, il semble qu’il n’y ait d’autre moyen que de supprimer les dossiers concernés dans les dossiers live, archive et renewal (dans /etc/letsencrypt/ )

Pour renouveler tous les certificats :

certbot renew

Pour renouveler seulement un domaine précis, au choix :

certbot certonly -d example.com

Vérifier la longueur d’une clé en appel direct d’un site web :

echo | openssl s_client -connect example:443 2>/dev/null | openssl x509 -text -noout | grep "Public-Key"

05 Nov 2019, 00:00

Notes sur les ACL Linux

Général

Les ACL (Access Control List) sont des autorisations qui permettent de gérer les droits de manière plus fine que les permissions UNIX traditionnelles.

Elles doivent être activées dans le noyau Linux (grep -i acl /boot/config*).

Elles doivent aussi être activées lors du montage de la partition, soit explicitement, soit via les options de montage par défaut (sudo tune2fs -l /dev/sdX1 | grep Default\ mount pour voir les options de montage par défaut d’une partition).

On vérifie que les outils sont installés : sudo apt install nfs4-acl-tools acl

On repère un dossier sur lequel des ACL sont positionnées via la présence d’un “+” à la fin des permissions. Par exemple :

ls -al ./DATA

donne

drwxr-x---+ 14 user     group      4096 oct.  31 12:44 .

Visualisation des ACL

On peut voir le détail avec la commande getfacl ./DATA

# file: DATA/
# owner: user
# group: group
user::rwx
user:www-data:r-x
group::---
mask::r-x
other::---

On y voit les permissions classiques via user::, group:: et other::. On peut voir que l’utilisateur “www-data” possède des droits de lecture positionnés via ACL.

Lister les ACL récursivement dans un dossier

getfacl -R -s -p /directory | sed -n 's/^# file: //p'

Source

Définition des ACL

On peut modifier les ACL via la commande setfacl. Par exemple, pour ajouter des droits RW à l’utilisateur “user2”, on lance :

setfacl -m u:user2:rwx ./DATA

Récursivement :

setfacl -R -m u:user2:rwx ./DATA

qui positionnera les droits RW pour user2 sur tous les fichiers/dossiers inclus dans ./DATA.

Suppression des ACL

On peut supprimer les autorisations via setfacl -b ./DATA.
On peut les supprimer récursivement via setfacl -R -b ./DATA. Cela supprimera toutes les ACL positionnées sur des fichiers/dossiers qui sont inclus dans ./DATA.

14 Oct 2019, 00:00

Prévoir la taille des données à déplacer lors d'une réduction de partition NTFS
/sbin/ntfsresize --force --no-action -s 100G /dev/sdX1 | grep -e ERROR -e relocations

--force peut ne pas être nécessaire
-s indique la nouvelle taille de partition, par défaut en octets, et peut être suivi des suffixes k,M,G,ki,Mi ou Gi

On peut aussi

07 Oct 2019, 00:00

Notes sur systemd

Gestion des services

Les services sont stockés sous forme de fichier .services présents dans /lib/systemd/system/ et /etc/systemd/system/.
Lorsqu’ils sont activés, des liens vers ces fichiers sont présents dans des dossiers du type /lib/systemd/system/my-service.wants ou /lib/systemd/system/runlevel.wants.

Pour désactiver le démarrage automatique d’un service :
sudo systemctl disable mon-service.service
Pour le réactiver :
sudo systemctl enable mon-service.service
Vérifier s’il va démarrer automatiquement au prochain boot :
systemctl is-enabled mon-service.service
Voir s’il est en cours de fonctionnement :
systemctl status mon-service.service

Pour le démarrer ou l’arrer manuellement :
systemctl start mon-service.service
systemctl stop mon-service.service

Pour voir le journal d’un service :
journalctl -u mon-service

User-level services

dans $HOME/.config/systemd

Pour les gérer, systemctl --user

06 Oct 2019, 00:00

Désactiver le formatage automatique des cellules en tant que nombre sous LibreOffice Calc

Source

Ouvrir un classeur vierge. Taper F11, pour Ouvrir les Styles et formatages.
Modifier “Par défaut” (modifie les caractéristiques de toutes les celleules, pour ce document uniquement)", et définir le style par défaut pour les nombre en tant que “Texte”.

Fichier -> Modèles -> Enregistrer comme modèle
Ranger dans une catégorie, lui donner un nom (par ex. “FormatageAutoEnTexte”), cocher “par défaut” en bas, et valider.

Ainsi, dans tous les nouveaux documents, ce réglage sera appliqué, et les 0 en début de chaîne ne sauteront plus.

23 Sep 2019, 00:00

Obtenir tous les numéros de série des disques

Avec 12 disques (a -> l)

for i in {a..l}; do echo sd$i; udevadm info --query=all --name=/dev/sd$i | grep ID_SERIAL_SHORT; done

29 Aug 2019, 00:00

Reconfiguration GRUB2 sur système EFI, avec partition slash chiffrée via LUKS et partition boot séparée

Se fait via un live-cd démarré en EFI, de la même architecture que le système à dépanner (pour que le chroot fonctionne)

  • sdX1 : ESP (EFI System Partition)
  • sdX2 : partition slash chiffré par LUKS
  • sdX3 : partition boot
# On déchiffre et monte slash
cryptsetup open /dev/sdX2 slash
mount /dev/mapper/slash /mnt
cd /mnt

# On monte l'ESP et la partition /boot
mount /dev/sdX3 ./boot
mount /dev/sdX1 ./boot/efi

# On monte les fichiers systèmes temporaires
mount --rbind /sys ./sys
mount --rbind /dev ./dev
mount --rbind /proc ./proc
mount --rbind /run ./run


chroot /mnt
grub-install /dev/sdX --target x86_64-efi
update-grub

# On recrée l'initramfs, afin qu'il demande le mot de passe LUKS
update-initramfs -k all -u

29 Jul 2019, 00:00

Docker

Une source intéressante
Images, conteneurs et volumes
Dockerfile build

Installation sous Debian

  • On installe avec
sudo apt install docker.io

à partir de buster ; sinon, utiliser le site docker.io.

  • Puis on peut faire
sudo adduser user docker

pour ne pas avoir à taper sudo à chaque commande.

Gestion des images

  • Chercher une image Debian officielle, en se basant sur le score de l’image
docker search --filter=stars=1000 debian
  • Récupérer cette image en local (stocké dans /var/lib/docker/, en grosse partie sous forme de diff dans overlay2/ )
docker pull debian:tag
# si :tag est omis, docker cherchera :latest
  • Lister les images locales
docker image ls -a

# ou
docker images
  • Créer une image depuis un Dockerfile
# In folder containing the Dockerfile
docker build -t "my-image123:test" .
  • Pour supprimer une image
docker rmi my-image123:test
# on peut aussi utiliser l'id de l'image

docker build & Dockerfile

Lien qui en parle aussi
Sert à génerer des images modifiées à partir d’images existantes.
Utilise un fichier Dockerfile (nom non négociable).
Celui-ci est formaté avec une instruction FROM qui définit l’image de base utilisée. Ce peut être un nom type debian ou un ID type 00bf7fdd8baf

On peut utiliser RUN pour lancer des instructions shell pour modifier notre image (par exemple installer des paquets).

On peut gérer le programme lancé au démarrage d’un conteneur instancié sur cette image (par défaut bash chez Debian), ainsi que la commande executée par ce programme, via les instructions ENTRYPOINT et CMD. Plus de détails ici.
En gros, ENTRYPOINT est le binaire lancé lorsque le conteneur démarre (habituellement bash), et CMD est la commande éventuelle lancée par cet entrypoint. Définir un entrypoint sur autre chose que bash permet de faire du container un exécutable, qui ne lancera que ce pour quoi il est fait.
Les instructions RUN, ENTRYPOINT et CMD peuvent être écrites de 2 formes, la forme shell et la forme exécutable. Dans la forme shell, elle seront exécutées via -c alors qu’en forme exécutable, la commande est appelée directement :

# Shell form  
RUN /path/to/command -o option arg otherarg

# Exec form  
RUN ["/path/to/exec", "-o", "option", "arg", "otherarg"]

Un exemple de Dockerfile qui lance un serveur apache basique :

FROM debian

RUN apt-get update \
&& apt-get install -y apache2 nano

EXPOSE 8080 80

CMD apachectl -D FOREGROUND

On peut ensuite construire l’image désirée via docker build :

docker build -t nom:tag /path/to/folder/with/Dockerfile
# --rm=false : permet de ne pas supprimer les conteneurs intermédiaires (cache), même après un build successful

Gestion des conteneurs

Un conteneur est instancié à partir d’une image.

  • Créer un conteneur à partir de cette image
# en version simple
docker create debian
# qui va chercher debian:latest
# on peut aussi faire
# en plus complet
docker create -ti --name my-app123 --hostname app --net my-net123 -p 8080:80 debian:tag welcome-command --arg1 value --arg2
# les options doivent être avant le nom de l'image de base
# -t pour --tty, ce qui permettra de lancer le conteneur avec un shell root@truc:/# . Sans ça, il se coupe si rien à faire
# -i pour --interactive , ce qui laissera la porte ouverte au conteneur pour recevoir des commandes (STDIN ouvert)
# si aucun nom s'est spécifié, Docker en génerera un poétique
# si aucun hostname n'est spécifié, il sera géneré aléatoirement
# --net ou --network permet d'attacher le conteneur à un réseau choisi (doitj être créé auparavant
# -p pour exposer les ports ; voir section réseau
# on peut spécifier, après le nom d'image, la commande à exécuter (typiquement bash)
# on peut aussi spécifier une autre commande  pour outrepasser l'entrypoint, et/ou passer des arguments
  • Démarrer ce conteneur
docker start my-app123

Le conteneur est lancé, mais ne s’affiche pas dans notre terminal (juste son nom).
Il faut l’attacher, pour avoir le shell à l’écran et pouvoir interagir.

docker attach my-app123

Ou encore

docker exec -it container_name bash

On peut directement attacher le shell lors de la création du conteneur, mais il faut alors spécifier l’option -i pour pouvoir interagir avec le conteneur (taper des commandes).

docker start -ia my-app123  # --interactive --attach
# -a , --attach pour voir l'état du conteneur
# -i pour pouvoir taper des commandes

On peut ensuite détacher le conteneur avec Ctrl-P -> Ctrl-Q.

  • Éteindre ce conteneur
docker stop my-app123
docker kill my-app123 # pour forcer l'extinction
  • Lister les conteneurs
docker container ls
# ou en plus court
docker ps
# pour lister les conteneurs en cours d'éxécution

docker ps -a
# pour lister tous les conteneurs, même éteints.

docker ps -s
# pour lister la taille des conteneurs
  • Supprimer un conteneur précis
docker container rm my-app123
# on peut aussi utiliser l'id
  • Supprimer tous les conteneurs qui ne sont pas en train de tourner
docker container prune
# -f si on souhaite ne pas avoir de prompt de confirmation

docker run

Combine docker pull, docker create et docker start

docker run name
# télécharge si nécessaire l'image "name:latest", crée un container avec un nom aléatoire, et le lance
# on peut passer à docker run les mêmes arguments que docker create
docker run --name="my-app123" -p 80:80 -e TERM=xterm -d --net my-net123 --ip 172.18.0.23 demo-docker

Réseau

Doc chez docker

Docker crée une interface virtuelle pour chaque réseau créé. Par défaut, c’est la carte docker0 qui crée le réseau bridgé 172.17.0.0/24 avec l’adresse 172.17.0.1.
Il y’a différents types de réseau : bridge (réseau virtuel “simple”, choix par défaut), host (le conteneur se connecte directement via la pile réseau de la carte de l’hôte), overlay (surtout pour le swarm), macvlan.

On peut créer des réseaux (bridgés) définis sur mesure. Ces réseaux se comporteront différemment du réseau par défaut. Notamment, les machines pourront communiquer entre elles via leur adresse IP, mais également via le nom de conteneur.
De plus, les conteneurs d’un même réseau peuvent communiquer librement entre eux sur tous les ports (et, par défaut, aucun port n’est ouvert vers l’extérieur de ce réseau). Un conteneur peut être connecté à plusieurs réseaux.
Chaque conteneur lancés aura aussi une interface virtuelle (par réseau) type veth1234567.

  • lister les réseaux
docker network ls
  • voir le détail d’un réseau
docker network inspect network-name
  • créer un réseau
docker network create --subnet 172.18.0.0/24 my-net123
  • lancer un container sur un network
docker run --net my-net123 --ip 172.18.0.23
  • Connecter un conteneur sur un réseau (peut être fait à la volée pour un réseau défini, mais le conteneur doit être éteint pour le faire sur le réseau par défaut docker0)
docker network connect my-net123 my-app123
  • Déconnecter un conteneur d’un réseau (même restriction que pour la connexion)
docker network disconnect my-net123 my-app123
  • Supprimer un réseau
docker network rm my-net123
  • retirer les réseaux inutiles
docker network prune

Exposition et publication de ports

Un article intéressant

L’exposition de ports peut se faire dans le Dockerfile, ou bien à la création du conteneur. Toutefois, elle est principalement là pour documenter les ports utilisés par le conteneur, et n’aura (presque) aucun effet pratique. Cela peut se faire :

  • à la création du conteneur via docker create --expose 8080:80/tcp
  • dans le Dockerfile (donc dans l’image) via EXPOSE 8080 80/tcp.

Il me semble que certains mécanismes peuvent faire appel aux ports exposés, par exemple la détection automatique de port par nginx-proxy.

La publication de ports sert effectivement à “ouvrir” le port du conteneur depuis l’hôte. Ainsi, le service fourni par le conteneur deviendra accessible via l’IP de l’hôte sur le port choisi. Cette publication ne peut se faire que lors de la création d’un conteneur.

docker create -p 8080:80/tcp debian
# tcp est le défaut, et peut être omis, ou remplacé par udp

va rediriger le port 8080 de l’hôte vers le port 80 du conteneur. Ainsi, seul l’IP de l’hôte a besoin d’être routable.
Un port n’a pas besoin d’avoir été exposé pour pouvoir être publié.
On peut aussi écrire uneiquement -p 80/tcp, auquel cas un port est choisi aléatoirement sur l’hôte.

Exposer un port sur un conteneur déjà lancé

Lors d’un docker ps, les ports publiés seront mentionnés sous la forme 0.0.0.0:80->80/udp, alors que les ports exposés seront mentionnés sous la forme 80/tcp.

Voir le détail des ports d’un conteneur :
docker inspect my-app123 | grep -i port -A3
On y voit les ports exposés (ExposedPorts) et les ports publiés (Ports).

Volumes

Servent à monter un dossier de l’hôte chez le client.
Peut être déclaré dans le Dockerfile (non recommandé ici), ou au moment de la création du conteneur.

Docker-compose

Doit être installé en sus de docker.

sudo apt install docker-compose

Sert automatiser, via fichier de conf docker-compose.yml, la construction d’image sur mesure, ainsi que la création de conteneurs basé sur ces images, et leur paramétrage (port, etc…).

Si on est dans un dossier testcompose, on peut avoir le fichier docker-compose.yml suivant :

version: '3'

services:

  apache-test:
    build:
      context: apache-folder
      dockerfile: Dockerfile
    ports:
      - "8080:80"
    restart: always
    command: --arg1 value --arg2

Ceci définit un service apache-test, dont le Dockerfile et les fichiers pouvant être nécessaires à se construction se trouvent dans le dossier (context) apache-folder. Le port 80 sera publié via le port 8080 de l’hôte.

Les projects docker-compose ont un nom, qui par défaut est le nom du dossier. Ceci peut causer des messages d’erreur si plusieurs projets sont dans des dossiers qui portent le même nom (par exemple dev/myapp/ et prod/myapp ; les 2 projets s’appelleront myapp et seront “confondus” par le système). Ce nom de projet peut être défini dans le fichier .env, via la variable COMPOSE_PROJECT_NAME.

On peut lister tous les projets docker-compose via la commande suivante (source) :
docker ps --filter "label=com.docker.compose.project" -q | xargs docker inspect --format='{{index .Config.Labels "com.docker.compose.project"}}'| sort | uniq.

On peut construire l’image avec docker-compose build. Elle sera nommée testcompose_apache-test (nomdudossier_nomduservice).
Ceci crée aussi un réseau testcompose_default auquel seront liés tous les services définis dans le docker-compose.yml.

On peut aussi construire l’image, puis démarrer un container basé sur cette image, via docker-compose up --build.
Ceci va créer un container dont le nom est testcompose_apache-test_1.
On peut passer les conteneurs en arrière-plan avec l’option -d.

On peut passer des arguments à docker-compose via l’entrée command (qui, contrairement à ce que son nom indique, ne fait que rajouter des arguments à l’entrypoint défini dans l’image, à condition que celle-ci ait été définie en forme Exec, et non Shell. Source ).

On peut écrire la commande sur plusieurs lignes, en suivant la syntaxe suivante (ne PAS échapper les fins de lignes) :

  command: >
           myapp
           --firstoption "value"
           --secondoption
           --thirdoption "value"

(explication ici)

Docker secrets

Lire ici !

Variable d’environnement

Voir ici : https://vsupalov.com/docker-arg-env-variable-guide/

En gros,on a :

  • Le fichier .env : n’est pris en compte qu’au moment de l’interprétation du fichier docker-compose.yml, et sert à remplacer des variables dans ce fichier par des valeurs. Elles ne seront absolument PAS visibles par le conteneur lors de son exécution. Le nom d’un service ne peut toutefois pas utiliser de variable.

  • Les arguments type docker create -e VAR=val pour définir des variables qui seront accessibles dans le conteneur en exécution (on peut les lister avec la commande env lancée dans le conteneur). Ce mécanisme est utilisable dans docker-compose via la directive environment:

  • L’argument docker create --env-file=./fichier qui permet de définir un fichier dans lequel lire des variables, qui seront accessibles comme si elles avaient été passées via -e. Ce mécanisme est utilisable dans docker-compose via la directive env_file:

Troubleshooting

Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use

Signifie que le port sur lequel on essaye de lancer une machine est déjà pris par une autre machine.

Logs

docker logs my-app

Les logs sont stockés dans le fichier /var/lib/docker/containers/<container_id>/<container_id>-json.log

On peut mettre en place une rotation des fichiers de log en éditant le fichier /etc/docker/daemon.json

{
"log-driver": "json-file",
"log-opts": {
    "max-size": "10m",    
    "max-file": "3"    
    }
} 

puis systemctl restart docker (ATTENTION : redémarre tous les containers).
N’affecte que les containers nouvellement lancés.
Source

Colorisation des logs

Un certain nombre d’applications sont conçues pour coloriser leur sortie si celle-ci est de type tty.
Ceci peut se paramétrer dans la commande docker : docker -t ou dans le fichier docker-compose.yml : tty: true

L’avantage est que la sortie visuelle d’une docker logs sera plus lisible ; l’inconvénient est ça limite les usages autres : un docker logs myapp | less nous affichera tous les caractères de coloration, rendant l’ensemble peu lisible ; de même, un grep sur une chaîne avec un changement de coloration au milieu ne fonctionnera pas.

Pour remédier à ceci, on peut utiliser la commande ansi2txt, contenue dans le paquet Debian colorized-logs, et qui supprime les caractères de colorisation. Par exemple,
docker logs myapp | ansi2txt | less

Il y’a aussi des solutions individuelles en fonction du programme de sortie ; par exemple pour less, on peut utiliser less -R pour préserver les couleurs.

19 Jun 2019, 00:00

Désactiver la mise en veille de la carte son sous Linux

Sous Linux, il arrive que, pour économiser de l’énergie, la carte son se mette en veille après quelques temps d’inactivité. Ceci génère chez moi des craquements assez désagréables lors de sa remise en fonctionemment, ou parfois un craquement très régulier tout le long de la veille.

Pour voir si la mise en veille est activée :

cat /sys/module/snd_hda_intel/parameters/power_save

S’il contient autre chose que 0, alors le mode powersave est activé.

Pour le désactiver, on peut ajouter le fichier /etc/modprobe.d/snd_disable_powersave.conf et entrer dedans la ligne suivante :

options snd_hda_intel power_save=0

Puis redémarrer, ou bien décharger/recharger le module.