避免在Solaris OS上重写文件

时间:2016-05-27 09:52:03

标签: c linux solaris

我遇到了某些C库函数的问题(顺便说一下,我无法访问的源代码)正在记录到文件中。这些库的某些版本使用附加到日志文件的函数进行编译。但以前的那些根本没有附加。

是否有某种方式(例如在Linux中使用chattr)以及#34;强制"进入附加模式的操作?我不允许对文件进行任何特定的操作,比如在使用这些库重新启动代理之前复制它们...所以我唯一的选择是强制这些函数附加到文件而不管它们是如何进行的已被编程打开它们。

感谢。

4 个答案:

答案 0 :(得分:2)

一种方法是使用会导致libc fopenopen函数重载的interposing dynamic library,并在请求时动态更改其模式参数文件是目标之一。 Here是一个精确插入fopen电话的示例,可以轻松适应您的需求。

或者,您可以在所谓的破坏性模式中使用dtrace拦截相同的打开调用,并在运行时修补参数或在覆盖之前备份文件。

Here是一个类似黑客的例子。

答案 1 :(得分:1)

我能想象的唯一可能的解决方法是在创建日志文件后立即重命名。由于程序有一个打开的文件描述符,它可以继续在那里写,但下一个打开将创建一个不同的文件。

例如,您可以使用守护程序进程扫描日志文件所在的目录,并在找到日志文件后立即对其进行适当重命名。

答案 2 :(得分:1)

在Solaris 11及更高版本中,您要查找的chattr命令的等效项是chmod S+vappendonly file,但必须以root身份完成,并且会导致尝试覆盖现有数据或打开文件在错误的模式下获取错误而不是仅仅将操作转换为静默附加,因此可能无法使用某些应用程序(例如, vi 不适用于此类文件)。

答案 3 :(得分:0)

由于所有答案都涉及某种类型的kludges和hacks,所以这里是我的:

  • 创建日志"文件"作为命名管道,使用mkfifo
  • 运行流程 从命名管道中读取并做任何事情,但追加它 读取真实的日志文件。
  • 测试应用程序以确保其有效。

这可以很好地完成"过程":

#!/bin/sh
while [ 1 ]; do
    cat /this/is/a/named/pipe/fake/log/file >> /this/is/the/real/log/file
done

是的,我知道。为"Useless use of cat"提供奖励。

或者,您可以尝试这样的C代码,它只能读取某些东西(可能是常规文件或FIFO),并将读取的任何内容转储到新文件,并在收到SIGHUP后重新打开该文件:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
// start with invalid descript so close() doesn't break things
int logFileFD = -1;
const char *logFileName = NULL;
void openLogFile( int sig )
{
    close( logFileFD );
    logFileFD = open( logFileName, O_WRONLY | O_CREAT | O_APPEND, 0644 );
}
void installSigHandler( void )
{
    struct sigaction sa;
    sigemptyset( &sa.sa_mask );
    // do NOT restart system calls
    sa.sa_flags = 0;
    sa.sa_handler = openLogFile;
    sigaction( SIGHUP, &sa, NULL );
}
int main( int argc, char **argv )
{
    logFileName = argv[ 2 ];
    openLogFile( SIGHUP );
    installSigHandler();
    int fifoFD = open( argv[ 1 ], O_RDONLY );
    for ( ;; )
    {
        char buffer[ 8 * 1024 ];
        ssize_t bytes = read( fifoFD, buffer, sizeof( buffer ) );
        if ( bytes > 0L ) write( logFileFD, buffer, bytes );
    }
}

我真的压缩了那段代码并且几乎没有关闭所有错误检查以摆脱任何滚动条。