Cách giới hạn kích thước tệp nhật ký bằng >>


24

Làm cách nào tôi có thể giới hạn kích thước của tệp nhật ký được ghi với >>200MB?

$ run_program >> myprogram.log

1
Bạn có muốn chương trình bị giết sau 200MB không? Hay bạn muốn 200 MB cuối cùng với mọi thứ cũ hơn trong thùng bit?
Aaron D. Marasco

Không, quá trình không thể dừng lại cho đến khi bị giết bằng tay
david

quyết định đi logrotate, cảm ơn mọi người vì những đầu vào có giá trị
david

Câu trả lời:


9

Nếu ứng dụng của bạn (ví dụ. run_program) Không hỗ trợ giới hạn kích thước của tệp nhật ký, thì bạn có thể kiểm tra kích thước tệp định kỳ trong một vòng lặp với một ứng dụng hoặc tập lệnh bên ngoài.

Bạn cũng có thể sử dụng logrotate(8)để xoay các bản ghi của mình, nó có sizetham số mà bạn có thể sử dụng cho mục đích của mình:

Với điều này, tệp nhật ký được xoay khi đạt đến kích thước được chỉ định. Kích thước có thể được chỉ định bằng byte (mặc định), kilobyte (sizek) hoặc megabyte (sizem).


1
+1 Logfiles với thông tin lặp đi lặp lại thường có thể bị nén theo thứ tự độ lớn.
người dùng không xác định

Liệu logrotate cắt ngắn các tập tin, hoặc chỉ đơn giản là sao chép hoặc di chuyển chúng? Bởi vì điều này sẽ chỉ hoạt động nếu tập tin liên quan đến fd bị cắt ngắn. Nếu là mv'd, tệp sẽ tiếp tục phát triển, nếu không liên kết, nó sẽ chỉ được mở và tiếp tục phát triển cho đến khi quá trình thoát khỏi ... bản sao logrotate của IIRC, hủy liên kết và tạo một tệp mới, đó là lý do tại sao người ta thường phải gửi SIGHUP tới dæmons khi nhật ký của họ đã được xoay.
Michael Trausch

Lưu ý rằng ngay cả khi bị cắt ngắn, vẫn có vấn đề nếu tệp không được mở ở chế độ chắp thêm (tệp nhật ký phải luôn được mở ở chế độ chắp thêm, nhưng theo kinh nghiệm của tôi thì thường không)
Random832

Logrotate có thể xoay khi tệp đã đạt đến một kích thước nhất định, hàng ngày, hàng tuần, v.v. Nó cũng có thể nén và bạn có thể sử dụng postscripttùy chọn để gửi cấu hình logrotate sau đó SIGHUPđến chương trình.
laebshade

12

Nếu chương trình của bạn không cần ghi bất kỳ tệp KHÁC nào lớn hơn giới hạn này, bạn có thể thông báo cho kernel về giới hạn này bằng cách sử dụng ulimit. Trước khi bạn chạy lệnh của mình, hãy chạy lệnh này để thiết lập giới hạn kích thước tệp 200 MB cho tất cả quá trình chạy trong phiên shell hiện tại của bạn:

ulimit -f $((200*1024))

Điều này sẽ bảo vệ hệ thống của bạn nhưng nó có thể gây nhiễu cho chương trình ghi tệp. Như Eyazici gợi ý , hãy xem xét việc thiết lập logrotateđể cắt tỉa các tệp nhật ký một khi chúng đạt đến một kích thước hoặc độ tuổi nhất định. Bạn có thể loại bỏ dữ liệu cũ hoặc lưu trữ dữ liệu đó trong một khoảng thời gian trong một loạt các tệp nén.


điều này giới hạn kích thước của bất kỳ tập tin nào được viết bởi chương trình
Kim

Thật. Nếu chương trình có nhu cầu chính đáng để ghi các tệp lớn khác, bạn sẽ cần một giải pháp khác.
Caleb

6

Bạn có thể tạo một hình ảnh hệ thống tập tin mới, gắn kết nó bằng thiết bị lặp và đặt tệp nhật ký vào hệ thống tập tin đó:

dd if=/dev/zero of=./200mb.img bs=1024 count=200000 # create new empty 200MB file
mkfs.ext2 200mb.img # or ext3, or whatever fits your needs
mkdir logs
sudo mount -t ext2 -o loop 200mb.img logs # only root can do '-o loop' by default
run_program >>logs/myprogram.log

Bạn cũng có thể sử dụng tmpfsthay vì một tập tin, nếu bạn có đủ bộ nhớ.


Ý tưởng sáng tạo ... để lại cho chương trình những việc cần làm khi hết.
Aaron D. Marasco

6

Bạn có thể cắt đầu ra với head:

size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log

Rất sáng tạo. Chỉ cần lưu ý rằng điều này sẽ chỉ hoạt động để giới hạn dữ liệu MỚI được ghi vào tệp, nó sẽ không tính đến việc tệp đã lớn hay nhỏ.
Caleb

