लॉगफ़ाइल में अंतिम 50 लाइनें कैसे रखें


21

मैं अपनी फ़ाइल में पिछली 50 पंक्तियों को रखने की कोशिश करता हूं जहां मैं हर मिनट तापमान बचाता हूं। मैंने इस कमांड का उपयोग किया:

tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test

लेकिन परिणाम खाली परीक्षण फ़ाइल है। मैंने सोचा, यह परीक्षण फ़ाइल की अंतिम 50 पंक्तियों को सूचीबद्ध करेगा और इसे परीक्षण फ़ाइल में सम्मिलित करेगा। जब मैं इस कमांड का उपयोग करता हूं:

tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2

यह ठीक काम कर रहा है। Test2 फ़ाइल में 50 लाइनें हैं।

क्या कोई मुझे समझा सकता है कि समस्या कहाँ है?


2
समय के साथ एन रिकॉर्ड (अन्य आँकड़ों के बीच) रखने के लिए rrdtool जैसा कुछ अधिक उपयुक्त हो सकता है।
thrig


2
क्लासिक
छंटनी का

यदि आप अपने लॉग को उत्पन्न करने के लिए अजगर का उपयोग कर रहे हैं, तो आपको loggingमॉड्यूल में देखना चाहिए
वेन वर्नर

जवाबों:


29

समस्या यह है कि आपका शेल कमांड चलाने से पहले कमांड पाइपलाइन स्थापित कर रहा है। यह "इनपुट और आउटपुट" की बात नहीं है, यह है कि फ़ाइल की सामग्री पूंछ से पहले ही चलती है। यह कुछ इस तरह है:

  1. खोल >, इसे रौंदते हुए, लेखन के लिए आउटपुट फ़ाइल खोलता है
  2. शेल में आउटपुट के लिए फ़ाइल-डिस्क्रिप्टर 1 (stdout के लिए) का उपयोग किया जाता है
  3. खोल निष्पादित करता है tail
  4. tailचलाता है, खोलता है /home/pi/Documents/testऔर वहां कुछ नहीं पाता है

विभिन्न समाधान हैं, लेकिन कुंजी समस्या को समझना है, वास्तव में क्या गलत है और क्यों हो रहा है।

यह आप के लिए क्या देख रहे हैं उत्पादन होगा,

echo "$(tail -n 50 /home/pi/Documents/test)" > /home/pi/Documents/test

स्पष्टीकरण:

  • $() को कमांड प्रतिस्थापन कहा जाता है जो निष्पादित करता है tail -n 50 /home/pi/Documents/test
  • आउटपुट में उद्धरण चिह्नों को सुरक्षित रखता है।
  • > /home/pi/Documents/testecho "$(tail -n 50 /home/pi/Documents/test)"उसी फ़ाइल के आउटपुट को रीडायरेक्ट करता है।

धन्यवाद, यह ठीक है! मेरे पास एक और प्रश्न है। क्या आप बता सकते हैं कि आपकी प्रक्रिया कैसे चरण दर चरण काम करती है?
d पर डोरिनैंड

1
लेकिन आपके मामले में पहले प्रदर्शन क्यों नहीं हुआ? मुझे समझ नहीं आ रहा है कि कमांड को कैसे बैश किया जाए। क्या कोई समझा सकता है?
डोरिनैंड

1
> इको कमांड पर है, इसलिए इको कमांड निष्पादित होने पर इसे निष्पादित किया जाता है। यह लिखने से पहले निष्पादन शुरू नहीं कर सकता। परिवर्तनीय प्रतिस्थापन वह है जो कमांड लिखता है। यह नेस्टेड कमांड चलाता है और मूल्य में प्रतिस्थापित करके इको कमांड बनाता है।
जॉब

जब मैं 50 के बजाय 5000 लाइनों का उपयोग कर 44gb लॉग फ़ाइल के लिए एक ही का उपयोग करने की कोशिश की, मैं त्रुटि मिलती हैbash: xrealloc: cannot allocate 18446744071562067968 bytes
Carmageddon

8

फ़ाइल को फिर से साफ़ करने के लिए फ़ाइल पुनर्निर्देशन का एक और समाधान पैकेज spongeसे उपयोग moreutilsकरना है जैसे:

tail -n 50 /home/pi/Documents/test | sponge /home/pi/Documents/test

6

ऐसा इसलिए है क्योंकि बैश >फ़ाइल की सामग्री को हटाते हुए पहले के साथ पुनर्निर्देशन की प्रक्रिया करता है । फिर यह कमांड निष्पादित करता है। क्या आप उपयोग करना चाहते थे >>, अंतिम 50 पंक्तियों को फ़ाइल में वर्तमान में क्या है, के अंत में जोड़ा जाएगा। इस स्थिति में, आपके पास दो बार दोहराई गई समान 50 लाइनें होंगी।

