किसी फ़ाइल में systemd सेवा के आउटपुट को पुनर्निर्देशित कैसे करें


171

मैं systemdएक फ़ाइल के लिए एक सेवा के उत्पादन को पुनर्निर्देशित करने की कोशिश कर रहा हूं, लेकिन यह काम नहीं करता है:

[Unit]
Description=customprocess
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server
StandardOutput=/var/log1.log
StandardError=/var/log2.log
Restart=always

[Install]
WantedBy=multi-user.target

कृपया मेरे दृष्टिकोण को ठीक करें।

जवाबों:


234

मुझे लगता है कि समस्या को हल करने के लिए एक और अधिक सुंदर तरीका है: एक पहचानकर्ता के साथ syslog को stdout / stderr भेजें और अपने syslog प्रबंधक को प्रोग्राम नाम से इसका आउटपुट विभाजित करने का निर्देश दें।

अपनी systemd सेवा इकाई फ़ाइल में निम्नलिखित गुणों का उपयोग करें:

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote

फिर, मान लें कि आपका वितरण syslogs को प्रबंधित करने के लिए rsyslog का उपयोग कर रहा है, /etc/rsyslog.d/<new_file>.confनिम्नलिखित सामग्री के साथ एक फ़ाइल बनाएं :

if $programname == '<your program identifier>' then /path/to/log/file.log
& stop

अब लॉग फाइल को syslog द्वारा लिखने योग्य बनाएं:

# ls -alth /var/log/syslog 
-rw-r----- 1 syslog adm 439K Mar  5 19:35 /var/log/syslog
# chown syslog:adm /path/to/log/file.log

Rsyslog ( sudo systemctl restart rsyslog) को पुनः आरंभ करें और आनंद लें! आपका कार्यक्रम stdout / stderr अभी भी journalctl ( sudo journalctl -u <your program identifier>) के माध्यम से उपलब्ध होगा, लेकिन वे आपकी पसंद की फ़ाइल में भी उपलब्ध होंगे।

आर्काइव.ऑर्ग के माध्यम से स्रोत


8
मेरे लिए Ubuntu 16.04 पर काम नहीं कर रहा। journalctl -uअभी भी काम करता है लेकिन निर्दिष्ट फ़ाइल को कुछ भी नहीं भेजा जाता है।
डंकन कलवर्ट

1
यह डेबियन खिंचाव पर बहुत अच्छा काम करता है, हालांकि यह शिकायत करता ~है कि यह पदावनत है और stopइसके बजाय इसका उपयोग किया जाना चाहिए। यह भी ध्यान दें कि & stopयदि दोनों एक दूसरे के बाद आते हैं तो दूसरी पंक्ति को छोटा किया जा सकता है ।
jlh

47
सिस्टमड 236 या नए के साथ आप StandardOutput = फाइल का उपयोग करके सीधे फाइल पर भी लिख सकते हैं: / कुछ / पथ github.com/systemd/systemd/pull/7198
leezu

5
मुझे यह /etc/rsyslog.d/<newfile>.confसामग्री बदलकर काम करने लगी है : :programname, isequal, "<your program identifier>" /var/log/somelog.log यहाँ rsyslog फ़िल्टरों पर प्रलेखन है: rsyslog.com/doc/v8-stable/configuration/filters.html और यहाँ गुण जैसे programname: rsyslog -doc
mbil

1
मुझे इस कॉन्फ़िगरेशन का उपयोग करने में तब तक समस्या थी जब तक कि मुझे rsyslogअपना उपयोगकर्ता नहीं मिल गया syslogऔर इसे लॉग्स स्थान तक लिखना पड़ता है। इसलिए chownउसी के अनुसार उपयोग करें । आशा है कि यह किसी की मदद करता है।
इमस्कर

73

आप एक नए के साथ एक नए distro है, तो systemd( systemdसंस्करण 236 या नए ), आप के मूल्यों को निर्धारित कर सकते हैं StandardOutputया StandardErrorकरने के लिए file:YOUR_ABSPATH_FILENAME


लम्बी कहानी:

के नए संस्करण में systemdवहाँ एक अपेक्षाकृत नया विकल्प होता है ( GitHub अनुरोध ish 2016 से है और वृद्धि विलय कर दिया है / 2017 ish बंद कर दिया ) आप के मूल्यों को निर्धारित कर सकते हैं जहां StandardOutputया StandardErrorकरने के लिए file:YOUR_ABSPATH_FILENAMEfile:pathविकल्प में प्रलेखित है सबसे हाल ही में systemd.execआदमी पेज

