Daemon intended to replace a Cronjob which reads and processes events from a queue
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.
At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <map>
#include <regex>
// daemon functions
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
// logs
#include <fstream>
#include <chrono>
#include <ctime>
#include <iomanip>
void logOutput(std::string);
static void daemon();
std::string exec(const char* cmd);
enum EventAction eventActioned,
eventOne,
eventTwo ;
static std::map<std::string, EventAction> mapValueToEvent;
void initialise();
int main()
syslog(LOG_ERR, "bendaemon has started");
daemon();
initialise();
for(int i = 0; i < 20; ++i)
std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
switch(mapValueToEvent[result])
case eventOne:
// process event one
logOutput("one");
break;
case eventTwo:
// process event two
break;
case eventActioned:
// write some event complete log
logOutput("zero");
sleep(20);
break;
default:
// event not defined. write some error log
break;
syslog(LOG_ERR, "Terminating daemon");
closelog();
return EXIT_SUCCESS;
std::string exec(const char* cmd)
std::array<char, 4096> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get()))
if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
result += buffer.data();
std::regex expression("EXITCODE-0");
if(std::regex_search(result, expression) == 1)
result = "1";
else
result = "0";
return result;
void initialise()
mapValueToEvent["1"] = eventOne;
mapValueToEvent["2"] = eventTwo;
mapValueToEvent["0"] = eventActioned;
void logOutput(std::string value)
std::ofstream logFile;
logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
return;
static void daemon()
pid_t pid;
// Fork off the parent process
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
// On success: The child process becomes session leader
if (setsid() < 0)
exit(EXIT_FAILURE);
//TODO: Implement a working signal handler
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
// Fork off for the second time (detatch from terminal window)
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
umask(0);
// This may need to point to a different directory in the future
chdir("/");
// Close all open file descriptors
for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
close (x);
// Open the log file
openlog("bendaemon", LOG_PID, LOG_DAEMON);
c++ linux
add a comment |Â
up vote
3
down vote
favorite
The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.
At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <map>
#include <regex>
// daemon functions
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
// logs
#include <fstream>
#include <chrono>
#include <ctime>
#include <iomanip>
void logOutput(std::string);
static void daemon();
std::string exec(const char* cmd);
enum EventAction eventActioned,
eventOne,
eventTwo ;
static std::map<std::string, EventAction> mapValueToEvent;
void initialise();
int main()
syslog(LOG_ERR, "bendaemon has started");
daemon();
initialise();
for(int i = 0; i < 20; ++i)
std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
switch(mapValueToEvent[result])
case eventOne:
// process event one
logOutput("one");
break;
case eventTwo:
// process event two
break;
case eventActioned:
// write some event complete log
logOutput("zero");
sleep(20);
break;
default:
// event not defined. write some error log
break;
syslog(LOG_ERR, "Terminating daemon");
closelog();
return EXIT_SUCCESS;
std::string exec(const char* cmd)
std::array<char, 4096> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get()))
if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
result += buffer.data();
std::regex expression("EXITCODE-0");
if(std::regex_search(result, expression) == 1)
result = "1";
else
result = "0";
return result;
void initialise()
mapValueToEvent["1"] = eventOne;
mapValueToEvent["2"] = eventTwo;
mapValueToEvent["0"] = eventActioned;
void logOutput(std::string value)
std::ofstream logFile;
logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
return;
static void daemon()
pid_t pid;
// Fork off the parent process
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
// On success: The child process becomes session leader
if (setsid() < 0)
exit(EXIT_FAILURE);
//TODO: Implement a working signal handler
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
// Fork off for the second time (detatch from terminal window)
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
umask(0);
// This may need to point to a different directory in the future
chdir("/");
// Close all open file descriptors
for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
close (x);
// Open the log file
openlog("bendaemon", LOG_PID, LOG_DAEMON);
c++ linux
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.
At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <map>
#include <regex>
// daemon functions
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
// logs
#include <fstream>
#include <chrono>
#include <ctime>
#include <iomanip>
void logOutput(std::string);
static void daemon();
std::string exec(const char* cmd);
enum EventAction eventActioned,
eventOne,
eventTwo ;
static std::map<std::string, EventAction> mapValueToEvent;
void initialise();
int main()
syslog(LOG_ERR, "bendaemon has started");
daemon();
initialise();
for(int i = 0; i < 20; ++i)
std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
switch(mapValueToEvent[result])
case eventOne:
// process event one
logOutput("one");
break;
case eventTwo:
// process event two
break;
case eventActioned:
// write some event complete log
logOutput("zero");
sleep(20);
break;
default:
// event not defined. write some error log
break;
syslog(LOG_ERR, "Terminating daemon");
closelog();
return EXIT_SUCCESS;
std::string exec(const char* cmd)
std::array<char, 4096> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get()))
if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
result += buffer.data();
std::regex expression("EXITCODE-0");
if(std::regex_search(result, expression) == 1)
result = "1";
else
result = "0";
return result;
void initialise()
mapValueToEvent["1"] = eventOne;
mapValueToEvent["2"] = eventTwo;
mapValueToEvent["0"] = eventActioned;
void logOutput(std::string value)
std::ofstream logFile;
logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
return;
static void daemon()
pid_t pid;
// Fork off the parent process
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
// On success: The child process becomes session leader
if (setsid() < 0)
exit(EXIT_FAILURE);
//TODO: Implement a working signal handler
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
// Fork off for the second time (detatch from terminal window)
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
umask(0);
// This may need to point to a different directory in the future
chdir("/");
// Close all open file descriptors
for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
close (x);
// Open the log file
openlog("bendaemon", LOG_PID, LOG_DAEMON);
c++ linux
The Daemon will read the output from a php command line interface, and process events until there are none left in the queue. Consider the sleep timer arbitrary.
At the moment testOutput.php simple logs some strings to the console, some of which contain "EXITCODE-0", meaning there are no events in the queue.
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
#include <map>
#include <regex>
// daemon functions
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
// logs
#include <fstream>
#include <chrono>
#include <ctime>
#include <iomanip>
void logOutput(std::string);
static void daemon();
std::string exec(const char* cmd);
enum EventAction eventActioned,
eventOne,
eventTwo ;
static std::map<std::string, EventAction> mapValueToEvent;
void initialise();
int main()
syslog(LOG_ERR, "bendaemon has started");
daemon();
initialise();
for(int i = 0; i < 20; ++i)
std::string result = exec("php -f /Users/easysigns/PlayGround/bash/readPhpOutput/testOutput.php");
switch(mapValueToEvent[result])
case eventOne:
// process event one
logOutput("one");
break;
case eventTwo:
// process event two
break;
case eventActioned:
// write some event complete log
logOutput("zero");
sleep(20);
break;
default:
// event not defined. write some error log
break;
syslog(LOG_ERR, "Terminating daemon");
closelog();
return EXIT_SUCCESS;
std::string exec(const char* cmd)
std::array<char, 4096> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
while (!feof(pipe.get()))
if (fgets(buffer.data(), 4096, pipe.get()) != nullptr)
result += buffer.data();
std::regex expression("EXITCODE-0");
if(std::regex_search(result, expression) == 1)
result = "1";
else
result = "0";
return result;
void initialise()
mapValueToEvent["1"] = eventOne;
mapValueToEvent["2"] = eventTwo;
mapValueToEvent["0"] = eventActioned;
void logOutput(std::string value)
std::ofstream logFile;
logFile.open("/Users/easysigns/PlayGround/bash/readPhpOutput/logFile.txt", std::ios_base::app);
std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
logFile << "Time: " << std::put_time(std::localtime(&now), "%F %T") << " Event success: " << value << std::endl;
return;
static void daemon()
pid_t pid;
// Fork off the parent process
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
// On success: The child process becomes session leader
if (setsid() < 0)
exit(EXIT_FAILURE);
//TODO: Implement a working signal handler
signal(SIGCHLD, SIG_IGN);
signal(SIGHUP, SIG_IGN);
// Fork off for the second time (detatch from terminal window)
pid = fork();
// An error occurred
if (pid < 0)
exit(EXIT_FAILURE);
// Success: Let the parent terminate
if (pid > 0)
exit(EXIT_SUCCESS);
umask(0);
// This may need to point to a different directory in the future
chdir("/");
// Close all open file descriptors
for (int x = (int)sysconf(_SC_OPEN_MAX); x >= 0; x--)
close (x);
// Open the log file
openlog("bendaemon", LOG_PID, LOG_DAEMON);
c++ linux
edited Jan 4 at 3:07
Jamalâ¦
30.1k11114225
30.1k11114225
asked Jan 4 at 2:58
pcgben
1383
1383
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
I'm not going to comment on the OS interactions here, just the C++ code in general.
prefer anonymous namespaces to the static keyword
static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:
namespace
void daemon();
std::map<std::string, EventAction> mapValueToEvent;
Prefer using enum class to regular enum
enum class EventAction ...;
This prevents a large number of namespace polution issues, and is just a good habit to build.
prefer using std::unordered_map to std::map
Unless you have a reallllly good reason, std::unordered_map
is almost always preferable.
Why shared_ptr?
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.
initialise() is unnecessary
You can simply initialize the map using a literal:
static std::map<std::string, EventAction> mapValueToEvent =
"1", eventOne,
"2", eventTwo,
"0", eventActioned
;
Logic error, exec() can only return "0" or "1"
That doesn't feel right, since you handle "0", "1" or "2"
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I'm not going to comment on the OS interactions here, just the C++ code in general.
prefer anonymous namespaces to the static keyword
static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:
namespace
void daemon();
std::map<std::string, EventAction> mapValueToEvent;
Prefer using enum class to regular enum
enum class EventAction ...;
This prevents a large number of namespace polution issues, and is just a good habit to build.
prefer using std::unordered_map to std::map
Unless you have a reallllly good reason, std::unordered_map
is almost always preferable.
Why shared_ptr?
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.
initialise() is unnecessary
You can simply initialize the map using a literal:
static std::map<std::string, EventAction> mapValueToEvent =
"1", eventOne,
"2", eventTwo,
"0", eventActioned
;
Logic error, exec() can only return "0" or "1"
That doesn't feel right, since you handle "0", "1" or "2"
add a comment |Â
up vote
2
down vote
accepted
I'm not going to comment on the OS interactions here, just the C++ code in general.
prefer anonymous namespaces to the static keyword
static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:
namespace
void daemon();
std::map<std::string, EventAction> mapValueToEvent;
Prefer using enum class to regular enum
enum class EventAction ...;
This prevents a large number of namespace polution issues, and is just a good habit to build.
prefer using std::unordered_map to std::map
Unless you have a reallllly good reason, std::unordered_map
is almost always preferable.
Why shared_ptr?
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.
initialise() is unnecessary
You can simply initialize the map using a literal:
static std::map<std::string, EventAction> mapValueToEvent =
"1", eventOne,
"2", eventTwo,
"0", eventActioned
;
Logic error, exec() can only return "0" or "1"
That doesn't feel right, since you handle "0", "1" or "2"
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I'm not going to comment on the OS interactions here, just the C++ code in general.
prefer anonymous namespaces to the static keyword
static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:
namespace
void daemon();
std::map<std::string, EventAction> mapValueToEvent;
Prefer using enum class to regular enum
enum class EventAction ...;
This prevents a large number of namespace polution issues, and is just a good habit to build.
prefer using std::unordered_map to std::map
Unless you have a reallllly good reason, std::unordered_map
is almost always preferable.
Why shared_ptr?
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.
initialise() is unnecessary
You can simply initialize the map using a literal:
static std::map<std::string, EventAction> mapValueToEvent =
"1", eventOne,
"2", eventTwo,
"0", eventActioned
;
Logic error, exec() can only return "0" or "1"
That doesn't feel right, since you handle "0", "1" or "2"
I'm not going to comment on the OS interactions here, just the C++ code in general.
prefer anonymous namespaces to the static keyword
static is just a C backwards compatibility thing, the proper way to prevent a name from leaking out of a translation unit is an anonymous namespace:
namespace
void daemon();
std::map<std::string, EventAction> mapValueToEvent;
Prefer using enum class to regular enum
enum class EventAction ...;
This prevents a large number of namespace polution issues, and is just a good habit to build.
prefer using std::unordered_map to std::map
Unless you have a reallllly good reason, std::unordered_map
is almost always preferable.
Why shared_ptr?
std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
While you get mad props for using RAII to manage the FILE pointer, you should be using a unique_ptr here, not a shared_ptr.
initialise() is unnecessary
You can simply initialize the map using a literal:
static std::map<std::string, EventAction> mapValueToEvent =
"1", eventOne,
"2", eventTwo,
"0", eventActioned
;
Logic error, exec() can only return "0" or "1"
That doesn't feel right, since you handle "0", "1" or "2"
answered Jan 4 at 3:20
Frank
2,947319
2,947319
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184244%2fdaemon-intended-to-replace-a-cronjob-which-reads-and-processes-events-from-a-que%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password