जब कोई भिन्न फ़ाइल पर पुनर्निर्देशित करता है, तो कमांड अपेक्षित रूप से कार्य करता है। यहाँ फ़ाइल का अंतिम 50 पंक्तियों को उसी नाम की फ़ाइल में लिखने का एक तरीका है:

tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 && mv /home/pi/Documents/test2 /home/pi/Documents/test

यह पहले अंतिम 50 पंक्तियों को एक अस्थायी फ़ाइल में लिखता है, जिसे फिर mvमूल फ़ाइल को बदलने के लिए उपयोग किया जाता है।

जैसा कि टिप्पणियों में उल्लेख किया गया है, यह काम नहीं करेगा यदि फ़ाइल अभी भी खुली है। फ़ाइल को स्थानांतरित करने से एक नया इनकोड भी बनता है और यह स्वामित्व और अनुमतियां बदल सकता है। एक अस्थायी फ़ाइल का उपयोग करके ऐसा करने का एक बेहतर तरीका होगा:

tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 ; cat /home/pi/Documents/test2 > /home/pi/Documents/test

अस्थायी फ़ाइल को भी हटाया जा सकता है, हालांकि हर बार ऐसा होने पर इसकी सामग्री को अधिलेखित कर दिया जाएगा।


धन्यवाद। क्या आप कृपया मुझे कदम से कदम समझा सकते हैं कि क्या है? मैं कल्पना नहीं कर सकता कि यह कैसे काम करता है।
डोरिनैंड

tail -50 /home/pi/Documents/test >/tmp/foo && cat /tmp/foo >/home/pi/Documents/test
स्टीव

1
ध्यान दें कि यदि लॉगफ़ाइल अभी भी लॉगिंग प्रक्रिया द्वारा खुला है (जो मूल, हटाए गए फ़ाइल के लिए लॉगिंग जारी रखेगा) काम नहीं करेगा। tempfile + एक नए इनोड (किसी भी हार्ड-लिंक को तोड़ना) में परिणाम ले जाता है, और संभवतः अलग-अलग मालिक या परमिट। tail ... > temp ; cat temp > orig ; rm -f tempकाम करता है।
कैस

4

चूंकि आपने मुख्य मुद्दे को शेल पुनर्निर्देशन के साथ देखा है, यहाँ एक फ़ाइल को इसकी अंतिम 50 पंक्तियों के लिए एक वैकल्पिक तरीका बताया गया है:

file=/path/to/the/file
n=$(( $(wc -l < "$file") - 50 ))
[[ $n -gt 0 ]] && sed -i 1,${n}d "$file"

जीएनयू द्वारा हार्ड वर्क -i"इन-प्लेस एडिटिंग" फीचर के साथ किया जाता है, जो अस्थायी फाइल में आउटपुट बनाकर कवर्स के नीचे काम करता है। बाकी लाइनों ने गणित को sed के संचालन के लिए सेट किया, अर्थात्:

  1. फ़ाइल में लाइनें गिनें ( wc), फिर 50 घटाएं; उसे असाइन करें n
  2. यदि n सकारात्मक है, तो n के माध्यम से लाइनों 1 को हटाने के लिए sed कमांड चलाएं।

4
printf '%s\n' '1,$-50d'   w | ed -s /home/pi/Documents/tes

printfका उपयोग पाइप कमांड (प्रति लाइन) में किया जाता है ededआदेशों हैं:

  • 1,$-50d - सभी लेकिन अंतिम 50 लाइनों को हटा दें
  • w - डिस्क पर वापस संशोधित फ़ाइल लिखें

इसमें कोई पुनर्निर्देशन शामिल नहीं है, इसलिए शेल को पढ़ने से पहले आउटपुट फ़ाइल को अधिलेखित नहीं किया जा सकता है।

इसके अलावा, "इन-प्लेस" संपादन के अधिकांश रूपों के विपरीत (जो आमतौर पर केवल "इन-प्लेस" को एक अस्थायी फ़ाइल बनाकर संपादित करता है और फिर इसे मूल रूप में बदल दिया जाता है), edवास्तव में मूल फ़ाइल को संपादित करता है - इसलिए यह एक ही इनोड रखता है ( और स्वामी, समूह, और अनुमतियाँ - tempfile + mv हमेशा इनोड को बदल देगा , और परिस्थितियों के आधार पर दूसरों को बदल सकता है)।


4

थोड़ा अलग ट्रैक पर, आप उपयोग कर सकते हैं logrotate(8) नियमित रूप से नामित फ़ाइलों के लिए लॉग फ़ाइलों का नियमित रूप से , और फिर पुराने को हटा सकते हैं।

यह है कि मुख्य सिस्टम लॉग फ़ाइलों को बहुत अधिक बढ़ने से रोकने के लिए प्रबंधित किया जाता है।

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