2009-11-18 28 views
9

Tôi đang cố quản lý kích thước tệp nhật ký của mình bằng tập lệnh cron. Về cơ bản tôi muốn xóa tất cả trừ 2000 dòng cuối cùng của tệp nhật ký mỗi đêm. Tôi đang cố gắng để chạy lệnh này, nhưng có vẻ như được đổ toàn bộ tập tin thay vì làm những gì tôi muốn:Tại sao doesnt "tail" làm việc để cắt bớt các tệp nhật ký?

đuôi -2000 logfile.txt> logfile.txt

Có ai biết tại sao isn này' t làm việc và/hoặc làm thế nào để hoàn thành những gì tôi muốn? Cảm ơn!

Trả lời

14

Bạn ghi đè tệp trước tail thậm chí bắt đầu đọc nó. Shell xử lý toán tử chuyển hướng >, bằng cách xóa tệp trước. Sau đó, nó chạy tail mà không có dữ liệu để đọc.

Bạn có thể giải quyết điều này bằng cách sử dụng một tập tin tạm thời:

tail -2000 logfile.txt >logfile.tmp 
mv logfile.tmp logfile.txt 
+0

'> logfile.txt' - có nghĩa là tạo tệp mới –

+2

có nhưng nếu tên tệp giống với đầu vào, nó sẽ ghi đè lên nó – Patonza

+0

Điều này chỉ hoạt động nếu quá trình ghi vào logfile đóng bộ mô tả tệp của nó. Điển hình, nhưng không phải lúc nào cũng đúng. – NVRAM

1

Greg Hewgill là đúng, logfile.txt đã được cắt ngắn trước đuôi có thể làm việc trên đó.

thử:

tail -2000 logfile.txt > logfile2.txt; rm -f logfile.txt; mv logfile2.txt logfile.txt 
+0

Trong trường hợp này 'rm' là không cần thiết vì' mv' sẽ hủy liên kết tệp đích trong khi đổi tên. –

+0

Phải ... Tôi chỉ đang thừa: P – Patonza

+0

Điều này chỉ hoạt động nếu quá trình ghi vào logfile đóng bộ mô tả tệp của nó. Điển hình, nhưng không phải lúc nào cũng đúng. – NVRAM

9

Thay vì làm điều này với tập tin cron riêng của bạn, bạn có thể muốn xem xét sử dụng logrotate kiếm một giải pháp mạnh mẽ hơn. Bạn có thể xoay các bản ghi, kiểm soát thời gian giữ chúng, gửi email, nén nhật ký cũ và chạy tập lệnh sau đó nếu bạn muốn.

Xem người đàn ông trang here hoặc loại man logrotate từ dòng lệnh

Tạo một file logrotate mới trong thư mục /etc/logrotate.d/ của bạn. Dưới đây là một ví dụ:

/var/logs/myapp/logfile.txt { 
    # keep the 5 latest rotations of the log 
    rotate 5 
    # rotate once the file is bigger than 2k 
    size 2k 
    # don't error if the file isn't there 
    missingok 
    # compress rotated (old) log files 
    compress 
    # set ownership and permissions on the new log file 
    create 0640 myuser myuser 
} 
10

Có một vấn đề với các giải pháp chấp nhận nếu quá trình giữ log file mở; về cơ bản bạn cần sử dụng lại i-nút. Phản ứng của Mmrobins là tốt, logrotate nên làm điều đúng.

Để sử dụng đuôi, bạn có thể làm điều gì đó (tương tự như ý tưởng của Greg Pantonza của &), nhưng giữ lại các tập tin ban đầu bằng cách cắt bỏ các tập tin ban đầu tại chỗ:

tail -2000 logfile.txt >logfile.tmp 
cat logfile.tmp > logfile.txt 
rm logfile.tmp 

Để tránh một tập tin tạm thời, bạn có thể đọc vào một biến, sau đó ghi lại nó:

bash -c 'X=$(tail -2000 logfile.txt);echo "$X">logfile.txt' 

Trong mọi trường hợp, có khả năng xảy ra tình trạng cuộc đua giữa quá trình cắt ngắn và quá trình thêm vào tệp. Không chắc chắn nếu logrotate xử lý rằng, không có giải pháp nào trong số đuôi ở đây thực hiện.

4

Đây là một giải pháp khác, mà không đối phó với các file tmp:

echo "`tail -2000 logfile.txt`" > logfile.txt 
+0

Tôi gặp sự cố khi tôi cố gắng cắt bớt một tệp có bộ mô tả tệp mở. Vì vậy, một tập tin tmp không phải là một lựa chọn. Cảm ơn! –

1

Nếu bạn là người dùng vim sau đó lựa chọn khác là sử dụng vi thay vì tail, để hoạt động trên các tập tin trực tiếp:

vi "+execute \"normal! G2000kO\<esc>dgg\"" "+w" "+q" logfile.txt 

Chuỗi G2000kO\<esc>dgg chỉ đơn giản là đầu vào bàn phím bạn sẽ sử dụng để thực hiện việc này với vi (nút thoát phải được thoát). Nó rất trực quan để sử dụng và bao gồm một loạt các trường hợp sử dụng.

vi cũng xử lý các tệp văn bản lớn (10+ GB) mà không bị chậm lại, vì vậy phương pháp này rất mạnh mẽ.

Các vấn đề liên quan