Bash : compter les heures, ajouter un 0 devant une heure inférieure à 10

closeCet article a été publié il y a 6 ans 9 mois 2 jours, il est donc possible qu’il ne soit plus à jour. Les informations proposées sont donc peut-être expirées.

J’ai été confronté à un problème simple à la base (pour un adminsys) : compter le nombre de requêtes sur un site, heure par heure, à partir d’un fichier access_log Apache. Finalement le problème était un peu plus tricky, et ça demande un peu plus d’explications qui ne tiennent pas dans une astuce diverse.

 Le log apache est facile à lire via bash, il contient la date et l’heure dans un format que grep n’aura aucun mal à identifier. Je shoot donc un one-liner rapide :

Simple, rapide, efficace, le quotidien du sysadmin quoi. Enfin efficace… Le résultat est sur le coup surprenant :

Damned. J’imagine mal un site public sous WordPress capable de ne pas subir la moindre requête pendant plusieurs heures, entre monitoring, intervention client ou robots d’indexation. J’ai donc fait une connerie. Une connerie vite identifiée vu le pépin : l’heure est notée sur deux chiffres dans les logs, hors il n’y a que 0,1,2 qui peuvent matcher dans ce cas, ce qui explique les trous de 3 à 9.

Certains furieux trouveraient certainement une regex ultra cradingue à exploiter à la place (et faut pas hésiter à partager en commentaires), j’ai fait un peu différent (c’est surtout pour ça que je voulais en parler), à savoir passer deux ensembles de nombres à for :

C’est beaucoup mieux.

Oui, on peut indiquer deux plages de valeurs sans avoir à faire deux boucles. Une bizarrerie découverte au hasard d’une recherche de solution à mon petit souci. En fait, dans la pratique les deux ensembles sont décomposés par Bash pour ne constituer qu’une seule liste, ce qui donne l’équivalent de la syntaxe suivante, bien plus longue et lente à écrire :

Ce langage ne cesse de m’étonner, j’ai l’impression qu’on pourrait y passer une vie sans en avoir fait le tour.

Bon ça m’empêchera pas de continuer à m’intéresser à PHP et Python 😛

5 Commentaires
Le plus ancien
Le plus récent
Commentaires en ligne
Afficher tous les commentaires
Liandri
Liandri
23/07/2017 13:59

Et l’heure 0? :0

Électron
Électron
23/07/2017 16:31

Y’a encore mieux, en fait.
Pour faire la liste tu peux simplement utiliser {00..23}, pour les valeurs de 0 à 9 bash va automatiquement insérer un 0 au début 🙂

Saeroshi
Saeroshi
23/07/2017 16:37

Bonjour à toi,

Tu peux aussi utiliser la commande seq -w 23 (ou seq -w 0 23)

Saeroshi.

David_5.1
David_5.1
23/07/2017 20:02

En plus compliqué : for i in {0..23}; do echo -ne "${i}h : $(grep "2017:$(printf '%02d' $i):" access.log |wc -l)n"; done Dans ce cas, c’est pas très utile, mais dans d’autres, ça peut, par exemple si on veut jouer avec de l’hexadécimal : for i in {0..255}; do printf '%02x ' $i; done' Dans tous les cas, le grep est peu précis et il pourrait matcher le user agent d'un troll… Aussi, logrotate (ou équivalent) peut passer et fausser les résultats. Je ferais plutôt :mawk ‘{gsub(« : »,  » « , $5); count[substr($5, 2, 14) »h: »]++} END {for (date in count) print date, count[date]}’… Lire la suite »

DasFranck
23/07/2017 23:15

Petite coquille à la fin sur la ligne de script shell : ‘for in in « 00 » « 01 » « 02 » « 03 » « 04 » « 05 » … « 23 »; do …’
Je crois pas que bash tolère les doubles in, ça doit juste être un i travesti en in.

Article sympathique sinon. 🙂