2
Lưu ý rằng có khả năng điều này sẽ giết chương trình (với SIGPIPE) một khi nó đã đạt đến giới hạn kích thước, thay vì loại bỏ dữ liệu.
Random832

1
Tôi đã suy nghĩ tương tự với một số ddma thuật nhưng yeah @ Random832 là đúng, bạn sẽ nhận được một SIGPIPEnhư head/ dd/ whatevergiọt nó.
Aaron D. Marasco

Điều gì về việc bỏ qua nó với một trap '' SIGPIPE?
tuxce

Hoặc đường ống thay thế để { head -c "$size" >> log; cat > /dev/null; }.
Stéphane Chazelas

5

Trong gói apache2-utilslà tiện ích hiện tại được gọi rotatelogs, nó có thể hữu ích cho bạn.

Tóm tắc:

rotatelogs [-l] [-L linkname ] [-p chương trình ] [-f] [-t] [-v] [-e] [-c] [-n number-of-files ] logfile rotationtime | kích thước tệp (B | K | M | G) [ offset ]

Thí dụ:

your_program | rotatelogs -n 5 /var/log/logfile 1M

Hướng dẫn đầy đủ bạn có thể đọc trên liên kết này .


Các liên kết là không tồn tại.
Alexander Gonchiy

1

Tôi chắc chắn các poster ban đầu đã tìm thấy một giải pháp. Đây là một cái khác cho những người khác có thể đọc chủ đề này ...

Curtail giới hạn kích thước của đầu ra của chương trình và bảo toàn 200 MB đầu ra cuối cùng bằng lệnh sau:

$ run_program | curtail -s 200M myprogram.log

Tài liệu tham khảo

LƯU Ý: Tôi là người duy trì repo trên. Chỉ cần chia sẻ giải pháp ...


Tôi thích ý tưởng của curtail. Tôi không quen thuộc với C, vậy có cơ hội cung cấp nhị phân cho nó không? hoặc ít nhất là hướng dẫn chi tiết về cách cài đặt nó?
Felipe

0

Vì nó là văn bản, tôi sẽ viết một kịch bản bằng ngôn ngữ yêu thích của bạn và chuyển nó sang đó. Yêu cầu nó xử lý tệp I / O (hoặc giữ tất cả trong bộ nhớ và sau đó kết xuất SIGHUPhoặc tương tự). Vì thế, thay vì 200 MB, tôi sẽ nghĩ đến một số dòng 'hợp lý' để theo dõi.


Giữ 200MB dữ liệu nhật ký trong bộ nhớ không vì lý do nào khác ngoài việc có thể cắt bớt nó không phải là cách sử dụng tài nguyên hệ thống rất tốt. Cũng không phải là đếm dòng trên một tệp nhật ký lớn. Tôi sẽ khuyên bạn nên sử dụng các công cụ được xây dựng cho việc này như thế nào sysloglogrotate.
Caleb

0

Các kịch bản sau đây nên làm công việc.

LOG_SIZE=500000
NUM_SEGM=2
while getopts "s:n:" opt; do
  case "$opt" in
    s)
      LOG_SIZE=$OPTARG
      ;;
    n)
      NUM_SEGM=$OPTARG
      ;;
  esac
done
shift $((OPTIND-1))
if [ $# == 0 -o -z "$1" ]; then
    echo "missing output file argument"
    exit 1
fi
OUT_FILE=$1
shift
NUM=1
while :; do
    dd bs=10 count=$(($LOG_SIZE/10)) >> $OUT_FILE 2>/dev/null
    SZ=`stat -c%s $OUT_FILE`
    if [ $SZ -eq 0 ]; then
        rm $OUT_FILE
        break
    fi
    echo -e "\nLog portion finished" >> $OUT_FILE
    mv $OUT_FILE $OUT_FILE.n$NUM
    NUM=$(($NUM + 1))
    [ $NUM -gt $NUM_SEGM ] && NUM=1
done

Nó có một vài đường tắt rõ ràng, nhưng nhìn chung nó làm những gì bạn yêu cầu. Nó sẽ chia khúc gỗ thành một khối có kích thước hạn chế và số lượng khối cũng bị giới hạn. Tất cả có thể được chỉ định thông qua các đối số dòng lệnh. Tệp nhật ký cũng được chỉ định thông qua dòng lệnh.

Lưu ý một gotcha nhỏ nếu bạn sử dụng nó với daemon chuyển thành nền. Sử dụng một đường ống sẽ ngăn daemon đi đến nền. Trong trường hợp này, có một cú pháp (có thể là bash-cụ thể) để tránh sự cố:

my_daemon | ( logger.sh /var/log/my_log.log <&0 & )

Lưu ý <&0, trong khi dường như dư thừa, nó sẽ không hoạt động mà không có điều này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.