Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Scripting

Niveau :      
Résumé : pam_exec

Vous souvenez-vous de PAM (Pluggable Authentication Modules) ? En plus des nombreux modules déjà présentés, on trouve pam_exec qui permet d'exécuter une commande arbitraire. A partir de là on peut faire pas mal de choses, comme par exemple une notification à chaque session ouverte par un utilisateur (connexion ssh, su, sudo, etc.).


Notification de connexion

Nous allons créer une règle utilisant le module pam_exec pour exécuter un script de notification à l'ouverture d'une nouvelle session.


Script de notification

D'après le manuel de pam_exec, les informations PAM sont passées au script à l'aide des variables d'environnement : PAM_RHOST, PAM_RUSER, PAM_SERVICE, PAM_TTY, PAM_USER et PAM_TYPE. Concevons donc un script simple qui :

  • ne s'intéresse qu'au cas de l'ouverture d'une nouvelle session, soit le type PAM open_session
  • récupère les informations et les envoie par mail à l'administrateur

continue reading...

Niveau :      
Résumé : test d'expression régulière

Vous essayez de développer une expression régulière mais vous ne savez pas pourquoi ça ne marche pas ?

Tester une expression

Je vous propose le petit programme suivant qui vous aidera dans la compréhension du fonctionnement de votre regex. Son usage est simple :

./regtest.pl <regex> <chaine>

Exemple :

./regtest.pl "(\d+7)\.1\." "127.127.1.12"
127.127.1.12 : \d+
127.127.1.12 : \d+7
127.127.1.12 : (\d+7)
127.127.1.12 : (\d+7)\.1\.
    127      : $1

Le programme découpe l'expression en éléments syntaxiquement corrects et les applique à la chaine pour voir ce qui matche et le met en évidence. A la fin la liste des groupes qui ont matchés est affiché.

Il est aussi possible de remplacer une des paramètres (la chaine ou la regex) par un '-'. Le programme boucle alors sur l'entrée et vous permet d'entrer une ligne à chaque fois. Vous pouvez donc faire un test en continu. L'avantage et surtout pour les regexp, cela permet de s'affranchir des caractères spéciaux qui pourraient être interprétés par le shell.

Notez que vous aurez besoin de Regexp::Parser qui n'est pas installé par défaut.


continue reading...

Niveau :      
Résumé :

Aujourd'hui un thème un peu polémique mais pas trop quand même.

Le XML est un descendant du SGML. C'est un format structuré de données comme l'est l'ASN1 ou le LDIF.

Tous ces formats ont été inventés dans une seule optique : être facile à parser par une machine. Et pourtant quand on voit les subtilités du XML et les difficultés à faire un parseur, on peut avoir des doutes... Mais de ce fait ils sont peu lisibles.

Ne vous méprenez pas, le XML a tout à fait sa place dans les échange de données, dans la communication entre machines. Le format est bien défini et fonctionne quel que soit le type de machine. Il est d'ailleurs très utilisé car on trouve des parseurs partout, dans presque tous les langages, et dans presque tous les frameworks.

Mais à force d'en user on en abuse.

Non le XML n'est PAS fait pour les humains ! Le xml n'est pas à sa place dans les fichiers de configuration, à moins que vous n'ayez pour objectif que l'utilisateur ne touche jamais à ces fichiers et que vous ayez le temps de développer une interface entre l'utilisateur et la modification (texte ? graphique ? sonore ?).

Le XML est pratique car il permet au développeur d'éviter l'usage de protocoles binaires incompréhensibles et mal parsés entre deux applications. Il est pratique car un autre développeur peut lire ce protocole sans l'avoir appris. Mais vous remarquerez que je ne parle que de développeurs, pas d'utilisateurs.

Alors par pitié arrêtez le XML dans les fichiers destinés aux HUMAINS. Il existe bien d'autres formats ayant des parseurs et tout aussi lisibles :

Mieux, il existe LUA qui vous permet à la fois d'avoir un fichier de configuration simple et lisible, mais qui en plus autorise l'utilisateur à faire des choses que vous n'auriez pas prévu, comme des configuration conditionnelles !

Niveau :      
Résumé : ~/.gnome2/nautilus-scripts

Aujourd'hui parlons un peu d'interface utilisateur. Vous arrive-t-il souvent de lancer la même commande sur plein de fichiers ? Avez-vous une personne de votre famille qui perd son temps à ouvrir des fichiers un par un pour faire une modification dans chaque ?

Si ces opérations sont automatisables (calculs openoffice, modification d'image, ajout d'une ligne de texte ...) alors il y a un moyen pour les rendre accessible directement depuis le navigateur de fichier. Pour cela, il suffit d'écrire un script et de le placer dans ~/.gnome2/nautilus-scripts. Essayer de bien le nommer car il apparaîtra tel quel dans le menu contextuel "Scripts" de nautilus.

Pour parler concrètement, nous allons faire un outil de réduction d'image disponible directement depuis le navigateur de fichier. Nous allons donc éditer le fichier ~/.gnome2/nautilus-scripts/ReductionPhotos qui nous permettra d'appeler imagemagick pour réduire la taille des photos sélectionnées (en ajoutant un préfixe pour ne rien perdre). Nous feront notre démo sur tous les fichiers sélectionnés à la souris pour bien montrer qu'on automatise un comportement d'utilisateur "normal".

Le script reçoit ses informations dans des variables d'environnement. La plus importante dans notre cas est NAUTILUS_SCRIPT_SELECTED_FILE_PATHS qui contient la liste des fichiers sélectionnés séparés par des retours à la ligne. Donc une petite boucle pour les traiter tous d'un coup :

echo -n "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" | while read in_file
do
        process_file $in_file
done

