Skip to content

Commit cc4a50d

Browse files
authored
add option to daemonize, log to file and syslog (#70)
1 parent 23eae75 commit cc4a50d

File tree

2 files changed

+101
-12
lines changed

2 files changed

+101
-12
lines changed

cmd/pktvisord/main.cpp

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#include "visor_config.h"
1212
#include <docopt/docopt.h>
1313
#include <resolv.h>
14+
#include <spdlog/sinks/basic_file_sink.h>
1415
#include <spdlog/sinks/stdout_color_sinks.h>
16+
#include <spdlog/sinks/syslog_sink.h>
1517
#include <spdlog/spdlog.h>
1618

1719
#include "GeoDB.h"
@@ -38,12 +40,16 @@ static const char USAGE[] =
3840
--admin-api Enable admin REST API giving complete control plane functionality [default: false]
3941
When not specified, the exposed API is read-only access to summarized metrics.
4042
When specified, write access is enabled for all modules.
43+
-d Daemonize; fork and continue running in the background [default: false]
4144
-h --help Show this screen
4245
-v Verbose log output
4346
--no-track Don't send lightweight, anonymous usage metrics.
4447
--version Show version
45-
--geo-city FILE GeoLite2 City database to use for IP to Geo mapping (if enabled)
46-
--geo-asn FILE GeoLite2 ASN database to use for IP to ASN mapping (if enabled)
48+
--geo-city FILE GeoLite2 City database to use for IP to Geo mapping
49+
--geo-asn FILE GeoLite2 ASN database to use for IP to ASN mapping
50+
Logging Options:
51+
--log-file FILE Log to the given output file name
52+
--syslog Log to syslog
4753
Prometheus Options:
4854
--prometheus Enable native Prometheus metrics at path /metrics
4955
--prom-instance ID Optionally set the 'instance' tag to ID
@@ -77,6 +83,70 @@ void initialize_geo(const docopt::value &city, const docopt::value &asn)
7783
}
7884
}
7985

86+
// adapted from LPI becomeDaemon()
87+
int daemonize()
88+
{
89+
switch (fork()) {
90+
case -1:
91+
return -1;
92+
case 0:
93+
// Child falls through...
94+
break;
95+
default:
96+
// while parent terminates
97+
_exit(EXIT_SUCCESS);
98+
}
99+
100+
// Become leader of new session
101+
if (setsid() == -1) {
102+
return -1;
103+
}
104+
105+
// Ensure we are not session leader
106+
switch (auto pid = fork()) {
107+
case -1:
108+
return -1;
109+
case 0:
110+
break;
111+
default:
112+
std::cerr << "pktvisord running at PID " << pid << std::endl;
113+
_exit(EXIT_SUCCESS);
114+
}
115+
116+
// Clear file mode creation mask
117+
umask(0);
118+
119+
// Change to root directory
120+
chdir("/");
121+
int maxfd, fd;
122+
maxfd = sysconf(_SC_OPEN_MAX);
123+
// Limit is indeterminate...
124+
if (maxfd == -1) {
125+
maxfd = 8192; // so take a guess
126+
}
127+
128+
for (fd = 0; fd < maxfd; fd++) {
129+
close(fd);
130+
}
131+
132+
// Reopen standard fd's to /dev/null
133+
close(STDIN_FILENO);
134+
135+
fd = open("/dev/null", O_RDWR);
136+
137+
if (fd != STDIN_FILENO) {
138+
return -1;
139+
}
140+
if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) {
141+
return -1;
142+
}
143+
if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) {
144+
return -1;
145+
}
146+
147+
return 0;
148+
}
149+
80150
int main(int argc, char *argv[])
81151
{
82152

@@ -85,7 +155,26 @@ int main(int argc, char *argv[])
85155
true, // show help if requested
86156
VISOR_VERSION); // version string
87157

88-
auto logger = spdlog::stdout_color_mt("pktvisor");
158+
if (args["-d"].asBool()) {
159+
if (daemonize()) {
160+
std::cerr << "failed to daemonize" << std::endl;
161+
exit(EXIT_FAILURE);
162+
}
163+
}
164+
165+
std::shared_ptr<spdlog::logger> logger;
166+
if (args["--log-file"]) {
167+
try {
168+
logger = spdlog::basic_logger_mt("pktvisor", args["--log-file"].asString());
169+
} catch (const spdlog::spdlog_ex &ex) {
170+
std::cerr << "Log init failed: " << ex.what() << std::endl;
171+
exit(EXIT_FAILURE);
172+
}
173+
} else if (args["--syslog"].asBool()) {
174+
logger = spdlog::syslog_logger_mt("pktvisor", "pktvisord", LOG_PID);
175+
} else {
176+
logger = spdlog::stdout_color_mt("pktvisor");
177+
}
89178
if (args["-v"].asBool()) {
90179
logger->set_level(spdlog::level::debug);
91180
}
@@ -151,7 +240,7 @@ int main(int argc, char *argv[])
151240
initialize_geo(args["--geo-city"], args["--geo-asn"]);
152241
} catch (const std::exception &e) {
153242
logger->error("Fatal error: {}", e.what());
154-
exit(-1);
243+
exit(EXIT_FAILURE);
155244
}
156245

157246
if (args["IFACE"]) {
@@ -195,21 +284,21 @@ int main(int argc, char *argv[])
195284

196285
} catch (const std::exception &e) {
197286
logger->error(e.what());
198-
exit(-1);
287+
exit(EXIT_FAILURE);
199288
}
200289
} else if (!args["--admin-api"].asBool()) {
201290
// if they didn't specify pcap target, or config file, or admin api then there is nothing to do
202291
logger->error("Nothing to do: specify --admin-api or IFACE.");
203292
std::cerr << USAGE << std::endl;
204-
exit(-1);
293+
exit(EXIT_FAILURE);
205294
}
206295

207296
try {
208297
svr.start(host.c_str(), port);
209298
} catch (const std::exception &e) {
210299
logger->error(e.what());
211-
exit(-1);
300+
exit(EXIT_FAILURE);
212301
}
213302

214-
return 0;
303+
exit(EXIT_SUCCESS);
215304
}

src/HttpServer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,31 @@ class HttpServer : public httplib::Server
2020

2121
Server &Get(const char *pattern, Handler handler)
2222
{
23-
spdlog::info("Registering GET {}", pattern);
23+
spdlog::get("pktvisor")->info("Registering GET {}", pattern);
2424
return httplib::Server::Get(pattern, handler);
2525
}
2626
Server &Post(const char *pattern, Handler handler)
2727
{
2828
if (_read_only) {
2929
return *this;
3030
}
31-
spdlog::info("Registering POST {}", pattern);
31+
spdlog::get("pktvisor")->info("Registering POST {}", pattern);
3232
return httplib::Server::Post(pattern, handler);
3333
}
3434
Server &Put(const char *pattern, Handler handler)
3535
{
3636
if (_read_only) {
3737
return *this;
3838
}
39-
spdlog::info("Registering PUT {}", pattern);
39+
spdlog::get("pktvisor")->info("Registering PUT {}", pattern);
4040
return httplib::Server::Put(pattern, handler);
4141
}
4242
Server &Delete(const char *pattern, Handler handler)
4343
{
4444
if (_read_only) {
4545
return *this;
4646
}
47-
spdlog::info("Registering DELETE {}", pattern);
47+
spdlog::get("pktvisor")->info("Registering DELETE {}", pattern);
4848
return httplib::Server::Delete(pattern, handler);
4949
}
5050
};

0 commit comments

Comments
 (0)