ลบบรรทัดแรก N ออกจากไฟล์บันทึกที่ใช้งานอยู่


26

มีวิธีลบNบรรทัดแรกออกจากบันทึกที่มีการต่อท้ายโดยแอปพลิเคชันหรือไม่?

คำตอบ:


10

ไม่ระบบปฏิบัติการเช่น Linux และเป็นระบบไฟล์ไม่ได้จัดเตรียมสำหรับการลบข้อมูลออกจากจุดเริ่มต้นของไฟล์ กล่าวอีกนัยหนึ่งจุดเริ่มต้นของการจัดเก็บสำหรับไฟล์ได้รับการแก้ไข

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


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

มียูทิลิตี้มากมายสำหรับจัดการขนาดของไฟล์บันทึกตัวอย่างเช่นlogrotate

บางโปรแกรมมีระบบสาธารณูปโภคของตนเอง ตัวอย่างเช่นเว็บเซิร์ฟเวอร์ Apache รวมถึงยูทิลิตี้rotatelogs


3
แต่คุณไม่ควรทำสิ่งนี้ในขณะที่บางสิ่งยังคงเปิดอยู่และยังคงต่อท้ายไฟล์เพราะมันจะเขียนไปยังไฟล์ที่ถูกลบตอนนี้และคุณจะสูญเสียข้อความบันทึกเหล่านั้น
Tarnay Kálmán

จริง แม้ว่าคุณจะใช้ชื่อไฟล์เดียวกัน
Hennes

น่าเสียดายที่ระบบปฏิบัติการของคุณไม่ยอมให้คุณมั่นใจว่าจะสะดวกสำหรับผู้ใช้งานที่ไม่จำเป็นต้องโหลดกระบวนการหลังจากการหมุน: |
rogerdpack

25

ฉันคิดว่างานนี้สามารถทำได้ด้วย sed

sed -i '1,10d' myfile

จะเอาสายจาก 1 เซนต์ไป 10 THสายในรูปแบบไฟล์

ฉันคิดว่าอย่างน้อยทุกคนควรดูซับในนี้ 1เส้น

โปรดทราบว่าสิ่งนี้ไม่ได้ผลสำหรับ logfiles ที่ถูกผนวกเข้ากับแอปพลิเคชัน (ตามที่ระบุในคำถาม)

sed -iจะสร้างไฟล์ใหม่และ 'ลบ' ไฟล์ที่กำลังเขียน แอปพลิเคชันส่วนใหญ่จะยังคงเขียนบันทึกลงในไฟล์บันทึกที่ถูกลบและจะยังคงเติมพื้นที่ดิสก์ต่อไป ไฟล์บันทึกใหม่ที่ถูกตัดทอนจะไม่ถูกผนวกเข้าด้วย สิ่งนี้จะหยุดลงเมื่อแอปพลิเคชั่นเริ่มต้นใหม่หรือมีการส่งสัญญาณให้ปิดและเปิดไฟล์บันทึกใหม่อีกครั้ง ณ จุดนี้จะมีช่องว่าง (บันทึกการขาดหายไป) ในไฟล์บันทึกใหม่หากมีกิจกรรมการบันทึกใด ๆ ระหว่างการใช้ sed และการรีสตาร์ทแอปพลิเคชัน

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


2
คุณรู้หรือไม่ว่าเกิดอะไรขึ้นกับแอพพลิเคชั่นที่ต่อท้าย?
Adam Matan

1
สมมติว่ามีตัวจัดการไฟล์เปิดแบบปกติซึ่งต่อท้ายบรรทัดและล้างข้อมูลทุก ๆ ครั้ง
Adam Matan

1
ฉันรู้วิธีของฉันรอบ ๆ sed และการแยกบรรทัดไปยังไฟล์ใหม่นั้นไม่ใช่เกมง่าย ๆ ที่มี sed ปัญหาคือเก็บทุกอย่างไว้ในไฟล์เดียวกัน
Adam Matan

