आप लॉग फ़ाइल की केवल अंतिम n लाइनें कैसे रखते हैं?


18

एक स्क्रिप्ट जो मैंने लिखी है वह कुछ करती है और अंत में, कुछ पंक्तियों को अपने लॉगफाइल में जोड़ देती है। मैं लॉगफ़ाइल की केवल अंतिम n लाइनें (कहना, 1000 लाइनें) रखना चाहूंगा। यह स्क्रिप्ट के अंत में इस तरह से किया जा सकता है:

tail -n 1000 myscript.log > myscript.log.tmp
mv -f myscript.log.tmp myscript.log

लेकिन वहाँ एक और अधिक स्वच्छ और सुंदर समाधान है? शायद एक ही आदेश के माध्यम से पूरा किया?


logrotateसुरुचिपूर्ण समाधान है
इपोर सिरकार

1
मैंने इसके बारे में सोचा है, लेकिन लॉगरेट कॉन्फ़िगरेशन स्क्रिप्ट से अधिक लंबा होगा ...
dr01

यदि लॉगरोट ओवरकिल है, तो आपका समाधान लगभग उतना ही सुंदर है जितना इसे प्राप्त होता है। Sed / awk के साथ आप इसे एक पंक्ति में करने में सक्षम हो सकते हैं लेकिन आंतरिक रूप से बिना किसी अस्थायी फ़ाइल के नहीं, इसलिए यह संभवतः अधिक कुशल और शायद कम पठनीय नहीं है।
kba

जवाबों:


28

यह इस तरह संभव है, लेकिन जैसा कि दूसरों ने कहा है, सबसे सुरक्षित विकल्प एक नई फ़ाइल की पीढ़ी है और फिर मूल को अधिलेखित करने के लिए उस फ़ाइल का एक कदम है।

नीचे दी गई विधि BASH में लाइनों को लोड करती है, इसलिए tailलॉग लाइनों की सामग्री को संग्रहीत करने के लिए स्थानीय शेल के मेमोरी उपयोग को प्रभावित करने वाली लाइनों की संख्या के आधार पर ।

नीचे भी खाली लाइनों को हटा दिया जाना चाहिए, जो लॉग फ़ाइल के अंत में मौजूद हैं (BASH मूल्यांकन के व्यवहार के कारण "$(tail -1000 test.log)") इसलिए सभी परिदृश्यों में वास्तव में 100% सटीक ट्रंकेशन नहीं देता है, लेकिन आपकी स्थिति के आधार पर, पर्याप्त हो सकता है।

$ wc -l myscript.log
475494 myscript.log

$ echo "$(tail -1000 myscript.log)" > myscript.log

$ wc -l myscript.log
1000 myscript.log

होशियार। मैंने इसे स्वीकृत उत्तर के रूप में चिह्नित किया है क्योंकि इसमें अतिरिक्त उपकरणों की स्थापना की आवश्यकता नहीं है। मेरी इच्छा है कि मैं तुम्हारा और जॉन १०२४ का उत्तर दोनों स्वीकार कर सकूं।
dr01

तुम्हारा फोन। मैंने स्पंज के घोल को उखाड़ दिया क्योंकि मुझे इसके बारे में जानकारी नहीं थी और इसे खाली लॉग लाइनों के साथ गड़बड़ नहीं करने की गारंटी है। इस समाधान में लॉग फाइल सामग्री के आधार पर ऐसा करने की क्षमता है।
पार्कमार्क

इस समाधान में एक दौड़ की स्थिति है। यदि आप अशुभ हैं, तो रीडायरेक्ट -इन्टो- फाइल पढ़ने से पहले होता है -फ्रॉम- फाइल और आप एक खाली फाइल के साथ समाप्त होते हैं।
कोरोन्स

21

उपयोगिता spongeकेवल इस मामले के लिए डिज़ाइन की गई है। यदि आपने इसे स्थापित किया है, तो आपकी दो पंक्तियाँ लिखी जा सकती हैं:

tail -n 1000 myscript.log | sponge myscript.log

आम तौर पर, एक फ़ाइल से उसी समय पढ़ना जो आप इसे लिख रहे हैं, अविश्वसनीय है। spongeइसे myscript.logतब तक नहीं लिखता है जब तक कि tailइसे पढ़ना समाप्त न हो जाए और पाइप समाप्त न हो जाए।

इंस्टॉल

spongeडेबियन जैसी प्रणाली को स्थापित करने के लिए :

apt-get install moreutils

spongeRHEL / CentOS सिस्टम पर स्थापित करने के लिए, EPEL रेपो जोड़ें और फिर करें:

yum install moreutils

प्रलेखन

से man sponge:

spongeमानक इनपुट पढ़ता है और इसे निर्दिष्ट फ़ाइल पर लिखता है। शेल पुनर्निर्देशित के विपरीत, spongeआउटपुट फ़ाइल लिखने से पहले अपने सभी इनपुट को भिगो देता है। यह उन पाइपलाइनों का निर्माण करने की अनुमति देता है जो उसी फ़ाइल से पढ़ते हैं और लिखते हैं।


2
+1 धन्यवाद, मुझे नहीं पता था sponge। उन सभी लोगों के लिए बहुत उपयोगी है, जो कठिन तरीके से सीखते हैं जो आप नहीं कर सकते sort importantfile.txt > importantfile.txt:)
dr01

