วิธีเปลี่ยนเส้นทางเอาต์พุตของบริการ 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

ฉันคิดว่ามีวิธีที่สวยงามกว่าในการแก้ปัญหา: ส่ง stdout / stderr ไปยัง syslog ด้วยตัวระบุและสั่งผู้จัดการ syslog ของคุณให้แยกเอาต์พุตด้วยชื่อโปรแกรม

ใช้คุณสมบัติต่อไปนี้ในไฟล์ systemd service unit ของคุณ:

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

จากนั้นสมมติว่าการแจกจ่ายของคุณใช้ rsyslog เพื่อจัดการ syslogs ให้สร้างไฟล์/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>) แต่จะสามารถใช้งานได้ในไฟล์ที่คุณเลือก

แหล่งที่มาผ่าน archive.org


8
ไม่ทำงานสำหรับฉันใน Ubuntu 16.04 journalctl -uยังคงใช้งานได้ แต่ไม่มีอะไรถูกส่งไปยังไฟล์ที่ระบุ
Duncan Calvert

1
วิธีนี้ใช้งานได้ดีกับการยืด Debian แต่ก็บ่นว่า~เลิกใช้แล้วและstopควรใช้แทน โปรดทราบด้วยว่าบรรทัดที่สองสามารถตัดให้สั้นลง& stopหากทั้งสองเชื่อมต่อกัน
jlh

48
ด้วย systemd 236 หรือใหม่กว่าคุณสามารถเขียนโดยตรงไปยังไฟล์โดยใช้ StandardOutput = file: / some / path 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.com/doc/master/configuration/properties .html
mbil

1
ฉันมีปัญหาในการใช้การกำหนดค่านี้จนกว่าฉันจะพบว่าrsyslogมีผู้ใช้ของตัวเองsyslogและต้องมีการเข้าถึงการเขียนไปยังตำแหน่งบันทึก ดังนั้นใช้chownตาม หวังว่านี่จะช่วยใครซักคน
Imaskar

73

หากคุณมี distro รุ่นใหม่ที่มีใหม่systemd( systemdรุ่น 236 หรือใหม่กว่า ) คุณสามารถตั้งค่าของStandardOutputหรือไปStandardErrorfile:YOUR_ABSPATH_FILENAME


เรื่องยาว:

ในรุ่นใหม่ของsystemdมีตัวเลือกค่อนข้างใหม่ ( คำขอ GitHub คือจาก 2,016 ish และการเพิ่มประสิทธิภาพที่มีการควบรวมกิจการ / ปิด 2,017 ish ) ที่คุณสามารถตั้งค่าของStandardOutputหรือไปStandardError ตัวเลือกการบันทึกไว้ในล่าสุดหน้าคนfile:YOUR_ABSPATH_FILENAMEfile:pathsystemd.exec

คุณลักษณะใหม่นี้ค่อนข้างใหม่ดังนั้นจึงไม่สามารถใช้งานได้สำหรับ distros รุ่นเก่าเช่น centos-7 (หรือ centos ใด ๆ ก่อนหน้านั้น)


10
ไม่ทำงานใน Ubuntu 1604 ในปี 2018-03-20 รุ่น systemd ใน Ubuntu 1604 นั้นเป็นเพียง 229.
บรอนซ์

ขอบคุณคุณพูดชัดเจนมาก ฉันไม่อยากจะเชื่อ systemd ในอูบุนตู 1604 ไม่สามารถเปลี่ยนเส้นทางการส่งออกไปยังไฟล์เพียงแค่ config.I ฉันต้องใช้วิธี sh ในการแก้ปัญหานี้
ชายทองสัมฤทธิ์

@bronzeman คำขอคุณลักษณะไม่ได้ถูกปิดจนกว่าจะถึงปี 2017 ในขณะที่ Ubuntu 16.04 ออกมาในปี 2016 ในรุ่นใหญ่ที่กำหนดของ Ubuntu (เช่น 16.04, 16.10, 17.04 ฯลฯ ) Ubuntu รักษาความเข้ากันได้ของ ABI ในแพ็คเกจระบบหลัก ดังนั้นพวกเขาจะไม่อัปเกรด systemd (หรือเคอร์เนลลินุกซ์หรือ glibc หรืออะไรก็ตาม) ยกเว้นว่ามันจะรักษา ABI เดียวกันกับเมื่อเวอร์ชัน Ubuntu เปิดตัวครั้งแรก
villapx

1
FWIW: ฉันได้ค้นหาบิต แต่คุณลักษณะนี้ไม่ปรากฏว่ามีบทบัญญัติสำหรับการหมุนล็อกเช่นฟังก์ชั่นที่จะเปิดล็อกไฟล์กับหนึ่งต้องใช้ชอบของในcopytruncate logrotate
antak