10
ไม่สิ่งนี้จะไม่ทำงาน sed -iสร้างไฟล์ใหม่ที่มีเนื้อหาที่แก้ไขแล้วและไฟล์เก่าจะถูกลบออกดังนั้นคุณจะไม่แก้ไขไฟล์ที่ใช้งานอยู่: $ ls -i --- 6823554 testfile --- $ sed -i 's/test/final/' testfile --- $ ls -i --- 6823560 testfile------ โปรดตรวจสอบวิธีการsed -iทำงาน ทำไมคำตอบที่ไม่ถูกต้องนี้มี upvotes มากมาย?
pabouk

1
คำถามระบุ "จากบันทึกที่กำลังถูกผนวกเข้ากับแอปพลิเคชัน" คำผ่าตัดคือ "แข็งขัน" บางทีคำอธิบายนั้นอาจถูกเพิ่มเข้าไปหลังจากคำตอบของคุณปรากฏขึ้น แต่ตามที่กล่าวมาผู้อ่านที่โน้มน้าวให้ "upvotes ที่สุด" จะทำให้เข้าใจผิด ฉันสามารถลงคะแนนเพียงครั้งเดียว
Scott Prive

5

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

ดู: http://www-uxsup.csx.cam.ac.uk/~jw35/courses/apache/html/x1670.htm


2

นี่คือคำตอบไม่ใช่ทางออก ไม่มีคำตอบสำหรับคำถาม ผู้ถามระบุอย่างชัดเจนว่า: "จากบันทึกที่ถูกต่อท้ายโดยแอปพลิเคชัน" คุณสามารถอ่านเพื่อทำความเข้าใจเพิ่มเติมและข้ามไปยังจุดสิ้นสุดสำหรับข้อเสนอแนะที่ฉันทำตามข้อสันนิษฐานของฉันทำไมรหัสนี้ไม่ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดในการบันทึก

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

ไฟล์ ACTIVE ไม่ได้เป็นประเภทของคอนเทนเนอร์ที่คุณใส่ข้อมูลลงไป ชื่อไฟล์จะชี้ไปที่ ONE inode (จุดเริ่มต้นของไฟล์) และ inode ทุกอันจะมีตัวชี้ไปยัง inode อื่น (หากมีข้อมูลเพิ่มเติม) นั่นหมายถึงไฟล์เขียนอย่างต่อเนื่องมี inode ที่เพิ่มเข้ามาอย่างต่อเนื่องและสิ่งที่คุณคิดว่า "ไฟล์" เป็นจริงลำดับของ inodes

ลองนึกภาพคุณกำลังติดตามใครบางคนบน Google แผนที่และบุคคลนั้นสามารถส่งผ่านทางไกลได้ทุกที่ในโลกตลอดเวลาและคุณพยายามเชื่อมต่อจุดเหล่านี้

เครื่องมือ Linux "truncate" สามารถทิ้งข้อมูลที่ส่วนท้ายของไฟล์เพียงแค่เดินไปที่ต้นไม้ inode และ (ที่ตำแหน่ง / ขนาดที่คุณกำหนด) มันจะทิ้งพอยน์เตอร์ที่ตามมาทั้งหมดในสแต็ก หากต้องการย้อนกลับ - ทิ้งข้อมูลตอนเริ่มต้นไฟล์ - จะเป็นกระบวนการที่ซับซ้อนและมีความเสี่ยงสูงในการเขียนทรีต้นไม้ inode ในแบบเรียลไทม์ซึ่งไม่มีใครจะเขียนเครื่องมือดังกล่าวให้กับสาธารณะเพราะพวกเขามักล้มเหลวและนำไปสู่ การสูญเสียข้อมูล inodes วิกิพีเดียเป็นเวลาสั้น ๆ แต่อธิบายบางส่วนของแนวคิดเหล่านี้

** คำแนะนำของฉัน: พลิกปัญหานี้ไป - แอพพลิเคชั่นนี้ทำเช่นนี้เพราะอะไร? มีแนวทางปฏิบัติที่ดีที่สุดในการเข้าสู่ระบบจำนวนมาก แต่บ่อยครั้งที่พวกเขาเชื่อมโยงกับสิ่งที่ระบบการบันทึกของคุณเป็นจริง (syslog ฯลฯ ) ที่แกนกลางแอปพลิเคชันคาดว่าจะ "ปล่อย" มันจัดการกับไฟล์ดังนั้น logrotate (ฯลฯ ) สามารถจัดการการประมวลผลของข้อมูลเก่าเพิ่มเติม

