文字コードSHIFT_JIS、改行コードLFのログを監視する方法について
いつもお世話になっております。
表題の件について、質問させてください。
ZabbixよりWindowsサーバー内にあるログを監視しようとしております。
ただ、そのログファイルの文字コードがSHIFT_JISで改行コードがLFとなっており、
ログ監視アイテム設定でSHIFT_JISを設定しても、改行コードが認識されていないらしく
監視データ⇒最新データより確認しても1行目しか値が取得できておりません。
ログを吐き出すアプリの仕様で文字コードや改行コードの変更は出来ないため、
試しに手動で該当ログファイルの改行コードだけをCR+LFに変更したところ正常に値を取得できました。
解決策としてどういった方法があるのでしょうか?
隠しオプション等ございますでしょうか?
・アイテム設定
タイプ:Zabbixエージェント(アクティブ)
キー:log[C:\test\test.log,,SHIFT_JIS]
データ型:ログ
更新間隔(秒):1
ヒストリ保存期間(日):90
・利用環境
Zabbix-server2.2.1(CentOS6.4)
Zabbix-agent2.2.1(Windows 2008 R2)
大変お手数ですが、宜しくお願い致します。
KAZ - 投稿数: 1085
zakiyamaさん
SHIFT_JISを設定しても、改行コードが認識されていない
ログ読んでいるところのZabbix2.2.1のソース見てみました。
改行判定が以下の通りになってます。
LF (Unix)
CR (Mac)
CR+LF (Windows)
なので、今のソースだとWindowsで改行がLFのみだと改行と判定しませんね…
Zabbixを改造するか、ログ出力を何とかすしか手がないかと…
以下、zbx_read関数です。下の方のコメントに改行判定が書かれてます。
/*
* Reads in at most one less than size characters from a file descriptor and stores them into the buffer pointed to by s.
* Reading stops after a newline. If a newline is read, it is stored into the buffer.
*
* On success, the number of bytes read is returned (zero indicates end of file).
* On error, -1 is returned, and errno is set appropriately.
*/
int zbx_read(int fd, char *buf, size_t count, const char *encoding)
{
size_t i, szbyte;
const char *cr, *lf;
int nbytes;
#ifdef _WINDOWS
__int64 offset;
#else
off_t offset;
#endif
#ifdef _WINDOWS
offset = _lseeki64(fd, 0, SEEK_CUR);
#else
offset = lseek(fd, 0, SEEK_CUR);
#endif
if (0 >= (nbytes = (int)read(fd, buf, count)))
return nbytes;
if (0 == strcasecmp(encoding, "UNICODE") || 0 == strcasecmp(encoding, "UNICODELITTLE") ||
0 == strcasecmp(encoding, "UTF-16") || 0 == strcasecmp(encoding, "UTF-16LE") ||
0 == strcasecmp(encoding, "UTF16") || 0 == strcasecmp(encoding, "UTF16LE"))
{
cr = "\r\0";
lf = "\n\0";
szbyte = 2;
}
else if (0 == strcasecmp(encoding, "UNICODEBIG") || 0 == strcasecmp(encoding, "UNICODEFFFE") ||
0 == strcasecmp(encoding, "UTF-16BE") || 0 == strcasecmp(encoding, "UTF16BE"))
{
cr = "\0\r";
lf = "\0\n";
szbyte = 2;
}
else if (0 == strcasecmp(encoding, "UTF-32") || 0 == strcasecmp(encoding, "UTF-32LE") ||
0 == strcasecmp(encoding, "UTF32") || 0 == strcasecmp(encoding, "UTF32LE"))
{
cr = "\r\0\0\0";
lf = "\n\0\0\0";
szbyte = 4;
}
else if (0 == strcasecmp(encoding, "UTF-32BE") || 0 == strcasecmp(encoding, "UTF32BE"))
{
cr = "\0\0\0\r";
lf = "\0\0\0\n";
szbyte = 4;
}
else /* Single or Multi Byte Character Sets */
{
cr = "\r";
lf = "\n";
szbyte = 1;
}
for (i = 0; i + szbyte <= (size_t)nbytes; i += szbyte)
{
if (0 == memcmp(&buf[i], lf, szbyte)) /* LF (Unix) */
{
i += szbyte;
break;
}
if (0 == memcmp(&buf[i], cr, szbyte)) /* CR (Mac) */
{
if (i + szbyte < (size_t)nbytes && 0 == memcmp(&buf[i + szbyte], lf, szbyte)) /* CR+LF (Windows) */
i += szbyte;
i += szbyte;
break;
}
}
#ifdef _WINDOWS
_lseeki64(fd, offset + i, SEEK_SET);
#else
lseek(fd, offset + i, SEEK_SET);
#endif
return (int)i;
}
zakiyama - 投稿数: 2
KAZ様
お世話になっております。
ソースの確認までして頂いてありがとうございます。
現状ですと、ソースを改造するしかないのですね。。。
アプリから出力されたログに対し改行コードを変換するバッチを作成し、その変換されたログファイルを監視するように検討します。
#タスクスケジューラでは1分間隔しか設定項目が見当たらないので、最大一分検知が遅延する形になりますが。。。
ありがとうございました。