49

คุณอาจได้รับข้อผิดพลาดนี้:

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

จากsystemd.exec(5)หน้าคน:

StandardOutput=

ควบคุมว่า file descriptor 1 (STDOUT) ของกระบวนการที่ดำเนินการเชื่อมต่ออยู่ ใช้เวลาหนึ่งinherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, หรือkmsg+consolesocket

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
ในบรรดาตัวเลือกต่าง ๆ แนะนำให้ทำการล็อกอินเข้าสู่ systemd journal journalctl -u your-unit-nameคุณดูเพียงบันทึกของกระบวนการของคุณลงในสมุดบันทึกโดยใช้
Mark Stosberg

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").
orion

5
คำตอบที่น่ากลัวมันแก้ปัญหาของฉันได้ ฉันเพียงแค่ต้องการที่จะขยายเพราะขณะนี้ถ้าบริการเริ่มต้นเขียนทับบันทึกเก่าต้องเปลี่ยนส่วนนี้: ไปนี้:2>&1 > /var/log.log 2>&1 >> /var/log.logขอบคุณ
PumpkinSeed

10
ตรงไปตรงมาการเรียกเชลล์ด้วยสตริงคำสั่งใน ExecStart ฟังดูเหมือนวิธีผิดพลาดจริง ๆ
David Tonhofer

1
"/ bin / sh" เป็นวิธีแก้ปัญหาที่ยอดเยี่ยม แต่คุณต้องใช้ "exec" มิฉะนั้นบริการจะไม่เริ่มต้นใหม่อย่างถูกต้องเนื่องจาก SIGTERM จะไม่ถูกส่งผ่านไปยังกระบวนการลูก ดูveithen.io/2014/11/16/sigterm-propagation.html
รวย

33

ฉันขอแนะนำให้เพิ่มstdoutและstderrไฟล์ในserviceไฟล์systemd ตัวเอง

การอ้างอิง: 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
คำตอบนี้ซ้ำโดยมีรายละเอียดน้อยลง
Gert van den Berg

9
ฉันคิดว่าฉันทำให้มันโดยตรง \ เข้าใจง่ายขึ้น
Rajat jain

1
สำหรับฉันfile:เส้นทางทำงานกับการโหลดครั้งแรกของบริการ แต่ในการรีสตาร์ทครั้งต่อไปมันไม่ได้เขียนไปยังไฟล์อีกต่อไป ฉันลองappend:จากเอกสารและนั่นไม่ได้ผลเลย
rb-

3
โปรดทราบว่าเอกสารที่ชัดเจนที่file:เขียนไปยังจุดเริ่มต้นของไฟล์ทุกครั้งและไม่ตัดทอน ... ต่อไปappend:ดูเหมือนว่าจะเป็นการเพิ่มใหม่ (เช่นไม่มีอยู่ในman systemd.execหน้าบน Ubuntu 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-bash ทำอะไร?
ตะเกียง

3

สมมติว่าบันทึกได้ถูกนำไปใช้กับstdout / stderrแล้วและมีบันทึกของ systemd unit/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 ซึ่งเป็นแอพพลิเคชั่นบู๊ทสปริงด้วย systemd ฉันใช้จาวาดังนี้ และการตั้งค่า StandardOutput เป็นไฟล์ไม่ทำงานสำหรับฉัน

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

ด้านล่างวิธีแก้ปัญหาการทำงานโดยไม่ต้องตั้งค่า StandardOutput ใช้ java ผ่าน sh ดังต่อไปนี้


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

ป้อนคำอธิบายรูปภาพที่นี่


-1 สำหรับการกำหนดพารามิเตอร์ jvm ในลำดับที่ไม่ถูกต้อง -Xmx512M ต้องถูกกำหนดไว้ก่อน -jar สิ่งที่คุณคาดหวัง Systemd ไม่เรียกใช้บริการโดยใช้เชลล์
Sami Korhonen

1
@SamiKorhonen ฉันเพิ่มความคิดเห็นหลังจากการทดสอบนี้ใช้งานได้ แม้ฉันกำลังคิดเกี่ยวกับการสั่งซื้อของ -Xmx512M นั้นฉลาดสำหรับคุณ กรุณาทดสอบก่อนที่จะเพิ่มความคิดเห็นที่ตาบอด
Santhosh Hirekerur

0

คำตอบสั้น ๆ :

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

หากคุณไม่ต้องการให้ไฟล์ถูกล้างทุกครั้งที่มีการเรียกใช้บริการให้ใช้ผนวก:

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

2
คำตอบนี้ซ้ำโดยมีรายละเอียดน้อย
rustyx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.