การบันทึกเอาต์พุตของ Daemon ด้วยพุ่งพรวด


34

ฉันมีภูตที่กำหนดเองที่จัดการโดยพุ่งพรวดบนเซิร์ฟเวอร์ Ubuntu ของฉัน มันทำงานได้อย่างสมบูรณ์ยกเว้นว่าฉันต้องจับ (บันทึก) เอาท์พุทของภูต หน้าอย่างเป็นทางการบทบอกว่าฉันสามารถใช้console loggedการทำเช่นนี้ แต่สิ่งที่ไฟล์ที่ไม่ได้เข้าสู่ระบบเพื่อ?

ฉันยังอ่านว่าconsole loggedเป็นไม่ได้เป็นบทที่ถูกต้อง ปัจจุบันฉันใช้ 0.3.9 (Hardy) แต่จะอัปเกรดเป็น 0.6.x (Lucid) ในอีกไม่กี่เดือน หากconsole loggedอันที่จริงแล้วใช้ไม่ได้กับเวอร์ชันใหม่กว่าฉันจะใช้อะไรแทน


1
คุณสามารถอัพเดต daemon แบบกำหนดเองของคุณเพื่อส่งเอาต์พุตไปยัง syslog หรือไปยังไฟล์บันทึกการทำงานที่ระบุในไฟล์กำหนดค่าของ daemon ได้หรือไม่
Zoredache

คำตอบ:


35

ตัวอย่างนี้จะไพพ์เอาต์พุตของบริการของคุณไปยังตัวบันทึกในขณะที่ยังอนุญาตให้คุณดำเนินการกระบวนการบริการ (ดังนั้นการแทนที่กระบวนการเชลล์) เพื่อให้การพุ่งพรวดไม่สับสน นอกจากนี้ยังทำให้แน่ใจว่ากระบวนการตัวบันทึกเป็น reparented เพื่อเริ่มต้นดังนั้นจึงไม่ใช่ลูกของบริการของคุณและจะหลีกเลี่ยงการทิ้ง cruft นั่งในระบบไฟล์แม้ว่ามันจะต้องสร้าง Fifo ชั่วคราว

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

นี่คือวิธีการทำงาน:

  1. mkfifo /tmp/myservice-log-fifoเพียงแค่ทำให้ไฟล์พิเศษ fifo (aka ชื่อท่อ) พิมพ์man 7 fifoเพื่อรับข้อมูลเพิ่มเติม
  2. ( logger ... </tmp/myservice-log-fifo & ) เริ่มคนตัดไม้อ่านจาก fifo ในพื้นหลัง parens ทำให้กระบวนการตัวบันทึกถูก reparented เพื่อเริ่มต้นแทนที่จะเป็นชายด์ของกระบวนการเชลล์ปัจจุบัน
  3. exec >/tmp/myservice-log-fifoเปลี่ยนทิศทาง stdout ของเชลล์ปัจจุบันไปยัง Fifo ตอนนี้เรามีตัวอธิบายไฟล์แบบเปิดสำหรับ Fifo นั้นและเราไม่ต้องการรายการระบบไฟล์อีกต่อไป ...
  4. rm /tmp/myservice-log-fifo ดังนั้นเราจะลบมันออก
  5. exec myservice 2>/dev/nullเพียงแค่เรียกใช้บริการตามปกติ Stdout กำลังจะไปถึง Fifo และนั่นจะไม่เปลี่ยนแปลงเมื่อโปรแกรมใหม่ดำเนินการ

UPDATE: set -eไม่จำเป็นเนื่องจาก Upstart จะเรียกใช้สคริปต์ด้วยตัวเลือกนี้ตามค่าเริ่มต้น (ดูที่ http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )


คำตอบที่ดีและไม่ปล่อยให้ไฟล์ Fifo วางอยู่รอบ ๆ
Ash Berlin-Taylor

คือset -eอะไร
Peter Mounce

1
set -eทำให้เกิดสคริปต์เพื่อออกทันทีถ้าคำสั่งใด ๆ ที่ล้มเหลว หากไม่มีบรรทัดนั้นสคริปต์จะยังคงเรียกใช้คำสั่งที่ตามมาอย่างไร้ประโยชน์ (และอาจเป็นอันตราย)
Keith Rarick

1
หากต้องการบันทึก stderr เช่นเดียวกับ stdout ให้เพิ่มบรรทัดexec 2>&1ด้านบนrmบรรทัดแล้วลบออก2>/dev/nullจากบรรทัดสุดท้าย
itsadok

31

สำหรับ Ubuntu รุ่นล่าสุด (12.04+) เพียงใช้

console log

และเอาต์พุต daemon (STDOUT & STDERR) จะถูกต่อท้าย /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log


2
นั่นน่าจะสะอาดและดี แต่น่าเสียดายที่มันใช้งานไม่ได้กับ CentOS 6.x ซึ่งยังคงส่งเวอร์ชั่นเก่าแก่ที่ไม่รองรับสิ่งนี้
Cristian Măgherușan-Stanciu

11

