From 1b7dee6c3d9e9e234383820d240e7fde84da39a4 Mon Sep 17 00:00:00 2001 From: weetmuts Date: Sun, 24 Feb 2019 09:58:31 +0100 Subject: [PATCH] Daemon mode now works. Run 'make install' then insert dongle. --- install.sh | 112 +++++++++++++++++++++++++++++++++++++++++++++++-- src/cmdline.cc | 5 ++- src/config.h | 1 + src/main.cc | 59 +++++++++++++++++++------- src/util.cc | 6 +-- 5 files changed, 158 insertions(+), 25 deletions(-) diff --git a/install.sh b/install.sh index 293c7fb..c8d061d 100755 --- a/install.sh +++ b/install.sh @@ -34,6 +34,11 @@ fi ROOT="${2%/}" +#################################################################### +## +## Intall binaries +## + rm -f $ROOT/usr/bin/wmbusmeters $ROOT/usr/sbin/wmbusmetersd mkdir -p $ROOT/usr/bin mkdir -p $ROOT/usr/sbin @@ -42,6 +47,11 @@ ln -s $ROOT/usr/bin/wmbusmeters $ROOT/usr/sbin/wmbusmetersd echo binaries: installed $ROOT/usr/bin/wmbusmeters and $ROOT/usr/sbin/wmbusmetersd +#################################################################### +## +## Create wmbusmeters user +## + ID=$(id -u wmbusmeters 2>/dev/null) if [ "$ADDUSER" = "true" ] @@ -56,15 +66,68 @@ then fi fi +#################################################################### +## +## Prepare for /var/run/wmbusmeters.pid +## + +#if [ ! -d $ROOT/var/run ] +#then +# # Create /var/run +# mkdir -p $ROOT/var/run +# echo pid store: created /var/run +#fi + +#################################################################### +## +## Prepare for /var/log/wmbusmeters and /var/log/wmbusmeters/meter_readings +## + +if [ ! -d $ROOT/var/log/wmbusmeters/meter_readings ] +then + # Create /var/run + mkdir -p $ROOT/var/log/wmbusmeters/meter_readings + chown -R wmbusmeters:wmbusmeters $ROOT/var/log/wmbusmeters + echo log: created /var/log/wmbusmeters/meter_readings +fi + +#################################################################### +## +## Install /etc/logrotate.d/wmbusmeters +## + +if [ ! -f $ROOT/etc/logrotate.d/wmbusmeters ] +then + mkdir -p $ROOT/etc/logrotate.d + # Create logrotate file + cat < $ROOT/etc/logrotate.d/wmbusmeters +/var/log/wmbusmeters/*.log { + rotate 12 + weekly + compress + missingok + postrotate + start-stop-daemon -K -p /var/run/wmbusmeters.pid -s HUP -x /usr/sbin/wmbusmeters -q + endscript +EOF + echo logrotate: created /etc/logrotate.d/wmbusmeters +fi + +#################################################################### +## +## Install /etc/wmbusmeters.conf +## + if [ ! -f $ROOT/etc/wmbusmeters.conf ] then # Create default configuration mkdir -p $ROOT/etc/ cat < $ROOT/etc/wmbusmeters.conf -loglevel=normal +loglevel=verbose device=auto logtelegrams=false -meterfiles=/tmp/wmbusmeters +robot=json +meterfilesdir=/var/log/wmbusmeters/meter_readings EOF chmod 644 $ROOT/etc/wmbusmeters.conf echo conf file: created $ROOT/etc/wmbusmeters.conf @@ -72,6 +135,11 @@ else echo conf file: $ROOT/etc/wmbusmeters.conf unchanged fi +#################################################################### +## +## Create /etc/wmbusmeters.d +## + if [ ! -d $ROOT/etc/wmbusmeters.d ] then # Create the configuration directory @@ -82,6 +150,11 @@ else echo conf dir: $ROOT/etc/wmbusmeters.d unchanged fi +#################################################################### +## +## Create /etc/systemd/system/wmbusmeters.service +## + if [ ! -f $ROOT/etc/systemd/system/wmbusmeters.service ] then mkdir -p $ROOT/etc/systemd/system/ @@ -92,11 +165,23 @@ Description=wmbusmeters service After=network.target [Service] -Type=simple +Type=forking +PrivateTmp=yes #Restart=always RestartSec=1 User=wmbusmeters -ExecStart=/usr/bin/wmbusmeters --useconfig +Group=wmbusmeters + +# Run ExecStartPre with root-permissions + +PermissionsStartOnly=true +ExecStartPre=-/bin/mkdir -p /var/log/wmbusmeters/meter_readings +ExecStartPre=/bin/chown -R wmbusmeters:wmbusmeters /var/log/wmbusmeters +ExecStartPre=-/bin/mkdir -p /var/run/wmbusmeters +ExecStartPre=/bin/chown -R wmbusmeters:wmbusmeters /var/run/wmbusmeters + +ExecStart=/usr/sbin/wmbusmetersd /var/run/wmbusmeters/wmbusmeters.pid +PIDFile=/var/run/wmbusmeters/wmbusmeters.pid [Install] WantedBy=multi-user.target @@ -106,3 +191,22 @@ EOF else echo systemd: $ROOT/etc/systemd/system/wmbusmeters.service unchanged fi + + +#################################################################### +## +## Create /etc/udev/rules.d/99-wmbus-usb-serial.rules +## + +if [ ! -f $ROOT/etc/udev/rules.d/99-wmbus-usb-serial.rules ] +then + mkdir -p $ROOT/etc/udev/rules.d + # Create service file + cat < $ROOT/etc/udev/rules.d/99-wmbus-usb-serial.rules +SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="im871a",MODE="0660", GROUP="wmbusmeters",TAG+="systemd",ENV{SYSTEMD_WANTS}="wmbusmeters.service" +SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="amb8465",MODE="0660", GROUP="wmbusmeters",TAG+="systemd",ENV{SYSTEMD_WANTS}="wmbusmeters.service" +EOF + echo udev: installed $ROOT/etc/udev/rules.d/99-wmbus-usb-serial.rules +else + echo systemd: $ROOT/etc/udev/rules.d/99-wmbus-usb-serial.rules unchanged +fi diff --git a/src/cmdline.cc b/src/cmdline.cc index 5b83d78..61d2040 100644 --- a/src/cmdline.cc +++ b/src/cmdline.cc @@ -31,9 +31,10 @@ unique_ptr parseCommandLine(int argc, char **argv) { const char *filename = strrchr(argv[0], '/')+1; if (!strcmp(filename, "wmbusmetersd")) { c->daemon = true; - if (argc > 1) { - error("Usage error: wmbusmetersd does not accept any arguments.\n"); + if (argc != 2) { + error("Usage error: wmbusmetersd must have a single argument to the pid file.\n"); } + c->pid_file = argv[1]; return unique_ptr(c); } if (argc < 2) { diff --git a/src/config.h b/src/config.h index eaaa615..19f6075 100644 --- a/src/config.h +++ b/src/config.h @@ -40,6 +40,7 @@ struct MeterInfo { struct CommandLine { bool daemon {}; + std::string pid_file; bool useconfig {}; bool reload {}; bool need_help {}; diff --git a/src/main.cc b/src/main.cc index ee5430f..2cc60e0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -39,8 +39,8 @@ using namespace std; void oneshotCheck(CommandLine *cmdline, SerialCommunicationManager *manager, Meter *meter, vector> &meters); void startUsingCommandline(CommandLine *cmdline); -void startUsingConfigFiles(string root); -void startDaemon(); // Will use config files. +void startUsingConfigFiles(string root, bool is_daemon); +void startDaemon(string pid_file); // Will use config files. int main(int argc, char **argv) { @@ -75,7 +75,7 @@ int main(int argc, char **argv) } else if (cmdline->daemon) { - startDaemon(); + startDaemon(cmdline->pid_file); exit(0); } else @@ -86,7 +86,7 @@ int main(int argc, char **argv) if (r != NULL) { root = r; } - startUsingConfigFiles(root); + startUsingConfigFiles(root, false); exit(0); } else { @@ -135,7 +135,11 @@ void startUsingCommandline(CommandLine *cmdline) wmbus = openSimulator(type_and_device.second, manager.get()); break; case DEVICE_UNKNOWN: - error("No wmbus device found!\n"); + warning("No wmbus device found! Exiting!\n"); + if (cmdline->daemon) { + // If starting as a daemon, wait a bit so that systemd have time to catch up. + sleep(1); + } exit(1); break; } @@ -246,8 +250,36 @@ void oneshotCheck(CommandLine *cmdline, SerialCommunicationManager *manager, Met manager->stop(); } -void startDaemon() +void writePid(string pid_file, int pid) { + FILE *pidf = fopen(pid_file.c_str(), "w"); + if (!pidf) { + error("Could not open pid file \"%s\" for writing!\n", pid_file.c_str()); + } + if (pid > 0) { + int n = fprintf(pidf, "%d\n", pid); + notice("writing pid %s\n", pid_file.c_str()); + if (!n) { + error("Could not write pid (%d) to file \"%s\"!\n", pid, pid_file.c_str()); + } + } + fclose(pidf); + return; +} + +void startDaemon(string pid_file) +{ + setlogmask(LOG_UPTO (LOG_INFO)); + openlog("wmbusmetersd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + + enableSyslog(); + + notice("wmbusmeters starting...\n"); + + // Pre check that the pid file can be writte to. + // Exit before fork, if it fails. + writePid(pid_file, 0); + pid_t pid = fork(); if (pid < 0) { @@ -255,20 +287,14 @@ void startDaemon() } if (pid > 0) { - // Parent returns to exit nicely. + // Success! The parent stores the pid and exits. + writePid(pid_file, pid); return; } // Change the file mode mask umask(0); - setlogmask(LOG_UPTO (LOG_NOTICE)); - openlog("wmbusmetersd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); - - enableSyslog(); - - notice("wmbusmeters started by user %d\n", getuid ()); - // Create a new SID for the daemon pid_t sid = setsid(); if (sid < 0) { @@ -284,12 +310,13 @@ void startDaemon() close(STDOUT_FILENO); close(STDERR_FILENO); - startUsingConfigFiles(""); + startUsingConfigFiles("", true); } -void startUsingConfigFiles(string root) +void startUsingConfigFiles(string root, bool is_daemon) { unique_ptr cmdline = loadConfiguration(root); + cmdline->daemon = is_daemon; startUsingCommandline(cmdline.get()); } diff --git a/src/util.cc b/src/util.cc index 0a45874..cd3309d 100644 --- a/src/util.cc +++ b/src/util.cc @@ -196,7 +196,7 @@ void info(const char* fmt, ...) { va_list args; va_start(args, fmt); if (syslog_enabled_) { - vsyslog(LOG_INFO, fmt, args); + vsyslog(LOG_NOTICE, fmt, args); } else { vprintf(fmt, args); } @@ -232,7 +232,7 @@ void verbose(const char* fmt, ...) { va_list args; va_start(args, fmt); if (syslog_enabled_) { - vsyslog(LOG_INFO, fmt, args); + vsyslog(LOG_NOTICE, fmt, args); } else { vprintf(fmt, args); } @@ -245,7 +245,7 @@ void debug(const char* fmt, ...) { va_list args; va_start(args, fmt); if (syslog_enabled_) { - vsyslog(LOG_INFO, fmt, args); + vsyslog(LOG_NOTICE, fmt, args); } else { vprintf(fmt, args); }