เมื่อใดก็ตามที่ฉันได้ยิน "ไปยังไฟล์บันทึกการใช้งาน" ฉันขอให้บุคคลนั้นบอก "เรื่องราวพิเศษ" ที่อยู่เบื้องหลังแอปพลิเคชันนี้ให้ฉันทันที โดยปกติแล้วมันคือ "นักพัฒนาเลิกและเราไม่สามารถเปลี่ยนรหัสได้นี่เป็นสิ่งที่ตรงกันข้ามกับความปลอดภัยมีความเสี่ยงของตัวเอง แต่ฉันขอให้คุณต้องการโซลูชันที่หลีกเลี่ยงการสัมผัสซอร์สโค้ดหากนี่คือ กรณีจำเป็นต้องมีคำถามที่เฉพาะเจาะจงมากขึ้น


0

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


-1

อาจจะคัดลอกตัดทอนคัดลอกกลับไปที่ขนาด = 0 การตัดทอนและลบสำเนาหรือไม่

ดีกว่ายังเหมาะสำหรับการคัดลอกแบบหางตัดส่วนต้นฉบับแบบต่อท้ายแบบย่อลงบนต้นฉบับ

คุณได้รับบรรทัดในบันทึกที่ความยาวหางดังนั้นดีกว่านั้นจำกัดความยาวไบต์

แก้ไขรายละเอียดจากความคิดเห็น:

ก่อนอื่นเรามีสคริปต์ตัวบันทึกใน Python3 สิ่งที่คุณต้องการ

from time import sleep

idx = 0
while 1 == 1:
    idx = (idx + 1)
    lf = open('tailTrunc.log', 'a')
    lf.write("line to file " + str(idx) + '\n')
    lf.close()
    sleep(0.01)

จากนั้นเราก็มีเครื่องตัดของเรา

#!/usr/bin/env bash

trap "kill 0" EXIT

rm tailTrunc.log
touch tailTrunc.log

python3 logLoop.py &
loggerPID=$!
sleep 1

kill -STOP $loggerPID
tail -10 tailTrunc.log > trimEnd.log
truncate -s 0 tailTrunc.log
kill -CONT $loggerPID
sleep 1

trimEnd.log แสดง 80 ถึง 89

บันทึกแสดง 90 ถึงสิ้นสุด

อย่างไรก็ตามที่ซึ่งมีความตั้งใจ

ตัวอย่างที่ซับซ้อนมากขึ้นของผู้รวบรวมและวิธีการเปิดหรือปิดกระแสการเขียนอาจต้องปรับเปลี่ยนต่อ cpu core เป็นต้นเพียงหยุดการเขียนและคิวหากคุณสามารถบันทึกการทำงานของกระบวนการบันทึก ฯลฯ


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

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

อย่าคิดว่ามันเป็นการลงคะแนนของฉัน แต่ฉันคิดว่าประเด็นนี้ได้รับการตอบกลับในความคิดเห็นของคำตอบอื่น ๆ : หากคุณคัดลอกไฟล์บันทึกแล้วจะไม่ใช่ไฟล์บันทึกการใช้งานอีกต่อไป ... ไม่ว่าคุณจะทำอะไร filehandle ของแอปพลิเคชันจะชี้ไปที่ inode ของ logfile ดั้งเดิม ลองใช้วิธีนี้: คุณมีแอปพลิเคชันที่ใช้ฟังก์ชั่นการบันทึกที่ไม่ได้มาตรฐานและเพิ่มไบต์อย่างต่อเนื่องในไฟล์ที่เปิดอยู่
Scott Prive

1
ขอโทษที่ต้องอนุมาน ใช่ไอโหนดจำเป็นต้องอยู่เหมือนเดิมนั่นคือเหตุผลที่ตัวอย่าง / ข้อพิสูจน์การใช้งานถูกตัดทอนและอีกครั้งมันขึ้นอยู่กับสถานการณ์ (ตัวเลือกสำหรับทุกคนซ่อนอยู่ในเว็บไซต์ธรรมดา)
อาจารย์เจมส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.