วิธีเปลี่ยนเส้นทาง stdout ไปยังไฟล์ต่อไปหลังจากที่ logrotate ทำการย้ายมัน


22

ฉันมีสคริปต์ง่าย ๆ ซึ่งส่งออกเป็นกลุ่มของบันทึกไปยังหน้าจอและฉัน pip STDOUT ไปยังไฟล์เพื่อเก็บบันทึก เนื่องจากสคริปต์นี้ใช้งานได้นานฉันจึงต้องหมุนไฟล์บันทึกเพื่อให้ไฟล์เหล่านั้นถูกจับให้เล็กลงและจัดการได้ง่ายขึ้น

ปัญหาที่ฉันพบคือเมื่อlogrotateย้ายไฟล์บันทึกปัจจุบันไปยังไฟล์ใหม่ไฟล์บันทึกที่สร้างขึ้นใหม่จะไม่ได้บรรจุด้วยบันทึกอีกต่อไป ดูเหมือนว่าเมื่อไฟล์บันทึกดั้งเดิมถูกลบแล้วตัวจัดการไฟล์จะหายไปและการเปลี่ยนเส้นทางจะไม่ทำงานอีกต่อไป

ฉันพบโพสต์นี้ซึ่งมีปัญหาเช่นเดียวกับฉันและอ้างว่าสามารถแก้ไขได้โดยใช้>>แทน>การเปลี่ยนเส้นทางเอาต์พุต ฉันทดสอบวิธีการแก้ปัญหาของเขา แต่มันไม่ได้ผลสำหรับฉัน ใครบ้างมีความคิดวิธีการทำให้การเปลี่ยนเส้นทางทำงานได้หรือไม่


4
ในกรณีของคุณฉันยังแนะนำให้ใช้ ">>" แทนที่จะเป็น ">" ถ้าคุณตั้งใจจะเขียนไปยังไฟล์ที่ถูกตัดทอน: เนื่องจาก ">>" เปิดในโหมดต่อท้ายมันจะค้นหาจนกว่าจะสิ้นสุดไฟล์ ทุกครั้งที่มันเขียน ด้วยวิธีนี้เมื่อคุณตัดทอนไฟล์ (ทำให้มันเปลี่ยนจาก XXXX ไบต์เป็น 0 ไบต์) มันจะ "ค้นหาจนกระทั่งจบ" ดังนั้นจะรู้ว่าตอนนี้ต้องเขียนหลังจากไบต์ 0 มิฉะนั้นอาจเขียนตามไบต์ XXXX และทำให้ สร้างไฟล์ที่กระจัดกระจายด้วย XXXX null ไบต์ก่อนหน้า (เช่นเมื่อ ">" fd สามารถจำได้ว่ามันอยู่ที่ไหนในไฟล์นั้นและเขียนจากที่นั่นโดยไม่ต้องตระหนักถึงขนาดขนาดไฟล์!)
Olivier Dulac

คำตอบ:


25

คุณควรใช้คำสั่ง copytruncate ในการกำหนดค่า logrotate ของคุณสำหรับไฟล์บันทึกนี้

คัดลอกตัดทอนตัดทอนไฟล์บันทึกดั้งเดิมหลังจากสร้างสำเนาแทนการย้ายไฟล์บันทึกเก่าและเลือกสร้างใหม่ สามารถใช้เมื่อบางโปรแกรมไม่สามารถบอกให้ปิด logfile และอาจทำการเขียนต่อท้ายไฟล์บันทึกการทำงานก่อนหน้านี้ โปรดทราบว่ามีการแบ่งเวลาเล็กน้อยระหว่างการคัดลอกไฟล์และตัดทอนดังนั้นข้อมูลการบันทึกบางอย่างอาจสูญหาย เมื่อใช้ตัวเลือกนี้ตัวเลือกการสร้างจะไม่มีผลเนื่องจากไฟล์บันทึกเก่ายังคงอยู่


2
อาจกล่าวได้ว่าคุ้มค่าสำหรับช่วงเวลาสั้น ๆ ก่อนการcompressดำเนินการข้อมูลจะถูกทำซ้ำ นั่นทำให้เราเกิดปัญหาหนึ่งครั้ง แต่มันก็แย่เพราะเราไม่ควรอยู่ใกล้lvขีด จำกัด พื้นที่ นอกจากนี้ตามที่ระบุไว้ในmanข้อมูลโค้ดคุณอาจสูญเสียข้อมูลบันทึกบางส่วนระหว่างการดำเนินการคัดลอกและตัดทอน
Belmin Fernandez

6

คุณอาจ:

  • ใช้ยูทิลิตี้คนตัดไม้ในสคริปต์ของคุณแทนการวางท่อด้วยเครื่องมืออำนวยความสะดวกเฉพาะ (เช่น local5) ตัวอย่างเช่น:

    logger -p local5.info -t myscriptname "this is some log data"

  • กำหนดค่า syslog เพื่อเขียนสิ่งอำนวยความสะดวกนี้ไปยังไฟล์บันทึกที่ต้องการตัวอย่าง (rsyslog.conf):

    local5.* /var/log/mylogfile

  • กฎการตั้งค่า logrotate สำหรับบันทึกนี้


echoนี้จะทำงานเฉพาะถ้าคุณมีคำสั่งส่งออกอย่างชัดเจนเช่น ผลลัพธ์ของเครื่องมือของบุคคลที่สามซึ่งถูกเรียกจากสคริปต์และเอาท์พุทบางอย่างไม่สามารถเปลี่ยนเส้นทางไปยังตัวบันทึกด้วยวิธีนี้
Daniel Alder

4

ทางเลือกอื่นในการแก้ปัญหาของ Iain ก็คือการใช้ postrotateสคริปต์เพื่อเปิดสคริปต์ของคุณอีกครั้งเมื่อมีการหมุนเวียน สิ่งนี้ทำสำหรับ daemons จำนวนมาก (รีสตาร์ทหรือโหลด daemon ใหม่) แต่ไม่ทราบว่าสคริปต์ของคุณฉันไม่รู้ว่าโซลูชันนี้จะเหมาะกับคุณหรือไม่ (สคริปต์ของคุณขึ้นอยู่กับสถานะที่สร้างไว้ในขณะนั้นหรือไม่)

เนื้อหาของ/etc/logrotate.d/your-script-name:

/var/log/your-script-name.log {
    # your current logrotate options
    ...
    postrotate
        # this supposing you have the current pid stored
        cat /run/your-script-name.pid | xargs -r kill
        #relaunch it again
        /usr/local/bin/your-script-name
    endscript
}

0

คุณสามารถไปป์ stdout ไปที่ "split" (ส่วนหนึ่งของ coreutils ใน linux) มันช่วยให้คุณสามารถแยกไฟล์ / stdin เป็นชิ้น ๆ ตามขนาดจำนวนบรรทัด ฯลฯ เมื่อคุณได้รับไฟล์แล้วคุณสามารถจัดการมันด้วย logrotate หากจำเป็น

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