首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在linux中设置特定文件的最大大小

如何在linux中设置特定文件的最大大小
EN

Stack Overflow用户
提问于 2017-12-17 18:34:45
回答 3查看 4.5K关注 0票数 2

我有一个应用程序,它将写入特定的日志文件,直到用户会话正在进行。我正在寻找的是对日志文件的大小设置最大上限,这样它就不会超过特定的大小,两种情况将是有用的

  1. 任何监视日志文件的实用程序,一旦达到最大大小,就会从一开始就截断文件内容,以便应用程序可以在末尾继续追加内容。
  2. 任何实用程序,在创建文件时,我可以通过它指定该文件的最大大小,并且当文件达到该最大大小时,它不应增长到超过该点。

我不想要的是

  1. 用于设置cron作业或脚本,这些作业或脚本将在特定时间间隔(例如1小时)后监视文件大小,然后在该时间删除其内容。
EN

回答 3

Stack Overflow用户

发布于 2017-12-19 04:31:19

作为shellscript脚本:

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

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

票数 2
EN

Stack Overflow用户

发布于 2018-07-30 06:56:59

truncate -s 10M log.txt呢?

请查看man truncate了解更多详细信息

票数 1
EN

Stack Overflow用户

发布于 2018-07-30 06:50:06

删除文件的一部分,然后让您附加更多数据的进程在任何系统上几乎都是不可用的,即使它是可能的,但它不是人们所做的事情。它可以在内核级别上完成,并且非常有效,但我也从未见过这一点。(即,内核将简单地取消inode与文件开头的链接,并在文件的第一个inode中具有字节能力的偏移量--而不是分页能力。)

在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()调用将是slow__,特别是在一个相当大的日志文件上。

请注意,大多数情况下,当进程打开日志文件时,它会保持打开状态,这意味着更改它脚下的文件不会有多大效果。实际上,在这里的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脚本,这样它就不会尝试运行两次(一次在“每日”运行,一次在每分钟运行。)

只需注意CRON中有一个挥之不去的bug,就像我在Ubuntu的bug report中显示的那样。当过多使用CRON (比如一分钟一次)时,可能会导致内存问题。

此外,正如前面在代码示例中提到的,您必须重新打开日志文件。只是旋转不会对你有任何好处,除非应用程序在每次想要写入日志文件时重新打开它,或者它被告知旋转(即关闭旧文件并打开新文件)。如果没有这种循环,应用程序将继续将数据附加到旧文件,无论它是什么名称。Unix记住这一点,因为它在打开文件时使用的是inode,而不是文件名。(在MS-Windows下,如果不先关闭对文件的所有访问权限,您将无法重命名...这非常烦人!)

在许多情况下,你要么重启整个应用程序。(因为它太愚蠢了,不知道如何重新打开日志),你发送应用程序。一个信号,以便它重新打开日志文件或应用程序。意识到文件发生了变化,不知何故...

如果这个应用。是不能或不知道的,重新启动将是您唯一的选择。如果它有一个UI,这对用户来说可能会很奇怪。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47854230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档