मुझे एक मालिकाना विरासत सेवा (डेबियन 10 पर चल रही) से निपटना पड़ रहा है जो विभिन्न (मोटे तौर पर) जानकारी और नोटिस स्तर की चीजों को स्टडआउट में लॉग करता है, और (मोटे तौर पर) चेतावनी और त्रुटि स्तर की चीजों को stderr में लॉग करता है। दोनों को --stdout <path> और --stderr <path> कमांड लाइन पैरामीटर का उपयोग करके फाइलों में लिखा जा सकता है। इस डेमॉन के लिए हमारी सिस्टमड यूनिट फाइल कुछ इस तरह दिखती है (जरूरी चीजों को काटकर):

[Unit]
Description=Some legacy proprietary thing
After=network.target

[Service]
ExecStart=/usr/local/bin/thing \
  --stdout /var/log/thing/stdout.log \
  --stderr /var/log/thing/stderr.log

[Install]
WantedBy=multi-user.target

समस्या यह है कि stdout.log और stderr.log को लिखी गई पंक्तियों में टाइमस्टैम्प नहीं है, जिसकी हमें अब आवश्यकता है। एप्लिकेशन हमारे लिए एक ब्लैक बॉक्स है, और टाइमस्टैम्प को शामिल करने के लिए इसके लॉगिंग आउटपुट को संशोधित करना संभव नहीं है।

अपने शोध में, मुझे दो विकल्प मिले हैं जो यहाँ काम कर सकते हैं। यदि आपके पास अन्य हैं, तो मैं उन्हें सुनने के लिए उत्सुक हूं।

विकल्प 1

Stdout और stderr दोनों के लिए mkfifo के साथ नामित पाइप बनाएं, और लीगेसी एप्लिकेशन को --stdout और --stderr लक्ष्यों के रूप में उपयोग करें। फिर, उन पाइपों को पढ़ने के लिए एक प्रक्रिया सेट करें, प्रत्येक पंक्ति को ts कमांड में पाइप करें, जो एक अच्छा टाइमस्टैम्प जोड़ता है, जैसे:

$ echo foo | ts '[%Y-%m-%d %H.%M.%.S]'
[2021-08-10 16.16.21.506571] foo

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

विकल्प 2

सिस्टमड यूनिट फ़ाइल में, हम StandardOutput और StandardError को syslog पर सेट करने में सक्षम हो सकते हैं, और फिर SyslogIdentifier को कुछ स्ट्रिंग पर सेट कर सकते हैं जिसका उपयोग हम rsyslog के साथ कर सकते हैं, एक जोड़कर टाइमस्टैम्प और अंतिम पंक्ति को लॉग फ़ाइल में लिखना।

दुर्भाग्य से, मुझे सिस्टमड को स्टडआउट और स्टैडर में अंतर करने का कोई तरीका नहीं मिला है: वे दोनों बिना किसी जानकारी के rsyslog पर भेजे जाएंगे, जिसके बारे में मूल था। (मुझे SyslogLevelPrefix के बारे में पता है, लेकिन इसके लिए हमारे ब्लैक बॉक्स एप्लिकेशन से आने वाले लॉग संदेशों में sd-daemon(3) शैली उपसर्ग शामिल होना चाहिए, और यह वर्तमान में संभव नहीं है।)

विवरण

विकल्प 2 में निहित समस्याओं के कारण, मैं विकल्प 1 पर आगे चर्चा करूँगा। यदि आप syslog दृष्टिकोण के समाधान के बारे में जानते हैं, तो फिर भी साझा करें।

