Sortie de la commande 'watch' sous forme de liste

27

Je veux faire un calcul simple du nombre de lignes par minute ajoutées à un fichier journal.

Je souhaite également enregistrer le décompte pour chaque seconde.

Ce dont j'ai besoin est la sortie de la commande suivante sous forme de liste qui sera mise à jour toutes les secondes:

watch -n1 'wc -l my.log'

Comment sortir la 'mise à jour' de la commande 'watch' sous forme de liste?

JohnJohnGa
la source

Réponses:

24

Vous pouvez utiliser le -tcommutateur watchqui l'empêche d'imprimer l'en-tête. Cependant, cela effacera toujours l'écran afin que vous soyez mieux avec une simple boucle de shell:

while sleep 1; do
    wc -l my.log
done

L'un des avantages est que vous pouvez facilement ajouter d'autres commandes (par exemple date) et / ou diriger la sortie sedpour la reformater. Soit dit en passant, si vous échangez sleep 1avec wcdans la boucle, il se terminera automatiquement en cas d'erreur.

peterph
la source
Cependant, notez qu'il ne le fera pas exactement toutes les secondes (avec zsh ou ksh93, vous pouvez ajuster le temps de sommeil afin de tenir compte de la dérive occasionnée par l'exécution des commandes dans la boucle, cependant)
Stéphane Chazelas
2
@StephaneChazelas ne le fera pas non plus wait- essayez simplement watch -n 1 "sleep 5".
peterph
En effet (j'ai vérifié les implémentations de procps et de busybox). Je pensais que c'était la seule chose qui watchétait utile, mais cela ne vous donne même pas cela, donc votre solution est aussi bonne que celle basée sur une montre, mais ni l'une ni l'autre ne répond avec une grande précision à la question "taux de croissance d'un fichier journal" .
Stéphane Chazelas
Eh bien, si le nombre de lignes par minute est l'objectif ultime, l'échantillonnage toutes les 10 secondes est plus que suffisant - donc les frais généraux ne sont pas si terribles (à moins que le fichier ne devienne vraiment gros, bien sûr). Et en fait à partir de la boucle, on peut imprimer des informations de synchronisation (même avant et après la fin de la commande si nécessaire), puis la précision peut s'améliorer (ordres de grandeur) même pour des fichiers plus gros.
peterph
1
@peterph watcha une -poption qui le fera correctement, si possible (évidemment, vous ne pouvez pas exécuter une commande qui prend 5 secondes toutes les 1 secondes, si vous n'êtes pas autorisé à en faire plusieurs simultanément). Je sais, je l'ai écrit :-P
derobert
8

Une vieille question, mais je viens de trouver une réponse très simple:

watch -n1 'wc -l my.log | tee -a statistics.log'

Cela exécutera wcchaque seconde, ajoutera sa sortie au fichier statistics.log et l'affichera également à l'écran.
Ainsi, vous vous retrouverez avec un fichier rempli de nombres, représentant le nombre successif de lignes de my.log.

Orabîg
la source
Veuillez noter que cette commande ne l'est watch "($MYCMD | tee -a $MYLOG)"pas watch "($MYCMD)" | tee -a $MYLOG. Si vous vous trompez comme je l'ai fait, la sortie va être très très déroutante. Une autre chose à noter ici est que cette commande n'ajoute pas l'horodatage de l'exécution de chaque commande par défaut, donc la réponse avec la boucle pourrait toujours mieux fonctionner pour vous.
ffledgling
3

Que diriez-vous

tail -f file.log | pv -rl > /dev/null
Stéphane Chazelas
la source
3

Essayez ce qui suit:

watch -n1 'wc -l my.log >> statistics.log'
Andy
la source
1

Je suis tombé sur cette question lorsque j'essayais d'obtenir une sortie meilleure / enregistrée à partir de du -sh $data_path. J'ai utilisé le modèle "while commande, do sleep" trouvé ici, mais j'ai utilisé un AWK complexe pour donner la sortie que je voulais.

while du -sh $data_path; do sleep 1; done | awk '
$1 != size {
    size=$1;
    path=$2;
    time=systime();
    seconds=time-prevtime;
    if(seconds < 1000000000){
        seconds=seconds" seconds"
    }else{
        seconds=""
    }
    print size, path, strftime("%m/%d/%Y@%H:%M:%S", time), seconds; 
    prevtime=time
}'

En fait, je l'ai fait comme un oneliner, c'est pourquoi il y a des points-virgules. Mais pour le rendre lisible, je l'ai éclaté. La sortie ressemble à:

502G /var/lib/cassandra/dump/ 05/22/2018@04:46:17
503G /var/lib/cassandra/dump/ 05/22/2018@04:46:59 42 seconds
504G /var/lib/cassandra/dump/ 05/22/2018@04:47:57 58 seconds
505G /var/lib/cassandra/dump/ 05/22/2018@04:48:55 58 seconds
506G /var/lib/cassandra/dump/ 05/22/2018@04:49:53 58 seconds
507G /var/lib/cassandra/dump/ 05/22/2018@04:50:50 57 seconds
508G /var/lib/cassandra/dump/ 05/22/2018@04:51:46 56 seconds
509G /var/lib/cassandra/dump/ 05/22/2018@04:52:44 58 seconds
510G /var/lib/cassandra/dump/ 05/22/2018@04:53:41 57 seconds
Bruno Bronosky
la source
0

Vous pouvez créer un script qui le fait pour vous. J'ai appelé le mien keep(comme, continuez à le faire) et l' ai mis sur le binchemin.

Voici mon script:

#!/bin/bash
echo "Repeating command $* every second"
while sleep 1; do
    "$@"
done
Alexandre Santos
la source
1
Vous devez utiliser "$@"pour exécuter la commande (arguments) au lieu de non cité $*. De cette façon, le shell conservera les arguments cités, etc. comme l'utilisateur s'y attendrait. FTFY.
roaima