现象:某个现场 odbc.ini 莫名其妙被清空,偶发情况,大概几周出现一次。
unixodbc官网地址–> https://www.unixodbc.org/
//2.3.7
BOOL _odbcinst_SystemINI( char *pszFileName, BOOL bVerify )
{
FILE *hFile;
char b1[ ODBC_FILENAME_MAX + 1 ];
sprintf( pszFileName, "%s/odbc.ini", odbcinst_system_file_path( b1 ));
if ( bVerify )
{
/* try opening for read */
hFile = uo_fopen( pszFileName, "r" );
if ( hFile )
uo_fclose( hFile );
else
{
//可能是文件描述符到上限了或者其它情况导致打开失败,并不是文件真的不存在,没有做这些场景的处理
//比如服务以普通用户运行,进程打开文件描述符上限为4096。
//此时进程打开文件描述符已经达到上限会出现以下情况
//第一个if判断时 超过打开上限 uo_fopen失败而进入else分支判断 此时如果进程释放了几个句柄 进程打开的文件描述数量小于4096了 再次uo_fopen成功了
//然后这里以w方式uo_fopen(底层封装的是系统的open函数)文件会清空odbc.ini
/* does not exist so try creating it */
hFile = uo_fopen( pszFileName, "w" );
if ( hFile )
uo_fclose( hFile );
else
return FALSE;
}
}
return TRUE;
}
//odbc官网2.3.8版本说明修复了2.3.7的bug对文件打开失败产生的错误码进行了判断
//没能下载到2.3.8的代码 此处代码为2.3.11
BOOL _odbcinst_SystemINI( char *pszFileName, BOOL bVerify )
{
FILE *hFile;
char b1[ ODBC_FILENAME_MAX + 1 ];
sprintf( pszFileName, "%s/odbc.ini", odbcinst_system_file_path( b1 ));
if ( bVerify )
{
/* try opening for read */
hFile = uo_fopen( pszFileName, "r" );
if ( hFile )
{
uo_fclose( hFile );
}
else
{
if ( ( !hFile ) &&
( errno != ENFILE ) && ( errno != EMFILE ) &&
( errno != ENOMEM ) && ( errno != EACCES ) &&
( errno != EFBIG ) && ( errno != EINTR ) &&
( errno != ENOSPC ) && ( errno != EOVERFLOW ) &&
( errno != EWOULDBLOCK ))
{
return FALSE;
}
/* does not exist so try creating it */
hFile = uo_fopen( pszFileName, "w" );
if ( hFile )
uo_fclose( hFile );
else
return FALSE;
}
}
return TRUE;
}
对比下不同版本的代码还是很明显的能看出问题所在
我们的思路是:
1 排查用到了linux的监控服务 audit配置规则自行百度 发现我们的模块修改odbc.ini文件
2 排查了自己服务和链接的静态库的所有代码没有操作odbc.ini的代码,转而怀疑系统的odbc库
3 去odbc官网查看修复信息。下载相应版本代码查看关键字 “odbc.ini” 发现了此处的代码
4 官方在2.3.8已经修复了