Skip to content

Linux Attitude

Le libre est un état d'esprit

Archive

Tag: Scripting

Niveau :      
Résumé : date ; vi

Convertir un timestamp en date :

$ perl -e '$t=localtime($ARGV[0]); print "$t\n";'

D'où l'alias utile :

$ alias sdate='perl -e "\$t=localtime(\$ARGV[0]); print \"\$t\\n\";"'

En vi pour commenter une ligne :

:s/^/#/

Pour commenter plusieurs lignes :

v
# sélectionnez vos lignes
:s/^/#/

Pour commenter toutes les lignes :

:%s/^/#/

Et n'oubliez pas de décommenter les lignes :

:%s/^#//

Pour lancer une commande dans un screen déjà lancé en une commande :

$ screen -S ma_session -X exec ma commande

Attention, la session screen doit avoir au moins été affichée une fois (ie pas lancée avec -d -m)

Niveau :      
Résumé : tail --retry ; tail --follow ; read

Savez-vous qu'il est possible de faire un tail sur un fichier qui n'existe pas encore (mais qui existera bientôt) ?

$ tail --retry

Savez-vous qu'il est possible de faire un tail sur un fichier qui disparaît et réapparaît (par exemple un fichier de log avec un logrotate intermédiaire) ?

$ tail --follow=name

Les éléments d'un pipe sont nécessairement exécutés dans des processus séparés. Par conséquent, il faut faire attention à vos scripts shell. Par exemple le script suivant ne met rien dans la variable var, même si fichier contient quelque chose (et c'est aussi valable pour les boucles while).

$ cat fichier | read var

Par contre le script suivant fera ce que vous pensez :

$ read var < fichier

Et si vous avez vraiment besoin d'utiliser les pipes, utilisez les pipes nommés :

$ mkfifo pipe
$ ligne | longue > pipe &
$ read var < pipe

Niveau :      
Résumé : m4

m4 est un langage de macro bien utile. Le jour ou vous avez un fichier texte (ou plusieurs) un peu long et répétitif et que vous en avez marre d'éditer 50 lignes à chaque modification, alors m4 est la solution à votre problème.

Tout d'abord m4 est un langage de macro, c'est-à-dire qu'il ne sert qu'à prendre du texte pour générer du texte, et il s'écrit inline. Donc votre fichier de configuration apache est déjà un fichier m4 qui se génère lui-même à l'identique :

$ m4 /etc/apache2/apache2.conf

C'est cool non ! Pas besoin de partir de zéro, vous faites avec ce que vous avez.

Maintenant écrivons un petit fichier m4 pour apprendre :

dnl ###############
dnl # commentaire #
dnl ###############
dnl

Premier test
`Deuxième test'
# `troisième test'

=>

Premier test
Deuxième test
# `troisième test'

continue reading...

Niveau :      
Résumé : dd ; vcstime ; fold ; for

Vous avez un fichier à faire grossir de 10M à 100M :

$ dd if=/dev/zero of=file bs=1M count=1 seek=99

Afficher l'heure dans tous les terminaux linux (dans celui en cours en fait), à laner en root :

# du paquet console-tools
$ vcstime &

Formater un texte à 80 colonnes :

$ fold -w 80 < texte

Conversion de base 12 en base 10 rapide en shell :