तो, नामित पाइप महान हैं, लेकिन मुझे नहीं पता कि उन्हें सिस्टमड यूनिट फ़ाइल में कैसे कार्यान्वित किया जाए। मुझे लगता है कि मेरे पास दो अलग-अलग पाठक प्रक्रियाएं होंगी, एक स्टडआउट पाइप के लिए और एक स्टैडर पाइप के लिए, और इसलिए दो नई यूनिट फाइलें। कुछ और नोट्स:

  • लेखक आवेदन शुरू होने से पहले नामित पाइप मौजूद होना चाहिए। मैं उन्हें पहले से mkfifo के साथ बना सकता हूं, इसलिए यह कोई समस्या नहीं होनी चाहिए। सिस्टमड के साथ पाइप के अस्तित्व को प्रबंधित करना आवश्यक नहीं होना चाहिए, जब तक कि यह यूनिट फ़ाइल को किसी भी तरह से सरल या अधिक मजबूत न बना दे।
  • पाठक प्रक्रियाएं जो टाइमस्टैम्प वृद्धि और लॉग फ़ाइल लेखन करती हैं, लेखक एप्लिकेशन शुरू होने से पहले ऊपर और चलनी चाहिए, जो कि यूनिट फाइलों में Before/After और Requires/Wants के लिए एक नौकरी है, मेरा मानना ​​​​है।
  • पूरे उपकरण को लेखक अनुप्रयोग या पाठक प्रक्रियाओं के पुनरारंभ होने से बचना चाहिए। जैसे यदि cat का उपयोग पाठक प्रक्रिया में किया जाता है, लेखक छोड़ देता है और cat EOF देखता है और छोड़ देता है, तो पाठक प्रक्रिया वापस आ जानी चाहिए और लेखक प्रक्रिया के वापस आने पर तैयार रहना चाहिए।
  • संबंधित पाठक प्रक्रियाओं के डाउन होने पर एप्लिकेशन द्वारा नामित पाइपों को लिखी गई कोई भी लॉग पंक्तियाँ खो जाती हैं, लेकिन यह स्वीकार्य है।

लेखक प्रक्रिया में पैरामीटर --stdout /path/to/outfifo --stderr /path/to/errfifo होने के कारण, पाठक प्रक्रियाएं, सिद्धांत रूप में, इस तरह सरल हो सकती हैं:

cat /path/to/outfifo | ts '[%Y-%m-%d %H.%M.%.S]' > /var/log/thing/stdout_ts.log
cat /path/to/errfifo | ts '[%Y-%m-%d %H.%M.%.S]' > /var/log/thing/stderr_ts.log

उसमें logrotate नियम जोड़ें copytruncate के साथ, और हम सुनहरे हैं! सिवाय इसके कि मैं यह नहीं जानता कि उपरोक्त पुनरारंभ करने योग्य आवश्यकताओं को पूरा करते हुए, सिस्टमड यूनिट फ़ाइल में यह कैसे करना है।

यदि आप यूनिट फ़ाइल निर्माण में मदद कर सकते हैं, या कोई वैकल्पिक तरीका सुझा सकते हैं, तो मैं आभारी रहूंगा।

1
JK Laiho 10 अगस्त 2021, 17:17

1 उत्तर

सबसे बढ़िया उत्तर

journald आपके लिए टाइमस्टैम्प आदि जोड़ सकता है।

एक आसान उपाय यह होगा कि systemd-cat का इस्तेमाल किया जाए :

ExecStart=/bin/systemd-cat \
  --priority=info \
  --stderr-priority=warning \
  --identifier=thing \
  /usr/local/bin/thing

यदि आपका thing प्राथमिकता स्तरों के लिए लकड़हारा उपसर्गों का उत्सर्जन करता है (उदाहरण के लिए warning संदेशों के लिए लाइन <4> से शुरू होती है) तो आप प्राथमिकताएं मैन्युअल रूप से सेट करने के बजाय --level-prefix ध्वज का उपयोग कर सकते हैं .

कुछ अन्य विचारों में शामिल हैं:

  • अपनी इकाई में स्ट्रीम लॉगिंग का उपयोग करना .
  • लॉग में पढ़ने के लिए एक कस्टम स्प्लिटर लिखना और उन्हें सही स्तरों के साथ systemd-cat पर पाइप करना। आप इसे एक ऐसी सेवा के रूप में चलाएंगे जिससे thing बात करेगा।
  • प्रकार: एक कस्टम पार्सर लिखें और पार्स किए गए लॉग को सीधे sd_journal_send(3) के माध्यम से जर्नल में भेजें। आप thing के आउटपुट को parser तक पहुंचाने के लिए systemd का उपयोग करेंगे।
  • एक सॉकेट इकाई पर stdout और stderr लिखने के लिए systemd का उपयोग करें StandardOutput= और StandardError= के माध्यम से।
3
docwhat 19 अगस्त 2021, 21:54
हुह, मैंने पहले कभी systemd-cat के बारे में नहीं सुना। यहां बेहद उपयोगी लगता है। मेरी ओर से कुछ और काम करने की जरूरत है, लेकिन यहां अन्य विचारों के साथ काफी अच्छा है। स्वीकृत और इनाम से सम्मानित किया गया।
 – 
JK Laiho
20 अगस्त 2021, 10:45