4

निश्चित रूप से "पूंछ + एमवी" ज्यादा बेहतर है! लेकिन ग्नू सेड के लिए हम कोशिश कर सकते हैं

sed -i -e :a -e '$q;N;101,$D;ba' log

3

रिकॉर्ड के लिए, edआप कुछ ऐसा कर सकते हैं

ed -s infile <<\IN
0r !tail -n 1000 infile
+1,$d
,p
q
IN

यह (यानी यह पहली पंक्ति से पहले उस आउटपुट को सम्मिलित करता है) के उत्पादन में खुलता है infileऔर rइप्स tail -n 1000 infileकरता है और फिर शुरू में फ़ाइल के अंत तक पहली पंक्ति से हटा दें। फ़ाइल को जगह में संपादित करने के ,pसाथ बदलें w
हालांकि ध्यान रखें कि edसमाधान बड़ी फ़ाइलों के लिए उपयुक्त नहीं हैं।


0

आप अपनी स्क्रिप्ट में क्या कर सकते हैं लॉग लॉग के तर्क को लागू करें। एक फ़ंक्शन के माध्यम से सभी लॉगिंग करें:

log()
{
   ...
}

यह कार्य, सबसे पहले, कुछ इस तरह करता है:

printf "%s\n" "$*" >> logfile

फिर, यह फ़ाइल के आकार की जाँच करता है या किसी तरह यह तय करता है कि फ़ाइल को रोटेशन की आवश्यकता है। उस बिंदु पर, फ़ाइल logfile.1, यदि वह मौजूद है, तो उसे हटा दिया जाता है, फ़ाइल logfile.0, यदि वह मौजूद है, तो उसका नाम बदल दिया जाता है logfile.1और logfileउसका नाम बदल दिया जाता है logfile.0

यह तय करना कि क्या घूमना स्क्रिप्ट में बनाए गए काउंटर पर आधारित हो सकता है। जब यह 1000 हिट करता है, तो यह शून्य पर रीसेट हो जाता है।

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

या आप आकार प्राप्त कर सकते हैं, जैसे कि wc -c logfileएक निश्चित आकार से अधिक के आधार पर रोटेशन के साथ । इस तरह से स्थिति को निर्धारित करने के लिए फ़ाइल को कभी स्कैन नहीं करना पड़ता है।


0

मैंने इसके बजाय mv, cpयह हासिल करने के लिए कमांड का उपयोग किया था कि आप उस जगह पर कुछ लॉगफाइल्स करने में सक्षम हैं जहां एक सॉफ्टवेयर चल रहा है। हो सकता है कि अलग-अलग उपयोगकर्ता होम डिर या ऐप डायर में हों और हार्डलिंक के रूप में सभी जगह एक ही हो। यदि आप mvकमांड का उपयोग करते हैं तो आप हार्ड लिंक खो देते हैं। यदि आप cpइसके बजाय कमांड का उपयोग करते हैं तो आप इस हार्ड लिंक को रखेंगे।

मेरा कोड कुछ इस तरह है:

TMP_FILE="$(mktemp "${TMPFILENAME}.XXX")"

for FILE in "${LOGFILE_DIR}"/* ; do
    tail -n $MAXLINES "${FILE}" > "${TMP_FILE}"
    if [ $(ls -g "${TMP_FILE}" | awk '{print $4}') -lt $(ls -g "${FILE}" | awk '{print $4}') ] ; then
        cp "${TMP_FILE}" "${FILE}"
    fi
done   

इसलिए यदि फाइलें एक ही फाइल सिस्टम पर हैं तो आप उपयोगकर्ताओं को और कुछ अलग अधिकारों को दे सकते हैं ${LOGFILE_DIR} आप में लंबाई को संशोधित कर सकते हैं जैसे मैं करता हूं।

यदि यह वह mvकमांड है जो आप फाइलों के बीच हार्डलिंक खो देते हैं और इसलिए आपकी दूसरी फाइल पहले वाले से ज्यादा जुड़ी नहीं है - शायद कुछ और जहां रखी गई है।

यदि दूसरी जगह पर आप किसी को फ़ाइल को मिटाने की अनुमति नहीं देते हैं तो आपकी लॉग्स एक साथ रहती हैं और आपकी स्क्रिप्ट के माध्यम से नियंत्रित होती हैं।

logrotateशायद अच्छा है। लेकिन मैं इस समाधान से खुश हूं।

"" से परेशान न हों लेकिन मेरे मामले में रिक्त स्थान और अन्य विशेष पत्रों के साथ कुछ फाइलें हैं और यदि मैं "" आसपास या {} नहीं करता हूं तो बहुत अच्छा काम नहीं करता है।

उदाहरण के लिए एक ऐसा डार है जहाँ पुरानी फाइलों को स्वचालित रूप से ज़िप किया जाता है OLDFILE.zipऔर जो कुछ मिलता है वह सब कुछ फाइल में सूचीबद्ध होता है .zip_logइसलिए .zip_logइस डेरे में भी है लेकिन LOGFILE_DIRमैं इसके साथ मिल गया हूं:

ln .zip_log "${LOGFILE_DIR}/USER_ZIP_log"

बराबर फ़ाइल क्योंकि यह एक कड़ी है।

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