在Linux中将文件内容复制到新文件

3
我想知道如何使用Linux命令将文件(server.log)的所有内容复制到一个新文件中,并从原始文件中删除该内容。实际上,这很容易做到。但我确实希望确保在操作过程中不会更新内容。以下Linux命令执行我想要的操作,但我必须确保在command1-command2执行期间server.log没有更改。
command1: #cp server.log serverNew.log 
command2: #truncate -l 0 server.log
5个回答

4
我会使用专门为此目的构建的工具,而不是使用一些临时解决方案。
请查看logrotate。您可以直接使用命令或设置cron作业。
它支持压缩,每次旋转后运行命令,基于大小或时间旋转等等……
根据您在下面的评论中的说明,我假设您对以下选项感兴趣: postrotate/endscriptpostrotateendscript之间的行(两者都必须单独出现在行上)在日志文件旋转后执行(使用/bin/sh)。这些指令只能出现在日志文件定义内。通常,日志文件的绝对路径作为第一个参数传递给脚本。如果指定了sharedscripts,则整个模式将传递给脚本。有关错误处理,请参见sharedscriptsnosharedscriptsprerotate/endscriptprerotateendscript之间的行(两者必须出现在单独的行上)将在日志文件被轮换并且仅当日志实际被轮换时执行(使用/bin/sh)。这些指令只能出现在日志文件定义内部。通常,日志文件的绝对路径作为第一个参数传递给脚本。如果指定了sharedscripts,整个模式将传递给脚本。另请参见postrotate。有关错误处理,请参见sharedscriptsnosharedscripts

1
你说得对。应该使用特殊工具。我的解决方案是:

cp server.log serverNew.log; truncate -s 0 server.log

但在创建serverNew.log文件后,我会将其压缩并签名。
- Ahmet Karakaya
logrotate会给我新创建的文件的名称吗?还是它会执行额外的操作,例如压缩和运行其他脚本? - Ahmet Karakaya
它有很多很多选项。只需查看logrotate的手册页,man logrotate即可。 - Eric des Courtis
在我的回答中为你添加了一些信息。 :) - Eric des Courtis

0

不要复制,而是重命名(使用mv)。重命名在文件系统级别上是原子的,因此任何使用旧名称写入文件的应用程序都不会发生冲突。


我必须保留原始文件,因为该文件被一个名为Glassfish的应用程序使用。如果我删除或移动它,甚至创建一个同名的新文件,应用程序都无法写入其输出。 - Ahmet Karakaya
@mmc18 这意味着应用程序仍然打开文件,很可能即使名称不同,它也可能继续向“mv”文件追加(在这种情况下,您在原始问题中的方法也可能无法按预期工作)。如果您真的想避免丢失任何条目,您将不得不关闭应用程序,然后根据需要进行“mv”/“cp”/“touch”,然后重新启动应用程序。或者使用“logrotate”在预定时间自动执行此操作。 - twalberg

0

您可以同时使用以下命令:cp oldFile newFile; cat '' >> oldFile
cp 命令用于复制文件。第二个命令在第一个命令执行后用于覆盖原始文件。

显然,如果您的“程序”(或脚本)一旦将旧文件的内容复制到新文件中,就会以写入方式打开文件(而不是写入和追加),则第二个命令就不必要了。
此外,对于 >> 重定向,您必须验证 noclobber 选项是否设置为“off”(1)。


我必须保留原始文件,因为该文件被一个名为Glassfish的应用程序所使用。如果我将其移除甚至创建一个同名的新文件,应用程序将不会写其输出。 - Ahmet Karakaya
cat '' >> oldFile 不会向 oldFile 中追加任何内容。cat(显然)无法打开该无名文件,因此不会追加任何内容。使用 echo -n '' >oldFile 命令可以清空 oldFile 中的内容。 - Cobra_Fast

0

这里有一个简单的C应用程序,它(可能)会做你想要的事情:

#include <stdlib.h>
#include <stdio.h>
#include <sys/file.h>

void main (int argc, char** argv)
{
    if (argc != 2)
        exit(1);

    FILE* fi = fopen(argv[1], "rb+");
    FILE* fo = fopen(argv[2], "wb");

    if (fi != NULL && fo != NULL && flock(fi, LOCK_EX) == 0)
    {
        while (feof(fi) == 0)
        {
            char* buf = malloc(4096);
            int bRead = 0;
            bRead = fread(buf, 1, 4096, fi);
            fwrite(buf, 1, bRead, fo);
        }

        frewind(fi);
        fputc(10, fi);

        flock(fi, LOCK_UN);
        fclose(fi);
        fclose(fo);
    }
else exit(1);

exit(0);
}

调用方式: ./a.out oldfile newfile

警告:我实际上并没有测试过这段代码,请务必在将其用于任何重要工作之前进行一些测试

或者,您还可以尝试使用shell工具flockhttp://linux.die.net/man/1/flock


0

之后,您可以使用touch命令来确保

command3: #touch server.log

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接