स्क्रिप्ट लॉग इन करने के लिए टाइमस्टैम्प कैसे जोड़ें?


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 के लिए लॉगिंग का एक व्यापक कार्यान्वयन है: 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 (बैश के आंतरिक क्षेत्र विभाजक, मूल रूप से व्हाट्सएप पात्रों की एक सूची) को readकमांड के लिए खाली करने के लिए सेट करता है ।
गॉर्डन डेविसन

2
... और -आर-वर्ण "\" से बच जाता है। यह वास्तव में सभी मामलों में काम करना चाहिए - स्क्रिप्टिंग के महान रस।
नेल्स

7
@ नील यह पूरी तरह से बुलेटप्रूफ नहीं है, क्योंकि echoव्याख्या के कुछ कार्यान्वयन से बचना क्रम है। यदि आप वास्तव में चाहते हैं कि यह सामग्री (तारीखों को जोड़ने के अलावा) के साथ खिलवाड़ न करे, तो echoकमांड को बदल देंprintf "%s %s\n" "$(date)" "$line"
गॉर्डन डेविसन

4
आपको ISO-8601 अनुरूप तिथि / टाइमस्टैम्प पर रुचि हो सकती है : date -u +"%Y-%m-%dT%H:%M:%SZ"या शायद अधिक सुंदर date +"%Y-%m-%d %T"
पाब्लो ए

1
हालांकि यह स्क्रिप्ट अपेक्षित रूप से काम करती है, यह प्रत्येक लॉग लाइन के dateलिए एक नई प्रक्रिया (निष्पादित ) करती है , जो आपकी मशीन और लॉग की मात्रा के आधार पर एक बड़ी खामी हो सकती है। मैं इसके बजाय tsयदि उपलब्ध हो तो उपयोग करने का सुझाव दूंगा, @willem से जवाब देखें
माइकल

56

tsउबंटू 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"

क्या आप चाहते हैं?


दिनांक कमांड का उपयोग करना मेरे मन में था, लेकिन मैं वास्तव में इसे स्क्रिप्ट में नहीं जोड़ सकता, इसलिए मैं जो खोज रहा हूं वह इस पंक्ति को बदलने का एक तरीका है: "script.sh >> / var / लॉग / लॉगफ़ाइल "तारीख को जोड़ने के लिए।
एंटोनियस बलोच

उस स्थिति में आपकी स्क्रिप्ट के आउटपुट को नामांकित पाइप पर पुनर्निर्देशित करें और आउटपुट के लिए एक डीमन सुन रहे हैं जो स्क्रिप्ट आउटपुट को लेता है और इसे लॉग फ़ाइल में लिखने से पहले एक तारीख जोड़ता है। ऐसा करने के लिए आप शायद मेरे द्वारा लिखी गई स्क्रिप्ट को संशोधित कर सकते हैं । मैं इसे करूंगा क्योंकि यह मुझे दिलचस्पी देता है लेकिन ब्रिटेन में देर हो चुकी है और कल मेरी शुरुआती शुरुआत है।
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]$ 

हम्म मेरे लिए काम नहीं कर रहा है।
एंटोनियस बलोच

जब आप कमांड निष्पादित करते हैं तो आप क्या प्राप्त कर रहे हैं?
स्पार्क्स

8
वह '' ./script.sh '' के संपूर्ण आउटपुट से पहले टाइमस्टैम्प लगाता है, प्रत्येक पंक्ति से पहले नहीं।
क्लैक

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 '' एक बार '' तारीख '' एक बार '' स्रोत ... / config.sh '' पर चलेगा।
15

5

आपका मतलब है जैसे:

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

मेरे भगवान, लोग, हर कोई टिक रिप्लेसमेंट कर रहा है, जिसका नाम पाइप है, इत्यादि। बस दोनों की तारीख और कमांड को स्क्रिप्ट में शामिल करें! जिस व्यक्ति के पास फ़ंक्शन है, उसके पास एक कानूनी मामला है यदि मल्टी-लाइन आउटपुट है और लॉग को हर पंक्ति पर तारीख के साथ सुंदर दिखने की आवश्यकता है, लेकिन इनमें से अधिकांश समाधान ओवरकिल हैं जो शेल शब्दार्थ का उपयोग नहीं करते हैं।
cjc

8
वह केवल निष्पादन के समय ही टाइमस्टैम्प को जोड़ देगा script.sh। ओपी को प्रति लाइन टाइमस्टैंप चाहिए।
डेव फ़ोरगैक

1
हालाँकि यह ओपी प्रश्न का उत्तर नहीं देता है फिर भी मुझे यह उपयोगी जानकारी मिली।
उपयोगकर्ता

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उबंटू में प्रति सेकंड लगभग 50 लाइनों की अनुमति देने की प्रक्रिया शुरू होने के ओवरहेड के साथ , और केवल 10 के बारे में -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

आप ध्यान दें कि जाग तेजी से भाग सकता है,

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 -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) /"सेड से पहले एक बार बैश का मूल्यांकन करने और चलाने की तारीख है। सेड को स्टैटिक स्ट्रिंग पास की जाती है।
इवान बेन

प्लेन बैश: yes | head -5000000 | while read line; do echo $((SECONDS)); done | uniq -cजो गॉक की तुलना में बहुत धीमा है। tsउपयोगिता में बैश लूप के समान प्रदर्शन है।
अखाड़ा

पर्ल: yes |head -5000000 |perl -ne 'print localtime."\t".$_' |uniq -cजो जाग से थोड़ा धीमा है।
अक्खन

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

अन्य उत्तर के रूप में, यह सिर्फ एक बार चलने की तारीख है। sed प्रति पंक्ति समय को अपडेट नहीं कर रहा है।
इवान बीन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.