วิธีเพิ่มการประทับเวลาเพื่อบันทึกสคริปต์ทุบตี?


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/… . คำตอบสองสามข้อจะนำไปใช้ที่นี่
Zoredache

สำหรับวิธีแก้ปัญหา awk / gawk ดูได้ที่: stackoverflow.com/questions/21564/…
ผู้ใช้

นี่คือการดำเนินการที่ครอบคลุมของการบันทึกสำหรับ bash: github.com/codeforester/base/blob/master/lib/stdlib.sh
codeforester

คำตอบ:


88

คุณสามารถไพพ์เอาท์พุทของสคริปต์ผ่านลูปที่นำหน้าวันที่และเวลาปัจจุบัน:

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

หากคุณกำลังใช้งานสิ่งนี้มากมันเป็นเรื่องง่ายที่จะสร้างฟังก์ชั่นทุบตีเพื่อจัดการวง:

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
@ ไม่มีมันเป็นเคล็ดลับในการป้องกันการreadตัดช่องว่างที่จุดเริ่มต้นและและของบรรทัด ตั้งค่า IFS (ตัวคั่นเขตข้อมูลภายในของ bash โดยทั่วไปคือรายการของอักขระช่องว่าง) เป็นค่าว่างสำหรับreadคำสั่ง
Gordon Davisson

2
... และ -r จะละเว้นอักขระการยกเว้น "\" สิ่งนี้ควรใช้งานได้จริงในทุกกรณี - ส่วนใหญ่ของการเขียนสคริปต์
นิลส์

7
@ ไม่มีสิ่งที่ไม่สามารถป้องกันได้อย่างสมบูรณ์เนื่องจากการใช้งานบางอย่างของechoการตีความลำดับหนี หากคุณไม่ต้องการยุ่งกับเนื้อหา (นอกเหนือจากการเพิ่มวันที่) ให้แทนที่echoคำสั่งด้วยprintf "%s %s\n" "$(date)" "$line"
Gordon Davisson

4
คุณอาจสนใจวันที่ / เวลามาตรฐานที่สอดคล้องกับ ISO-8601date -u +"%Y-%m-%dT%H:%M:%SZ"หรือมากกว่าdate +"%Y-%m-%d %T"นั้น
Pablo

1
ในขณะที่สคริปต์นี้ทำงานได้ตามที่คาดไว้มันจะสร้างกระบวนการใหม่ (ดำเนินการdate) สำหรับแต่ละบรรทัดบันทึกซึ่งอาจเป็นข้อเสียเปรียบอย่างมากขึ้นอยู่กับเครื่องของคุณและจำนวนบันทึก ฉันอยากจะแนะนำให้ใช้tsถ้ามีให้ดูคำตอบจาก @willem
Michael Schaefers

56

ดูtsจากmoreutilsแพ็คเกจUbuntu :

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 นั้นเป็นสิ่งที่ฉันนึกไว้ แต่ฉันไม่สามารถเพิ่มมันลงในสคริปต์ได้ดังนั้นสิ่งที่ฉันกำลังมองหาคือวิธีเปลี่ยนบรรทัดนี้: "script.sh >> / var / log / logfile "เพื่อผนวกวันที่
Antonius Bloch

ในกรณีนั้นเปลี่ยนทิศทางเอาต์พุตของสคริปต์ของคุณไปยังไพพ์ที่มีชื่อและมี daemon คอยฟังเอาต์พุตซึ่งใช้เอาต์พุตสคริปต์และเพิ่มวันที่ก่อนที่จะเขียนลงในล็อกไฟล์ คุณอาจแก้ไขสคริปต์ที่ฉันเขียนที่นี่เพื่อทำสิ่งนี้ ฉันจะทำเพราะสนใจฉัน แต่มันสายในสหราชอาณาจักรและฉันจะเริ่มในวันพรุ่งนี้
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]$ 

อืมฉันไม่ได้ทำงาน
Antonius Bloch

คุณจะได้อะไรเมื่อคุณรันคำสั่ง
SparX

8
ที่ทำให้การประทับเวลาก่อนที่จะส่งออกทั้งหมดของ '' ./script.sh '' ไม่ใช่ก่อนแต่ละบรรทัด
clacke

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 '' ของคุณจะทำงาน '' date '' เพียงครั้งเดียวใน '' source ... / config.sh ''
clacke

5

คุณหมายถึงชอบ:

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

พระเจ้าผู้คนทุกคนกำลังทำหน้าที่แทนเห็บแทนชื่อไพพ์ ฯลฯ เพียงแค่ใส่ทั้งวันที่และคำสั่งในสคริปต์! ผู้ชายที่มีฟังก์ชั่นนั้นมีกรณีที่ถูกต้องถ้ามีเอาต์พุตหลายบรรทัดและบันทึกต้องดูสวยในวันที่ทุกบรรทัด แต่โซลูชันเหล่านี้ส่วนใหญ่เป็นแบบ overkill ที่ไม่ได้ใช้ซีแมนทิกส์เชลล์
cjc

8
script.shที่จะเพิ่มการประทับเวลาหนึ่งครั้งต่อการดำเนินการของ OP ต้องการการประทับเวลาต่อบรรทัด
Dave Forgac

1
แม้ว่าสิ่งนี้จะไม่ตอบคำถาม OP แต่ฉันก็ยังพบข้อมูลที่เป็นประโยชน์
ผู้ใช้

4

ลองสิ่งนี้

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

เรียกใช้ฟังก์ชันการประทับเวลานี้ในทุกคำสั่ง echo:

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

@ shazbot: ขอบคุณสำหรับการแก้ไขนั่นเป็นข้อผิดพลาดที่พิมพ์ผิดฉันไม่ได้สังเกต
Sanjay Yadav

4

คำตอบที่ได้รับการยอมรับhttps://serverfault.com/a/310104อาจช้านิดหน่อยหากต้องประมวลผลหลายบรรทัดโดยมีค่าใช้จ่ายในการเริ่มต้นdateกระบวนการที่ให้ประมาณ 50 บรรทัดต่อวินาทีใน Ubuntu และประมาณ 10 เท่านั้น -20 ใน Cygwin

เมื่อbashสามารถสันนิษฐานได้ว่าเป็นทางเลือกที่เร็วกว่าจะเป็นprintfbuiltin พร้อมตัว%(...)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 Sed ถูกส่งผ่านสตริงแบบสแตติก
Evan Benn

ธรรมดาทุบตี: yes | head -5000000 | while read line; do echo $((SECONDS)); done | uniq -cซึ่งช้ากว่าเพ่งพิศ tsยูทิลิตี้มีประสิทธิภาพที่คล้ายกันเป็นห่วง bash
akhan

Perl: yes |head -5000000 |perl -ne 'print localtime."\t".$_' |uniq -cซึ่งช้ากว่า awk เล็กน้อย
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

คำสั่ง date แรกของคุณควรใช้เครื่องหมายคำพูดเดี่ยวไม่ใช่เครื่องหมายคำพูดคู่
Jason Harrison

1

อีกทางเลือกหนึ่งคือการตั้งค่าฟังก์ชั่นการโทรทุกครั้งที่คุณต้องการส่งออกข้อมูลในรหัสของคุณ:

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

จากนั้นทุกครั้งในรหัสของคุณที่คุณต้องการส่งไปยังไฟล์บันทึกการโทร

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

peasy ง่าย ....


0

ไปป์ "sed":

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

สำหรับคำตอบอื่น ๆ นี่เป็นเพียงการทุบตีวันที่ทำงานเพียงครั้งเดียว sed ไม่ได้อัปเดตเวลาต่อบรรทัด
Evan Benn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.