หากคุณใช้console output stanzaจากนั้นไพพ์เอาต์พุตสคริปต์ของคุณไปที่logger(อินเตอร์เฟสคำสั่งเชลล์ไปยังโมดูลบันทึกระบบ syslog (3)) จากนั้นจะทำงาน

ตัวอย่างเช่น

console output
exec /my/script | logger

จะเข้าสู่ระบบ /var/log/messages

ตัวอย่างเช่น

console output
exec /my/script | logger -t my-script

จะเข้าสู่ระบบ/var/log/messagesและแท็กแต่ละข้อความด้วยmy-script

logger --help สำหรับตัวเลือกการใช้งานคนตัดไม้

(ฉันใช้ Amazon Linux AMI ซึ่งใช้ Centos 5.x; YMMV)


4
ปรากฎว่านี่ไม่ใช่ทางออกที่ดี พุ่งพรวดเข้าหา PID ของloggerไม่ใช่กระบวนการที่คุณต้องการจัดการ
Peter Mounce

10

ฉันไม่ได้รับmkfifoเคล็ดลับในการทำงานอย่างน่าพอใจ; ดูเหมือนจะไม่จับ stderr และพยายามเปลี่ยนเส้นทางทำให้พุ่งพรวดโดยไม่มีข้อผิดพลาด

นอกจากนี้ยังมีผลข้างเคียงที่โชคร้ายในการทำให้loggerกระบวนการแฮงค์เป็นเด็กinitดังนั้นข้อมูลเกี่ยวกับผู้ที่ "เจ้าของ" คนตัดไม้หายไปและทุกคนที่ไม่ได้ตระหนักถึงความmkfifoสามารถในการคิดว่ามันเป็นกระบวนการห้อยที่สามารถฆ่าได้

แต่ฉันลงเอยด้วยวิธีแก้ปัญหาต่อไปนี้ซึ่งแก้ไขปัญหาเหล่านี้ทั้งหมด มันทำให้logger กลายเป็นกระบวนการเด็กในขณะที่รักษาบริการเป็นกระบวนการราก น่าเสียดายที่มันต้องมีการเรียกใช้bashแต่มันก็ดูสกปรก

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

สิ่งนี้ใช้เคล็ดลับที่เปลี่ยนเส้นทาง stdout และ stderr ไปยังคำสั่ง เนื่องจากเราดำเนินการบริการภายในbashคำสั่งนี้มีผลข้างเคียงของการแทนที่เชลล์และการทุบตีอย่างน่าอัศจรรย์กลายเป็นกระบวนการลูกของบริการดังที่แสดงโดยps aufxw:

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

bash -cด้วยเหตุผลบางคำสั่งดังกล่าวจะต้องมีการห่อใน ฉันถือว่านี่เป็นเพราะพุ่งพรวดเพียงแกล้งทำสคริปต์ของคุณผ่าน Bash แต่ไม่จริง หากใครสามารถแนะนำวิธีหลีกเลี่ยงเปลือก bash พิเศษนั่นจะยอดเยี่ยม


1
ใช่ ฉันดีใจที่พบสิ่งนี้ ดูดีกว่าตัวแปร mkfifo และในกรณีของฉันฉันต้องexec bash -l << EOFไม่มีการสูญเสีย
thom_nic

6

มันน่าเกลียด แต่จนถึงตอนนี้ฉันก็พบสิ่งที่ดีที่สุดแล้ว

exec / path / to / server >> /tmp/upstart.log 2> & 1


2
วิธีแก้ปัญหาไม่ดีเมื่อพูดถึงการหมุนเวียนของบันทึกเนื่องจากแอปพลิเคชันกำลังบันทึกลงไฟล์โดยตรง การบันทึกผ่าน syslog เพื่อหลีกเลี่ยงปัญหาที่เกี่ยวข้อง
Mark Stosberg

3

นอกจากนี้คุณยังสามารถเปลี่ยนเส้นทางผลลัพธ์ไปยัง syslog เช่น

exec $SERVER 2>&1 | logger -t myservice -p local0.info

อย่างไรก็ตามไปป์ไลน์อาจทำให้พุ่งพรวดสับสน PID ของกระบวนการบันทึกด้วย PID ของ daemon


daemon ที่ทำให้ PID สับสนนั้นจริง ๆ แล้วก็คือ daemon ที่ไร้ประโยชน์เนื่องจากมันควรจะคอยดูกระบวนการ มีความคิดเห็นเกี่ยวกับวิธีการตรวจสอบว่ามีการดู PID ที่ถูกต้องหรือไม่
Johann Philipp Strathausen

ฉันคิดว่า (แต่ยังไม่ได้ลอง) ว่าคุณจะต้องการexpect forkหรือexpect daemonบทที่ หรือคุณสามารถcatpid-file ลงในบันทึกข้อความเป็นอย่างอื่นฉันเดา
Peter Mounce

1

อีกทางเลือกหนึ่งคือใช้ tee like:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

เพื่อรับทั้งไฟล์พุ่งพรวดและเอาต์พุต syslog

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