यह नई सुविधा अपेक्षाकृत नई है और इसलिए पुराने डिस्ट्रोस जैसे सेंटोस -7 (या इससे पहले कोई सेंटोस) के लिए उपलब्ध नहीं है।


10
2018-03-20 में ubuntu 1604 में काम नहीं कर रहा। Ubuntu 1604 में सिस्टमड संस्करण केवल 229 है।
कांस्य पुरुष

धन्यवाद, आपने बहुत स्पष्ट कहा। मैं बस विश्वास नहीं कर सकता ubuntu 1604 में systemd किसी फाइल को आउटपुट को सिर्फ config द्वारा रीडायरेक्ट नहीं कर सकता। मुझे इस समस्या को हल करने के लिए sh तरीके का उपयोग करना है।
कांस्य पुरुष

@bronzeman सुविधा अनुरोध 2017 तक बंद नहीं किया गया था, जबकि उबंटू 16.04 2016 में बाहर आया था। उबंटू की एक प्रमुख रिलीज (जैसे 16.04, 16.10, 17.04, आदि) में, उबंटू अपने मुख्य सिस्टम पैकेजों में एबीआई संगतता बनाए रखता है। इसलिए जब तक यह उबंटू संस्करण पहली बार जारी नहीं किया जाता है, तब तक वे सिस्टमड (या लिनक्स कर्नेल, या ग्लिबक, या कुछ भी) को अपग्रेड नहीं करेंगे।
विलेपक्स

1
FWIW: मैंने थोड़ा खोजा है, लेकिन इस सुविधा में लॉग रोटेशन के प्रावधान नहीं हैं, जैसे कि लॉग फ़ाइल को फिर से खोलने के लिए फ़ंक्शन, जिसमें से एक को पसंद का उपयोग करना copytruncateहै logrotate
एंटैक २१'१

49

आपको संभवतः यह त्रुटि मिलती है:

Failed to parse output specifier, ignoring: /var/log1.log

से systemd.exec(5)आदमी पेज:

StandardOutput=

नियंत्रण जहां निष्पादित प्रक्रियाओं की फ़ाइल डिस्क्रिप्टर 1 (STDOUT) से जुड़ा है। में से एक लेता है inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+consoleया socket

systemd.exec(5)आदमी पेज प्रवेश से संबंधित अन्य विकल्प बताते हैं। यह भी देखें systemd.service(5)औरsystemd.unit(5) मैन पेज ।

या शायद आप इस तरह की चीजों की कोशिश कर सकते हैं (सभी एक पंक्ति में):

ExecStart=/bin/sh -c '/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server 2>&1 > /var/log.log' 

7
विकल्पों में से, सिस्टमड जर्नल में लॉगिंग की सिफारिश की जाती है। आप जर्नल में अपनी प्रक्रिया के लिए लॉग का उपयोग करके देखते हैं journalctl -u your-unit-name
मार्क स्टोसबर्ग

6
फ़ाइल को निर्दिष्ट करने के लिए, एक और क्लीनर विकल्प है, जैसा कि प्रलेखन द्वारा इंगित किया गया है:The fd option connects the output stream to a single file descriptor provided by a socket unit. A custom named file descriptor can be specified as part of this option, after a ":" (e.g. "fd:foobar").
ओरियन

5
जवाब, यह मेरी समस्या हल हो गई है। : मैं बस का विस्तार करने के लिए, क्योंकि वर्तमान में अगर सेवा वर्ष लॉग ऊपर लिख पुनः आरंभ, इस हिस्से को बदलने के लिए चाहते हैं 2>&1 > /var/log.logयह करने के लिए: 2>&1 >> /var/log.log। धन्यवाद
pumpkinseed

10
सच कहूँ तो, ExecStart में एक कमांड स्ट्रिंग के साथ शेल को कॉल करना वास्तव में गलत तरीका लगता है।
डेविड टोनहोफर

1
"" बिन / श "एक महान समाधान है, लेकिन आप" निष्पादन "का उपयोग करना चाहिए, अन्यथा सेवा ठीक से पुनरारंभ नहीं होगी क्योंकि SIGTERM बच्चे की प्रक्रिया में पारित नहीं होगा। Veithen.io/2014/11/16/sigterm-propagation.html
रिच

33

मैं जोड़ने का सुझाव stdoutऔर stderrsystemd में फ़ाइल करेंगेservice फाइल में ही ।

संदर्भ: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=

जैसा कि आपने कॉन्फ़िगर किया है यह पसंद नहीं करना चाहिए:

StandardOutput=/home/user/log1.log
StandardError=/home/user/log2.log

यह होना चाहिए:

StandardOutput=file:/home/user/log1.log
StandardError=file:/home/user/log2.log

