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

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.


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')"
}

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

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).


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.

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

-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.