如何充当系统日志接收器?
Howto act as a syslog receiver?
我想成为特定系统日志的接收者。因此,从一个程序中收集所有系统日志消息并将它们推送给用户。
有什么方法可以 "subscribe" 我在 syslog 上获取一个单元的日志消息?
除了看文件什么的。
在我的例子中,它是针对 rsyslog 的,可以通过 omuxsock 模块完成。
omuxsock == "output module unix socket"
这是 rsyslog 的一部分。
该模块 "writes" 将日志记录到一个需要由接收程序创建的 unix 套接字。
编辑:
下面是接收程序的例子:
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
/*
this program acts as a receiver for rsyslog messages.
Just create a .conf file in /etc/rsyslog.d/ with the
following content:
$ModLoad omuxsock
$Template MyForwardTemplate,"%PRI%|%TIMESTAMP%|%HOSTNAME%|%syslogtag%|%msg%"
$OMUxSockSocket /tmp/mysock
*.* :omuxsock:;MyForwardTemplate
*/
vector<string> split(const string &s, char delim) {
stringstream ss(s);
string item;
vector<string> tokens;
while (getline(ss, item, delim)) {
tokens.push_back(item);
}
return tokens;
}
int main(int argc, char* argv[])
{
const char *mysocketpath = "/tmp/mysock";
struct sockaddr_un namesock;
char buffer[512] = { 0 };
int fd;
int ret;
namesock.sun_family = AF_UNIX;
strncpy(namesock.sun_path, (char *)mysocketpath, sizeof(namesock.sun_path));
cerr << "creating the socket ..." << endl;
fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
cerr << "binding it to the socket path ..." << endl;
ret = ::bind(fd, (struct sockaddr *) &namesock, sizeof(struct sockaddr_un));
if(ret != 0) {
cerr << "bind error: " << strerror(errno) << endl;
ret = 1;
goto exit;
}
do {
memset(buffer, 0, 512);
ret = ::read(fd, buffer, 512);
if(ret > 0) {
string s = buffer;
vector<string> v = split(buffer, '|');
if(v.size() == 5)
cerr << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ", " << v[4] << endl;
else {
for(string s : v) {
cerr << s << ", ";
}
cerr << endl;
}
}
} while(ret > 0);
exit:
close(fd);
unlink(mysocketpath);
return ret;
}
我想成为特定系统日志的接收者。因此,从一个程序中收集所有系统日志消息并将它们推送给用户。
有什么方法可以 "subscribe" 我在 syslog 上获取一个单元的日志消息?
除了看文件什么的。
在我的例子中,它是针对 rsyslog 的,可以通过 omuxsock 模块完成。 omuxsock == "output module unix socket" 这是 rsyslog 的一部分。 该模块 "writes" 将日志记录到一个需要由接收程序创建的 unix 套接字。 编辑: 下面是接收程序的例子:
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
/*
this program acts as a receiver for rsyslog messages.
Just create a .conf file in /etc/rsyslog.d/ with the
following content:
$ModLoad omuxsock
$Template MyForwardTemplate,"%PRI%|%TIMESTAMP%|%HOSTNAME%|%syslogtag%|%msg%"
$OMUxSockSocket /tmp/mysock
*.* :omuxsock:;MyForwardTemplate
*/
vector<string> split(const string &s, char delim) {
stringstream ss(s);
string item;
vector<string> tokens;
while (getline(ss, item, delim)) {
tokens.push_back(item);
}
return tokens;
}
int main(int argc, char* argv[])
{
const char *mysocketpath = "/tmp/mysock";
struct sockaddr_un namesock;
char buffer[512] = { 0 };
int fd;
int ret;
namesock.sun_family = AF_UNIX;
strncpy(namesock.sun_path, (char *)mysocketpath, sizeof(namesock.sun_path));
cerr << "creating the socket ..." << endl;
fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
cerr << "binding it to the socket path ..." << endl;
ret = ::bind(fd, (struct sockaddr *) &namesock, sizeof(struct sockaddr_un));
if(ret != 0) {
cerr << "bind error: " << strerror(errno) << endl;
ret = 1;
goto exit;
}
do {
memset(buffer, 0, 512);
ret = ::read(fd, buffer, 512);
if(ret > 0) {
string s = buffer;
vector<string> v = split(buffer, '|');
if(v.size() == 5)
cerr << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ", " << v[4] << endl;
else {
for(string s : v) {
cerr << s << ", ";
}
cerr << endl;
}
}
} while(ret > 0);
exit:
close(fd);
unlink(mysocketpath);
return ret;
}