यह तब काम करता है जब आप बार-बार सेवा को फिर से शुरू नहीं करना चाहते हैं

यह एक नई फ़ाइल बनाएगा और मौजूदा फ़ाइल में संलग्न नहीं होगा।

इसके बजाय उपयोग करें:

StandardOutput=append:/home/user/log1.log
StandardError=append:/home/user/log2.log

नोट: सुनिश्चित करें कि आप पहले से ही निर्देशिका बना रहे हैं। मुझे लगता है कि यह एक निर्देशिका बनाने के लिए समर्थन नहीं करता है।


5
इस विवरण की डुप्लिकेट , कम विवरण के साथ
गर्ट वैन डेन बर्ग

9
मुझे लगता है, मैंने इसे समझना अधिक आसान बना दिया।
रजत जैन

1
मेरे लिए file:मार्ग सेवा के पहले लोड पर काम करता है, लेकिन बाद के पुनरारंभ में यह अब फ़ाइल पर नहीं लिखता है। मैंने append:डॉक्स से कोशिश की और यह बिल्कुल काम नहीं किया।
आरबी-

3
ध्यान दें कि डॉक्स स्पष्ट करते file:हैं कि हर बार फ़ाइल की शुरुआत के लिए लिखता है, और काट नहीं करता है ... आगे, append:एक नया जोड़ प्रतीत होता है (अर्थात man systemd.execउबंटू 18.04 पर पृष्ठ में मौजूद नहीं )।
कोल

19

अगर किसी कारण से rsyslog का उपयोग नहीं किया जा सकता है, तो यह होगा: ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"


बैश का -e ऑप्शन क्या करता है?
दीपक

3

मान लें कि लॉग पहले से ही stdout / stderr में रखे गए हैं , और सिस्टम यूनिट का लॉग इन है/var/log/syslog

journalctl -u unitxxx.service

Jun 30 13:51:46 host unitxxx[1437]: time="2018-06-30T11:51:46Z" level=info msg="127.0.0.1
Jun 30 15:02:15 host unitxxx[1437]: time="2018-06-30T13:02:15Z" level=info msg="127.0.0.1
Jun 30 15:33:02 host unitxxx[1437]: time="2018-06-30T13:33:02Z" level=info msg="127.0.0.1
Jun 30 15:56:31 host unitxxx[1437]: time="2018-06-30T13:56:31Z" level=info msg="127.0.0.1

कॉन्फ़िगर rsyslog (सिस्टम लॉगिंग सेवा)

# Create directory for log file
mkdir /var/log/unitxxx

# Then add config file /etc/rsyslog.d/unitxxx.conf

if $programname == 'unitxxx' then /var/log/unitxxx/unitxxx.log
& stop

Rsyslog को पुनरारंभ करें

systemctl restart rsyslog.service

1

हम Centos7, सिस्टम के साथ स्प्रिंग बूट एप्लिकेशन का उपयोग कर रहे हैं। मैं नीचे जावा चला रहा था। और फ़ाइल के लिए StandardOutput सेट करना मेरे लिए काम नहीं कर रहा था।

ExecStart=/bin/java -jar xxx.jar  -Xmx512-Xms32M

StandardOutput को सेट किए बिना वर्कअराउंड समाधान के नीचे काम करना। नीचे के रूप में श के माध्यम से जावा चल रहा है।


ExecStart=/bin/sh -c 'exec /bin/java -jar xxx.jar -Xmx512M -Xms32M >> /data/logs/xxx.log 2>&1'

यहां छवि विवरण दर्ज करें


गलत क्रम में jvm मापदंडों को परिभाषित करने के लिए -1। -Xmx512M को -jar से पहले परिभाषित किया जाना चाहिए। आप जो अनुभव करते हैं, वह भी अपेक्षित है। Systemd शेल का उपयोग करते हुए सेवाओं का आह्वान नहीं करता है
सामी

1
@SamiKorhonen, मैंने यह परीक्षण करने के बाद अपनी टिप्पणियाँ जोड़ीं कि यह काम कर रहा है। यहां तक ​​कि मैं -Xmx512M के आदेश के बारे में सोच रहा था, आप के लिए मुस्कुरा रहे हैं। कृपया अंधे टिप्पणियों को जोड़ने से पहले परीक्षण करें।
संतोष हिरकेरर

0

संक्षिप्त जवाब:

StandardOutput=file:/var/log1.log
StandardError=file:/var/log2.log

यदि आप नहीं चाहते कि सेवा चलने पर हर बार फाइलें साफ हो जाएं, तो इसके बजाय एपेंड का उपयोग करें:

StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log

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