タイムスタンプをbashスクリプトログに追加する方法は?


94

私はログファイルに出力するスクリプトを常に実行しています:

script.sh >> /var/log/logfile

ログに追加される各行の前にタイムスタンプを追加したいと思います。好む:

Sat Sep 10 21:33:06 UTC 2011 The server has booted up.  Hmmph.

使用できる柔術はありますか?


2
このクエストをご覧ください。 serverfault.com/questions/80749/...。ここでいくつかの答えが当てはまります。
ゾレダチェ

AWK / gawkのソリューションを参照してください。stackoverflow.com/questions/21564/...
ユーザー

bashのロギングの包括的な実装を次に示し
codeforester

回答:


88

スクリプトの出力を、現在の日付と時刻の前に付けるループを介してパイプできます。

./script.sh | while IFS= read -r line; do printf '%s %s\n' "$(date)" "$line"; done >>/var/log/logfile

これを頻繁に使用する場合、ループを処理するbash関数を簡単に作成できます。

adddate() {
    while IFS= read -r line; do
        printf '%s %s\n' "$(date)" "$line";
    done
}

./thisscript.sh | adddate >>/var/log/logfile
./thatscript.sh | adddate >>/var/log/logfile
./theotherscript.sh | adddate >>/var/log/logfile

3
@Nils readは、行頭と行頭の空白を切り取らないようにするのがコツです。readコマンドに対してIFS(bashの内部フィールド区切り、基本的には空白文字のリスト)を空に設定します。
ゴードンデイヴィソン

2
...および-rは、エスケープ文字「\」を無視します。これは、すべての場合に実際に機能するはずです-スクリプト作成の大物。
ニルス

7
@Nilsは、完全な防弾ではありませんecho。エスケープシーケンスを解釈する実装がいくつかあるためです。あなたがいる場合、実際にはない(日付を追加すること以外の)コンテンツを台無しにそれをしたい、置き換えechoてコマンドをprintf "%s %s\n" "$(date)" "$line"
ゴードンDavisson

4
ISO-8601準拠の日付/タイムスタンプに興味があるdate -u +"%Y-%m-%dT%H:%M:%SZ"かもしれませんdate +"%Y-%m-%d %T"
パブロA

1
このスクリプトは期待どおりに動作しますが、ログ行ごとに新しいプロセス(実行date)を生成します。これは、マシンとログの量によっては大きな欠点になる可能性があります。可能であれば使用することをお勧めします。@ willemからの回答を参照してくださいts
Michael Schaefers

56

tsUbuntu moreutilsパッケージから参照してください。

command | ts

または、$command自動バッファリングを行う場合(expect-devパッケージが必要):

unbuffer command | ts

18

日付のコマンドは、その情報を提供します

date -u
Sat Sep 10 22:39:24 UTC 2011

だからあなたはできる

echo $(date -u) "Some message or other"

それはあなたが欲しかったことですか?


dateコマンドの使用は、私が念頭に置いていたものの1つですが、スクリプト自体に実際に追加することはできません。したがって、私が探しているのは、次の行を変更する方法です。 log / logfile」を使用して日付を追加します。
アントニウスブロッホ

その場合、スクリプトの出力を名前付きパイプにリダイレクトし、スクリプト出力を取得してログファイルに書き込む前に日付を追加する出力をリスニングするデーモンを用意します。これを行うために、ここで書いスクリプトをおそらく変更することができます。興味があるのでやりますが、イギリスでは遅く、明日は早いスタートです。
user9517

12

コマンド出力をログファイルにエコーするだけです。すなわち、

echo "`date -u` `./script.sh`" >> /var/log/logfile

それは実際に動作します :)

例:

[sparx@E1]$ ./script.sh 
Hello Worldy
[sparx@E1]$ echo "`date -u` `./script.sh`" >> logfile.txt
[sparx@E1]$ cat logfile.txt 
Mon Sep 12 20:18:28 UTC 2011 Hello Worldy
[sparx@E1]$ 

うーん、私のために働いていません。
アントニウスブロッホ

コマンドを実行すると何が得られますか?
SparX

8
これにより、各行の前ではなく、 ''。/ script.sh ''の出力全体の前にタイムスタンプが追加されます。
15年

8

作成しconfig.shたファイルを

