registro de data e hora antes de um eco

12

Existe uma maneira melhor de criar registro de data e hora na frente de um echo?

Atualmente eu faço desta maneira:

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

A saída deve ser algo assim:

10:36 usb device already mounted
TaXXoR
fonte

Respostas:

22

Você pode pular o echoe simplesmente colocar a mensagem no datecomando datepermite inserir texto na string de formato ( +%Rno seu exemplo). Por exemplo:

date +"%R usb device already mounted"

Você também pode jogá-lo em uma função shell por conveniência. Por exemplo:

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

echo_time "usb device already mounted"

Este é um limpador se você for reutilizá-lo várias vezes.

David Baggerman
fonte
6
echo_timefará o que você espera, até que sua mensagem tenha um %sinal. Não é uma solução muito robusta.
precisa saber é
1
@derobert Como a implementação está escondido em uma função, echo_timepoderia usar apenas a data do OP + construção eco
Izkata
Eu tinha acabado de mudar "$ *" por "$ @" (para adquirir o hábito de usar o mais recente)
Olivier Dulac
como usar isso em um cachimbo?
precisa saber é o seguinte
6

Aqui está uma maneira mais robusta e portátil (POSIX) de fazer isso, particularmente uma que permite %permanecer não processada como argumento:

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

Você pode criar uma variável 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
fonte
3
Isso é bom porque chama data apenas uma vez, em vez de três vezes.
precisa saber é
2
Isso é bom quando o script não dura muito, mas terá a data errada quando será mais longo.
TaXXoR 30/08/13
4

Com ksh93e versões recentes de bash:

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

Com zsh:

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

Ou para evitar a rápida expansão da "$@"peça:

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

Uma maneira hacky para versões mais antigas de bash:

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

Na verdade, se o objetivo é fazer:

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

Você poderia fazer:

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

Ou para evitar bifurcar um sub shell:

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

Então:

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

(observe que esses são ecoados no stderr, o que pode ser realmente preferível).

Stéphane Chazelas
fonte
1

Quando faço coisas assim, geralmente quero que todas as linhas (incluindo qualquer saída do programa) sejam marcadas com data e hora. Assim, eu usaria algo como isto:

#!/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 aponta abaixo, programas individuais podem proteger sua saída quando enviados para um tubo. Obviamente, esses buffers serão liberados quando o programa terminar. Na pior das hipóteses, os carimbos de data e hora serão mostrados quando o programa for encerrado (se ele armazenar em buffer sua saída e não imprimir o suficiente para preencher o buffer). No entanto, todos os echoregistros de data e hora serão precisos.

Como uma amostra executável para teste:

#!/bin/sh

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

Resultado:

[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
fonte
No entanto, observe que quando a saída vai para um canal, os aplicativos começam a armazenar buffer em sua saída, portanto, os tempos podem não refletir a hora em que foram impressos.
Stéphane Chazelas
2
Sugiro verificar o tscomando que faz parte do moreutils. É um script perl semelhante, mas com várias opções de formato de timestamp, etc.
derobert
@derobert - por que você não escreve como fazer isso usando ts? Parece que seria a melhor opção aqui.
slm
1

Criando registros de data e hora com ts

instale a ferramenta ts(parte do pacote moreutils):

sudo apt-get install moreutils

Adicionando um registro de data e hora a uma saída:

echo "foo" | ts

resultado:

Sep 03 14:51:44 foo
TaXXoR
fonte
-1
alias echo="d=$(date +%Y-%m-%d); echo $d "
echo hola
iiii
fonte
1
Isso não funcionou quando eu apenas tentei.
slm
Assim como @slm escreveu. Você precisa proteger a string de comandos prematuros e expansões variáveis.
manatwork