$ echo $((12#123))

Faire des boucles énumérées en bash (sisi c'est possible) :

$ for ((i=0;i<=10;i++)); do echo $i; done

Pour passer d'une page à la suivante, faites un clic/déplacer/clic. Ça ressemble à un double clic avec un déplacement au milieu. Si votre déplacement est vers la gauche, vous revenez d'une page en arrière, s'il est vers la droite, vous avancez d'une page.

Niveau :      
Résumé : kill -STOP ; kill -CONT

Lorsque vous lancez un programme, vous pouvez lui faire faire une pause. Vous savez tous comment faire :

$ sleep 10
ctrl-z
# et on relance
$ fg

Super, et maintenant si le soft a été lancé en arrière plan ?

$ sleep 10 &
# on le fait refenir au premier plan
$ fg
# pause
ctrl-z
# et on relance
$ fg

Bravo, vous avez passé le premier test. Maintenant, plus difficile. Et si le soft a été lancé depuis un autre terminal ? La réponse se trouve dans l'étude des signaux. Il existe un grand nombre de signaux, pour preuve :

$ kill -l

Mais une sélection précise permet de retrouver ceux qui sont derrière ctrl-z et fg. Il s'agit de STOP (19) et CONT (18). La réponse est donc :

# on pause
$ kill -19 1234
# et on relance
$ kill -18 1234

PS : Tant qu'on est dans les signaux, notez le signal sigalarm qui permet de réveiller un sleep qui dort (attention sa valeur de retour ne sera alors plus 0).

$ kill -14 1234

Niveau :      
Résumé : mysleep

Si vous gérez plusieurs serveurs, il est probable que vous ayez des crons sur un certain nombre d'entre eux. Il est aussi probable qu'un certain nombre aient des cron en commun. Lorsque ces cron impactent d'autres serveurs (serveur NFS, ftp ...) il vaut mieux éviter de lancer toutes ces crons en même temps.

Mais il et dommage de devoir gérer et envoyer des configurations différentes pour chaque serveur. D'autre part, les lancer de façon aléatoire pose le problème qu'elles peuvent encore se lancer en même temps, mais aussi qu'il sera plus difficile de débugger un éventuel problème .

Je vous propose dons un outil qui pourra être commun à toutes les machines et qui lancera ces cron à des moments presque tous différents mais invariables, appelons-le mysleep.

#!/bin/sh

# choix d'une durée
DURATION=$((0x`hostid`%$1*$2))

# debug
[ "$DEBUG" == "1" ] && echo $DURATION

# et on attend
sleep $DURATION

Il s'utilise alors de la façon suivante dans vos cron :

# 5 machines, lancement séparé de 60 secondes
0 12 * * * /usr/local/bin/mysleep 5 60 && /path/to/cron/script

Attention, ce script se base sur le hostid. Rien ne garantit qu'il soit unique, il est d'abord lu comme le premier entier de 32 bits de /etc/hostid, et s'il n'existe pas comme l'ip correspondant au hostname. Et enfin s'il n'existe pas il vaut 0. En cas de problème vérifiez donc la distribution de vos hostid.

En cas de problème vous pouvez faire afficher au script la valeur de son sleep :

$ DEBUG=1 /usr/local/bin/mysleep 5 60

Ensuite ce script prend 2 paramètres le premier indique le nombre de valeurs différentes qu'on veut obtenir et le second l'écart entre ces valeurs. Le produit des 2 indique donc l'écart maximum entre la première et la dernière cron.

Attention, rien ne garanti que la répartition soit uniforme et donc que 2 machines ne se lanceront jamais en même temps. Mais si vos machines sont distribuées sur un réseau local, il est probable que les ip se suivent et donc que les valeurs de sleep soient toutes différentes.

Niveau :      
Résumé : ~/.bash_logout ; pgrep ; time

Pour éviter de laisser traîner des infos dans une console ouverte :

$ echo clear >> ~/.bash_logout

Pour récupérer rapidement un process sans tomber sur grep :

$ ps aux | grep "[t]oto"
$ pgrep -l toto

Comptage des connexions http et mail :

$ exec 3>&1 && ( netstat -putan | tee /dev/stderr |  echo http: $(grep -c ":80 .*ESTABLISHED") ) 2>&1 1>&3| echo smtp: $(grep -c ":25 .*ESTABLISHED" )

Lorsque vous faites une modification sur un serveur ssh, pensez à garder un ssh connecté. En effet, celui-ci restera ouvert même si le serveur ssh tombe. Faites vos modifications, puis un test avec un 2e client ssh et c'est seulement là que vous serez assez courageux pour fermer le premier client.

Mesurer une durée dans un script shell :

$ begin=$(date +%s)
$ [...]
$ duration=`date +%T  -d "01/01/1970 +$(($(date +%s)-begin)) seconds "`
$ echo $duration

Mesurer une durée dans un script shell (bis) :

# attention, ce n'est pareil, l'information est écrite directement dans le terminal
$ time [...]