#!/usr/bin/env bash
LOGFILE="/path/to/log.log"
TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`

ログファイルに送信する必要がある場合

#!/usr/bin/env bash
source /path/to/config.sh

echo "$TIMESTAMP Say what you are doing" >> $LOGFILE

do_what_you_want >> $LOGFILE

ログファイルは次のようになります

2013-02-03 18:22:30 Say what you are doing

日付で並べ替えるのは簡単です


8
'' config.sh ''は、 '' source ... / config.sh ''で '' date ''を一度だけ実行します。
15年

5

あなたは次のような意味です:

(date && script.sh) >> /var/log/logfile

私の神、人々、誰もがバックティック置換、名前付きパイプなどをしています。日付コマンドとスクリプトの両方を括弧で囲んでください!関数を持っている人は、複数行の出力があり、ログがすべての行の日付をきれいにする必要がある場合に正当なケースを持っていますが、これらのソリューションのほとんどはシェルセマンティクスを使用しない過剰です。
CJC

8
タイムスタンプは、の実行ごとに1回だけ追加されscript.shます。OPでは、行ごとにタイムスタンプが必要です。
デイブForgac

1
これはOPの質問には答えませんが、それでも有用な情報が見つかりました。
ユーザー

4

これを試して

timestamp()
{
 date +"%Y-%m-%d %T"
}

すべてのエコーコマンドでこのタイムスタンプ関数を呼び出します。

echo "$(timestamp): write your log here" >> /var/log/<logfile>.log

@ shazbot:編集してくれてありがとう、それはタイプミスでした。
サンジェイヤダブ

4

多くの行を処理する必要がある場合、受け入れられた回答https://serverfault.com/a/310104は少し遅くなります。プロセスを開始するオーバーヘッドによりdate、Ubuntuでは1秒あたり約50行、わずか約10行Cygwinで-20。

ときは、bashより高速な代替だろうと想定することができprintf、その持つ組み込み%(...)T書式指定子。比較する

>> while true; do date; done | uniq -c
     47 Wed Nov  9 23:17:18 STD 2016
     56 Wed Nov  9 23:17:19 STD 2016
     55 Wed Nov  9 23:17:20 STD 2016
     51 Wed Nov  9 23:17:21 STD 2016
     50 Wed Nov  9 23:17:22 STD 2016

>> while true; do printf '%(%F %T)T\n'; done | uniq -c
  20300 2016-11-09 23:17:56
  31767 2016-11-09 23:17:57
  32109 2016-11-09 23:17:58
  31036 2016-11-09 23:17:59
  30714 2016-11-09 23:18:00

1

awkは高速で実行されることに注意してください。

gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }'

yes |head -5000000 |gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }' |uniq -c
 461592 [2017-02-28 19:46:44] y
 488555 [2017-02-28 19:46:45] y
 491205 [2017-02-28 19:46:46] y
 498568 [2017-02-28 19:46:47] y
 502605 [2017-02-28 19:46:48] y
 494048 [2017-02-28 19:46:49] y
 493299 [2017-02-28 19:46:50] y
 498005 [2017-02-28 19:46:51] y
 502916 [2017-02-28 19:46:52] y
 495550 [2017-02-28 19:46:53] y
  73657 [2017-02-28 19:46:54] y

しかし、sedははるかに高速に実行され、

sed -e "s/^/$(date -R) /"

yes |head -5000000 |sed -e "s/^/$(date -R) /" |uniq -c
5000000 Tue, 28 Feb 2017 19:57:00 -0500 y

ただし、詳細な検査では、セットは時間を変更しないようです。

vmstat 1 | sed -e "s/^/$(date -R) /"

1
これは、"s/^/$(date -R) /"sedの前に日付を1回評価して実行するbashであるためです。Sedには静的な文字列が渡されます。
エヴァン・ベン

プレーンbash:yes | head -5000000 | while read line; do echo $((SECONDS)); done | uniq -cgawkよりもはるかに遅いです。tsユーティリティは、bashループと同様のパフォーマンスを発揮します。
akhan

Perl:yes |head -5000000 |perl -ne 'print localtime."\t".$_' |uniq -cawkよりも少し遅いです。
akhan

1

以下は私のログファイルの内容です

xiongyu@ubuntu:~/search_start_sh$ tail restart_scrape.log 

2017-08-25 21:10:09 scrape_yy_news_main.py got down, now I will restart it

2017-08-25 21:10:09 check_yy_news_warn.py got down, now I will restart it

2017-08-25 21:14:53 scrape_yy_news_main.py got down, now I will restart it

シェルの内容の一部は以下のとおりです

log_file="restart_scrape.log"
TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
echo "$TIMESTAMP $search_py_file got down, now I will restart it" | tee -a $log_file 

1

このスクリプトは、出力を端末に出力し、ログファイルにも保存します。

#!/bin/bash

MY_LOG=/var/log/output.log

echolog(){
    if [ $# -eq 0 ]
    then cat - | while read -r message
        do
                echo "$(date +"[%F %T %Z] -") $message" | tee -a $MY_LOG
            done
    else
        echo -n "$(date +'[%F %T %Z]') - " | tee -a $MY_LOG
        echo $* | tee -a $MY_LOG
    fi
}

echolog "My script is starting"
whoami | echolog

サンプル出力:

[2017-10-29 19:46:36 UTC] - My script is starting
[2017-10-29 19:46:36 UTC] - root

最初の日付コマンドでは、二重引用符ではなく単一引用符を使用する必要があります。
ジェイソンハリソン

1

別のオプションは、コードでデータを出力するたびに呼び出す関数をセットアップすることです。

PrintLog(){
  information=$1
  logFile=$2
  echo "$(date +'%Y-%m-%d %H:%M:%S" $information} >> $logFile
}

その後、コード内でログファイル呼び出しに送信するたびに

PrintLog "Stuff you want to add..." ${LogFileVariable}

簡単に...


0

「sed」をパイプします。

script.sh | sed "s|^|$('date') :: |" >> /var/log/logfile

他の答えについては、これは1回のbash実行日です。sedは行ごとの時間を更新していません。
エヴァンベン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.