horodatage avant un écho

12

Existe une meilleure façon de créer un horodatage devant un echo?

Actuellement, je le fais de cette façon:

#!/bin/sh

if mount | grep -q /mnt/usb; then
        echo `date +%R\ ` "usb device already mounted"
else
        echo `date +%R\ ` "mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
                echo `date +%R\ ` "usb device successfully mounted"
        fi
fi

La sortie devrait ressembler à quelque chose comme ça:

10:36 usb device already mounted
TaXXoR
la source

Réponses:

22

Vous pouvez ignorer le echo, et simplement mettre le message dans la datecommande. datevous permet d'insérer du texte dans la chaîne de formatage ( +%Rdans votre exemple). Par exemple:

date +"%R usb device already mounted"

Vous pouvez également le jeter dans une fonction shell pour plus de commodité. Par exemple:

echo_time() {
    date +"%R $*"
}

echo_time "usb device already mounted"

C'est un nettoyant si vous comptez le réutiliser plusieurs fois.

David Baggerman
la source
6
echo_timefera ce que vous attendez, jusqu'à ce que votre message soit %signé. Pas une solution très robuste.
derobert
1
@derobert Parce que l'implémentation est cachée dans une fonction, echo_timepourrait simplement utiliser la construction date + echo de l'OP
Izkata
je voudrais juste changer "$ *" par "$ @" (pour prendre l'habitude d'utiliser ce dernier)
Olivier Dulac
comment l'utiliser dans une pipe?
erikbwork
6

Voici un moyen plus robuste et portable (POSIX) de le faire, en particulier celui qui permet %de rester non traité comme argument:

echo_time() {
    date +"%H:%M $(printf "%s " "$@" | sed 's/%/%%/g')"
}
jlliagre
la source
5

Vous pouvez créer une variable pour date +%R:

#!/bin/sh

T=$(date +%R)

if mount | grep -q /mnt/usb; then
        echo "$T usb device already mounted"
else
        echo "$T mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
                echo "$T usb device successfully mounted"
        fi
fi
Radu Rădeanu
la source
3
C'est bien car il n'appelle la date qu'une fois, plutôt que trois fois.
evilsoup
2
C'est bien quand le script ne dure pas longtemps, mais il aura une mauvaise date quand il sera plus long.
TaXXoR
4

Avec ksh93et versions récentes de bash:

ts_echo() {
  printf '%(%R)T: %s\n' -1 "$*"
}

Avec zsh:

ts_echo() print -P %T: "$@"

Ou pour éviter une expansion rapide de la "$@"pièce:

ts_echo() echo ${(%):-%T}: "$@"

Un moyen hacky pour les anciennes versions de bash:

ts_echo() (
  PS4="\A"
  set -x; : "$@"
)

En fait, si le but est de le faire:

echo "<timestamp>: doing cmd args..."
cmd args...

Vous pourriez faire:

ts() (
  PS4='\A: doing '
  set -x; "$@"
)
ts cmd args...

Ou pour éviter de bifurquer un sous-shell:

ts() {
  local PS4='\A: doing ' ret
  set -x; "$@"
  { ret=$?; set +x; } 2> /dev/null
  return "$ret"
}

Puis:

$ ts echo whatever
14:32: doing echo whatever
whatever

(notez que ceux-ci sont répercutés sur stderr, ce qui peut en fait être préférable).

Stéphane Chazelas
la source
1

Quand je fais des choses comme ça, je veux généralement que toutes les lignes (y compris toute sortie de programme) soient horodatées. Ainsi, j'utiliserais quelque chose comme ceci:

#!/bin/sh

(
    if mount | grep -q /mnt/usb; then
        echo "usb device already mounted"
    else
        echo "mounting usb device..."
        mount -t msdosfs /dev/da0s1 /mnt/usb

        if mount | grep -q /mnt/usb; then
            echo "usb device successfully mounted"
        fi
    fi
) 2>&1 | perl -ne 'print "[".localtime()."] $_"'

Comme Stephane le souligne ci-dessous, les programmes individuels peuvent tamponner leur sortie lorsqu'ils sont envoyés à un tuyau. Bien sûr, ces tampons seront vidés à la sortie du programme, donc au pire les horodatages s'afficheront à la sortie du programme (s'il tamponne sa sortie et n'imprime pas suffisamment pour remplir le tampon). Cependant, les echohorodatages seront tous précis.

En tant qu'échantillon exécutable pour les tests:

#!/bin/sh

(
    echo "Doing something"
    sleep 5
    echo "Doing something else..."
    ls /some/file
    sleep 8
    echo "Done."
) 2>&1 | perl -ne 'print "[".localtime()."] $_"'

Production:

[Thu Aug 29 07:32:37 2013] Doing something
[Thu Aug 29 07:32:42 2013] Doing something else...
[Thu Aug 29 07:32:42 2013] ls: cannot access /some/file: No such file or directory
[Thu Aug 29 07:32:50 2013] Done.
Dean Serenevy
la source
Cependant, notez qu'une fois la sortie envoyée vers un canal, les applications commencent à mettre en mémoire tampon leur sortie, de sorte que les synchronisations peuvent ne pas refléter l'heure à laquelle elles ont été imprimées.
Stéphane Chazelas
2
Je suggère de vérifier la tscommande qui fait partie de moreutils. C'est un script perl similaire, mais avec diverses options pour le format d'horodatage, etc.
derobert
@derobert - pourquoi n'écrivez-vous pas comment faire cela en utilisant ts? Il semble que ce serait la meilleure option ici.
slm
1

Création d'horodatages avec ts

installer l'outil ts(partie du package moreutils):

sudo apt-get install moreutils

Ajout d'un horodatage à une sortie:

echo "foo" | ts

production:

Sep 03 14:51:44 foo
TaXXoR
la source
-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
iiii
la source
1
Cela n'a pas fonctionné quand je l'ai essayé.
slm
Tout comme @slm l'a écrit. Vous devez protéger la chaîne des commandes prématurées et des extensions de variables.
manatwork