如何在linux

时间:2017-12-17 10:34:45

标签: linux bash logrotate

我有一个应用程序,它将写入特定的日志文件,直到用户会话继续进行。 我正在寻找的是对日志文件的大小设置最大上限,使其不会超出特定的大小,2个场景将是有用的

  1. 任何注意日志文件的实用程序,一旦达到最大大小,就会从一开始就截断文件内容,以便应用程序可以在最后添加内容。

    < / LI>
  2. 在创建文件时,我可以指定该文件的最大大小的任何实用程序,当文件达到maxsize时,它应该不会超过该点。

  3. 我不想要的是

    1. 设置一个cron作业或脚本,它将在特定的时间间隔(比如1小时)后监视文件大小,然后在那时删除其内容。

3 个答案:

答案 0 :(得分:2)

作为一个shellcript:

file=file_to_watch
maxsize=98765
truncsice=8765
while : ; do
    inotifywait -e modify "$file"
    filesize=$(du "$file")
    if  [ $filesize -gt $maxsize ] ; then
        tail -c $truncsize "$file" > /tmp/truncatedfile.$$
        mv /tmp/truncatedfile.$$ "$file"
    fi
done

请注意,您可能会遇到一些可能导致丢失日志数据的竞争条件。

答案 1 :(得分:0)

删除文件的一部分然后让您附加更多数据的过程几乎不可能在任何系统上使用,即使有可能,但这并不是一个人要做的事情。它可以在内核级别完成,而且确实有效,但我也从未见过。 (即内核将只是从文件开头取消索引节点的链接,而在文件的第一个索引节点中就字节能力有一个偏移量,与分页能力相对。)

在Unix系统上,可以为此目的使用mmap()unmap()。所以当您的应用程序。确定文件大小超过一定数量,则必须从文件开头读取,确定日志的第10,000行的位置,然后将其余部分memmove() {开始。最后,它将截断文件并以追加模式将其重新打开。最后一步是非常重要的一步...

// WARNING: code without any error checking
// if multiple processes may run in parallel, make sure to use a lock as well
int fd = open("/var/log/mylog.log", O_RDWR);
ssize_t size = lseek(fd.get(), 0, SEEK_END);
lseek(fd.get(), 0, SEEK_SET);
char * start = (char *)mmap(nullptr,
                            size,
                            PROT_READ | PROT_WRITE, MAP_SHARED,
                            fd,
                            0);
char * end = start + size;
char * l10000 = start; // search line 10,000
for(int line(0); line < 10000; ++line)
{
    for(; l10000 < end && *l10000 != '\n'; ++l10000);
    if(*l10000 == '\n')
    {
        ++l10000; // skip the '\n'
    }
}
ssize_t new_size = end - l10000;
memmove(start, l10000, new_size);
truncate(fd, new_size);
close(fd);

(在GitHub上的sendmail::dequeue()中找到了示例,其中包括此处未找到的所有错误检查。)

重要提示:memmove()调用将,特别是在相当大的日志文件上。

请注意,大多数情况下,当进程打开日志文件时,它将保持打开状态,这意味着更改文件在脚下不会有什么用。实际上,在此处的mmap()示例中,如果不确定确保关闭并重新打开日志,您将在移动的数据和下一次写入之间创建一个带有许多零(\0字符)的间隙。代码中未显示)。

因此,它在代码中是可行的(尽管在C ++中,您可以很容易地在C中进行编译。)但是,如果您只想使用bashlogrotate当然是您的最佳选择打赌。但是,默认情况下,至少在Ubuntu上,logrotate每天仅运行一次。您可以专门针对使用您的应用程序或系统范围内的用户进行更改。

至少您可以每小时通过移动或复制logrotate脚本来每小时运行一次,如下所示:

sudo cp /etc/cron.daily/logrotate /etc/cron.hourly/logrotate

您还可以设置一个运行该脚本的每分钟CRON文件。要编辑crontab根文件,请执行以下操作:

sudo crontab -u root -e

然后添加一行:

* * * * *   root    /etc/cron.daily/logrotate

请确保进行测试,并确保其可以正常工作。如果添加了这样的脚本,还可以从此处删除/etc/cron.daily/logrotate脚本,这样它就不会尝试运行两次(“每日”运行一次,每分钟运行一次)。

请注意,如我对Ubuntu的bug report所示,CRON中存在一个挥之不去的错误。过多使用CRON(例如每分钟一次)会导致内存问题。

此外,如先前在上面的代码示例中所述,您必须重新打开日志文件。除非应用程序在每次要写入日志文件时重新打开日志文件,或者被告知要旋转(即关闭旧文件并打开新文件),否则只是旋转不会对您有任何好处。应用程序将继续将数据追加到旧文件中,而无论其名称如何。 Unix记得,因为打开文件后便使用了索引节点,而不是文件名。 (在MS-Windows下,如果不先关闭对文件的所有访问权限,就无法重命名...这很烦人!)

在许多情况下,您要么重新启动整个应用程序。 (因为它太笨了,以至于不知道如何重新打开日志),您可以发送该应用程序。信号,以便重新打开日志文件或应用。知道文件已更改,以某种方式...

如果是应用程序。无法或不知道,重新启动将是您唯一的选择。如果用户具有UI,对于用户来说可能会很奇怪。

答案 2 :(得分:0)

truncate -s 10M log.txt怎么样?

检查man truncate以获得更多详细信息