marca de tiempo antes de un eco

12

Existe una mejor manera de crear una marca de tiempo frente a un echo?

Actualmente lo hago de esta manera:

#!/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 salida debería verse así:

10:36 usb device already mounted
TaXXoR
fuente

Respuestas:

22

Puede omitir el echo, y simplemente poner el mensaje en el datecomando. datele permite insertar texto en la cadena de formato ( +%Ren su ejemplo). Por ejemplo:

date +"%R usb device already mounted"

También puede incluirlo en una función de shell para mayor comodidad. Por ejemplo:

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

echo_time "usb device already mounted"

Este es un limpiador si lo va a reutilizar muchas veces.

David Baggerman
fuente
66
echo_timehará lo que espera, hasta que su mensaje tenga una %señal en él. No es una solución muy robusta.
derobert
1
@derobert Debido a que la implementación está oculta en una función, echo_timepodría usar la construcción date + echo del OP
Izkata
simplemente cambiaría "$ *" por "$ @" (para acostumbrarme a usar el último)
Olivier Dulac
¿Cómo usar eso en una tubería?
erikbwork
6

Aquí hay una forma más robusta y portátil (POSIX) de hacerlo, particularmente una que permite %permanecer sin procesar como argumento:

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

Puede crear una variable para 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
fuente
3
Esto es bueno porque solo llama a date una vez, en lugar de tres veces.
evilsoup
2
Esto es bueno cuando el script no dura mucho, pero tendrá una fecha incorrecta cuando será más largo.
TaXXoR
4

Con ksh93y versiones recientes de bash:

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

Con zsh:

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

O para evitar una rápida expansión en la "$@"parte:

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

Una forma hacky para versiones anteriores de bash:

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

En realidad, si el punto es hacer:

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

Podrías hacerlo:

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

O para evitar una bifurcación secundaria:

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

Entonces:

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

(tenga en cuenta que estos se repiten en stderr, que en realidad puede ser preferible).

Stéphane Chazelas
fuente
1

Cuando hago cosas como esta, generalmente quiero que todas las líneas (incluida la salida de cualquier programa) tengan una marca de tiempo. Por lo tanto, usaría algo como esto:

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

Como Stephane señala a continuación, los programas individuales pueden amortiguar su salida cuando se envían a una tubería. Por supuesto, estos búferes se enjuagarán cuando el programa salga, por lo que, en el peor de los casos, las marcas de tiempo mostrarán cuándo salió el programa (si amortigua su salida y no imprime lo suficiente para llenar el búfer). Sin embargo, las echomarcas de tiempo serán todas precisas.

Como muestra ejecutable para pruebas:

#!/bin/sh

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

Salida:

[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
fuente
Sin embargo, tenga en cuenta que una vez que la salida se dirige a una tubería, las aplicaciones comienzan a amortiguar su salida, por lo que los tiempos pueden no reflejar la hora en que se imprimieron.
Stéphane Chazelas
2
Sugiero revisar el tscomando que es parte de moreutils. Es un script en perl similar, pero con varias opciones para el formato de fecha y hora, etc.
Derobert
@derobert: ¿por qué no escribes cómo hacer esto usando ts? Parece que sería la mejor opción aquí.
slm
1

Crear marcas de tiempo con ts

instale la herramienta ts(parte del paquete moreutils):

sudo apt-get install moreutils

Agregar una marca de tiempo a una salida:

echo "foo" | ts

salida:

Sep 03 14:51:44 foo
TaXXoR
fuente
-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
iiii
fuente
1
Esto no funcionó cuando lo intenté.
slm
Justo como escribió @slm. Debe proteger la cadena de comandos prematuros y expansiones variables.
manatwork