我有一个应用程序,它将写入特定的日志文件,直到用户会话正在进行。我正在寻找的是对日志文件的大小设置最大上限,这样它就不会超过特定的大小,两种情况将是有用的
我不想要的是
发布于 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
请注意,您可能会得到一些竞争条件,这可能会导致日志数据丢失。
发布于 2018-07-30 06:56:59
那truncate -s 10M log.txt
呢?
请查看man truncate
了解更多详细信息
发布于 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编译。)但是,如果您只想使用bash
,logrotate
肯定是您最好的选择。然而,默认情况下,至少在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,这对用户来说可能会很奇怪。
https://stackoverflow.com/questions/47854230
复制相似问题