Alors il se peut que le script ait des questions à poser à l'utilisateur. C'est le moment d'utiliser zenity. Un petit outil sympa, équivalent de dialog, mais bien mieux intégré dans gnome. Petite exemple avec la sélection d'un nombre dans une intervalle de 0 à 100 :

$ percent=$(zenity --scale --title="Choix du pourcentage" --text "Pourcents : " --value="50" --min-value="0" --max-value="100" --step="1")

Simple non ?

Pour traiter les images en ligne de commande, vous connaissez imagemagick. Voici la commande à utiliser dans mon cas :

convert image1.jpg -quality 80 -resize 1200 image2.jpg

Voila, on a toutes les briques pour faire le script.


continue reading...

Niveau :      
Résumé : pam_faildelay.so ; tail -F * ; dusort ;

Réduire le délai en cas d'erreur du mot de passe (très chiant pour su par exemple). Simple calcul, le délai par défaut de 2s donne 13243 ans pour bruteforcer un mot de passe de 8 lettres (26 possibilités). On peut donc se permettre de diviser ce délai par 4 pour apporter un peu de confort à l'usage :

$ vi /etc/pam.d/common-auth
# on annule le délay ajouté par pam_unix
auth    required        pam_unix.so nullok_secure nodelay
# on ajoute un délai en microsecondes
auth  optional  pam_faildelay.so  delay=500000

Attention, login vient avec son propre délai supplémentaire de 3 secondes chez debian (dans /etc/pam.d/login).

Il est possible de regarder les nouvelles lignes sur plusieurs fichiers en même temps :

$ tail -F /var/log/*

Alias pour connaître rapidement les 10 plus gros répertoire du répertoire en cours :

$ alias dusort='du --max-depth=1 | sort -rn | head -n 10'

Appeler une commande en évitant tous les alias possible (par exemple rm qui est aliasé rm -i):

# bash uniquement
$ \commande

Avancer / reculer d'un mot lors de l'édition de ligne (bash ou tout outil readline) Esc-fleche droite ou gauche.

Effacer les fichiers de plus de XX jours :

$ find . -not -ctime -XX -name "*.ncap" -exec rm {} ;

Niveau :      
Résumé : moreutils ; ts ; vidir ; mispipe ; isutf8 ; lckdo ; vipe ; ifdata ; pee

Ces commandes sont dans le paquet moreutils sur debian.

Ajouter un timestamp sur chaque ligne pour lire une commande un peu lente :

$ ./commande | ts | tail

Éditer en masse les entrées d'un répertoire (pour renommer des images par exemple) :

# Tout le répertoire
$ vidir repertoire
# Seulement les images 
$ vidir *.jpg

Retourner le code d'erreur du premier élément d'un pipe et non du dernier (très utile en scripting) :

# Retourne une erreur si $dir n'existe pas
$ mispipe "ls $dir" "tail"

Vérifier qu'un fichier utf8 est valide :

$ isutf8 fichier && echo OK || echo "Not OK" 

Ne pas écraser un fichier de destination avant la fin de la commande :

# Version fonctionnelle de cat a b > a
$ cat a b | sponge a

Créer un script de type cron avec un lock sans effort :

$ lckdo -W 10 /var/lock/mylock /usr/local/bin/myscript

Éditer le contenu d'un pipe (très pratique pour le debug de script) :

$ commande1 | vipe | commande2

Éviter les envois de mail de rapport lorsqu'il n'y a rien à rapporter :

$ /usr/local/bin/rapport.pl | ifne mail -s "Synchro en retard" sysadmins@mynnet.net

Permettre (optionnelle ment) de passer des fichiers compressés en argument à un script (comme pour zless) :

# Recoder zless
$ zrun less $1

Éviter de parser le résultat de ifconfig ou de ip dans un script (nombreuses options, de sortie, lire le man) :

# Afficher le nombre d'octets reçus
$ ifdata -sib eth0

Passer le résultat d'une commande à plusieurs autres

# Attention si commande1 et commande2 produit du texte, rien ne garantit leur ordre
$ commande | pee "commande1" "commande2"

Comparer ligne par ligne deux fichiers avec des opérateurs plus évolués que comm :

$ combine fichier1 xor fichier2

Niveau :      
Résumé : man -H ; $- ; dd ; losetup ; bc ; APT::Install-Recommends=false ; /proc/net/ip_conntrack

Tester si on est dans un shell interactif (spécifique bash) :

$ if [[ "$-" == *i* ]]; then echo INTERACTIF; fi

Réduire le lecteur dvd au silence :

# copie sur le disque, attention au changement de media :-)
$ dd if=/dev/dvd of=/tmp/dvd && sudo rm /dev/dvd && sudo ln -s /tmp/dvd /dev/dvd

Réduire le lecteur dvd au silence (mieux):

# copie sur le disque puis loopback, attention au changement de media :-)
$ dd if=/dev/dvd of=/tmp/dvd
$ loop=$(sudo losetup-f)
$ sudo losetup $loop /tmp/dvd
$ sudo rm /dev/dvd && sudo ln -s $loop /dev/dvd

Conversion de base :

# hexadécimal -> decimal
$ echo "ibase=10; AC"|bc
# décimal -> hexadecimal
$ echo "obase=16; 100"|bc

Lecture des pages de man dans firefox :

$ man -Hfirefox ls
# si /etc/alternatives/www-browser (debian) ou $BROWSER pointent vers le bon navigateur
$ man -H ls

Ne pas installer les paquets recommandés pendant une installation (base debian, ubuntu ...) :

## apt-get install -o APT::Install-Recommends=false LePaquet
# Mieux
apt-get --no-install-recommends install LePaquet

Bloquer a fonction de routage d'un noyau < 2.6.12 :

while true; do cat /proc/net/ip_conntrack > /dev/null; done