timestamp prima di un'eco


12

Esiste un modo migliore per creare il timestamp di fronte a un echo?

Attualmente lo faccio in questo modo:

#!/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

L'output dovrebbe essere simile al seguente:

10:36 usb device already mounted

Risposte:


22

È possibile saltare il echoe semplicemente inserire il messaggio nel datecomando. dateti permette di inserire del testo nella stringa di formato ( +%Rnel tuo esempio). Per esempio:

date +"%R usb device already mounted"

Puoi anche lanciarlo in una funzione shell per comodità. Per esempio:

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

echo_time "usb device already mounted"

Questo è un detergente se lo riutilizzerai più volte.


6
echo_timefarà ciò che ti aspetti, fino a quando il tuo messaggio non avrà un %segno. Non è una soluzione molto solida.
derobert,

1
@derobert Poiché l'implementazione è nascosta in una funzione, echo_timepotrebbe semplicemente utilizzare la data del PO + il costrutto echo
Izkata,

cambierei semplicemente "$ *" con "$ @" (per prendere l'abitudine di usare il successivo)
Olivier Dulac,

come usarlo in una pipa?
erikbwork

6

Ecco un modo più robusto e portatile (POSIX) per farlo, in particolare uno che consente %di rimanere non elaborato come argomento:

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

5

Puoi creare una variabile per 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
Questo è bello perché chiama la data solo una volta, anziché tre volte.
evilsoup,

2
È bello quando lo script non dura a lungo, ma avrà una data sbagliata quando sarà più lungo.
TaXXoR,

4

Con ksh93e versioni recenti di bash:

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

Con zsh:

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

O per evitare una rapida espansione nella "$@"parte:

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

Un modo complicato per le versioni precedenti di bash:

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

In realtà, se il punto è fare:

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

Potresti fare:

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

O per evitare il fork di una sub shell:

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

Poi:

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

(nota che quelli fanno eco su stderr, che in realtà potrebbe essere preferibile).


1

Quando faccio cose del genere, di solito desidero che tutte le righe (incluso qualsiasi output del programma) siano timestamp. Quindi, userei qualcosa del genere:

#!/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()."] $_"'

Come Stephane sottolinea di seguito, i singoli programmi possono bufferizzare il loro output quando inviati a una pipe. Naturalmente, questi buffer verranno svuotati quando il programma esce, quindi nel peggiore dei casi i timestamp mostreranno quando il programma è uscito (se bufferizza il suo output e non stampa abbastanza per riempire il buffer). Tuttavia, i echotimestamp saranno tutti precisi.

Come campione eseguibile per il test:

#!/bin/sh

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

Produzione:

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

Tuttavia, notare che una volta che l'output sta per essere inviato a una pipe, le applicazioni iniziano a bufferizzare il loro output, quindi i tempi potrebbero non riflettere il tempo in cui sono stati stampati.
Stéphane Chazelas,

2
Suggerisco di dare un'occhiata al tscomando che fa parte di moreutils. È uno script perl simile, ma con varie opzioni per il formato timestamp, ecc.
derobert

@derobert - perché non scrivi come fare usando ts? Sembra che sarebbe l'opzione migliore qui.
slm

1

Creazione di timestamp con ts

installa lo strumento ts(parte del pacchetto moreutils):

sudo apt-get install moreutils

Aggiunta di un timestamp a un output:

echo "foo" | ts

produzione:

Sep 03 14:51:44 foo

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

1
Questo non ha funzionato quando l'ho appena provato.
slm

Proprio come ha scritto @slm. Devi proteggere la stringa dal comando prematuro e dalle espansioni variabili.
arte
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.