r69326 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r69325‎ | r69326 | r69327 >
Date:05:10, 14 July 2010
Author:tstarling
Status:deferred
Tags:
Comment:
* Updates for Lucid: fixed missing headers due to new compiler, etc.
* Added init script.
* Added code to run as non-root daemon with PID file.
* Send messages to a log file instead of the terminal. No timestamps yet.
* Added default configuration file and created log directory on package installation. The daemon should now start successfully on install.

The package should work as-is for the MW logging instance, and with a small tweak to /etc/default/udp2log it should work for the squid logs too.
Modified paths:
  • /trunk/udplog/debian/changelog (modified) (history)
  • /trunk/udplog/debian/conffiles (added) (history)
  • /trunk/udplog/debian/control (modified) (history)
  • /trunk/udplog/debian/dirs (modified) (history)
  • /trunk/udplog/debian/postinst (added) (history)
  • /trunk/udplog/debian/rules (modified) (history)
  • /trunk/udplog/debian/udp2log.init (added) (history)
  • /trunk/udplog/srclib/Exception.h (modified) (history)
  • /trunk/udplog/srclib/SocketAddress.h (modified) (history)
  • /trunk/udplog/srcmisc/delta.cpp (modified) (history)
  • /trunk/udplog/udp2log/udp2log.conf.default (added) (history)
  • /trunk/udplog/udp2log/udp2log.cpp (modified) (history)

Diff [purge]

Index: trunk/udplog/debian/control
@@ -7,5 +7,5 @@
88
99 Package: udplog
1010 Architecture: any
11 -Depends: ${shlibs:Depends}, ${misc:Depends}
 11+Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6)
1212 Description: Utilities for UDP logging
Index: trunk/udplog/debian/dirs
@@ -1 +1,3 @@
22 usr/bin
 3+var/log/udp2log
 4+etc
Index: trunk/udplog/debian/postinst
@@ -0,0 +1,8 @@
 2+#!/bin/sh
 3+if ! getent passwd udp2log > /dev/null; then
 4+ groupadd udp2log
 5+ useradd -d/ -c'udp2log daemon' -gudp2log -s/sbin/nologin udp2log
 6+fi
 7+chown udp2log:udp2log /var/log/udp2log
 8+
 9+#DEBHELPER#
Property changes on: trunk/udplog/debian/postinst
___________________________________________________________________
Added: svn:eol-style
110 + native
Added: svn:executable
211 + *
Index: trunk/udplog/debian/changelog
@@ -1,3 +1,11 @@
 2+udplog (1.5-1) lucid; urgency=low
 3+
 4+ * Updates for Lucid
 5+ * Added init script
 6+ * Added code to run as non-root daemon with PID file
 7+
 8+ -- Tim Starling <tstarling@wikimedia.org> Tue, 13 Jul 2010 14:15:55 +1000
 9+
210 udplog (1.4-1) unstable; urgency=low
311
412 * Allow the stream flushing behaviour to be configured for each processor
Index: trunk/udplog/debian/conffiles
@@ -0,0 +1 @@
 2+/etc/udp2log
Property changes on: trunk/udplog/debian/conffiles
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: trunk/udplog/debian/rules
@@ -55,8 +55,9 @@
5656 dh_clean -k
5757 dh_installdirs
5858
59 - # Add here commands to install the package into debian/udplog.
6059 $(MAKE) install DESTDIR=$(CURDIR)/debian/udplog
 60+ # Create default configuration file
 61+ install -m644 udp2log/udp2log.conf.default $(CURDIR)/debian/udplog/etc/udp2log
6162
6263
6364 # Build architecture-independent files here.
@@ -78,7 +79,7 @@
7980 # dh_installpam
8081 # dh_installmime
8182 # dh_python
82 -# dh_installinit
 83+ dh_installinit --name=udp2log
8384 # dh_installcron
8485 # dh_installinfo
8586 dh_installman
Index: trunk/udplog/debian/udp2log.init
@@ -0,0 +1,137 @@
 2+#! /bin/sh
 3+### BEGIN INIT INFO
 4+# Provides: udp2log
 5+# Required-Start: $remote_fs $syslog
 6+# Required-Stop: $remote_fs $syslog
 7+# Default-Start: 2 3 4 5
 8+# Default-Stop: 0 1 6
 9+# Short-Description: UDP log receiver (udp2log)
 10+# Description: UDP log receiver (udp2log)
 11+### END INIT INFO
 12+
 13+# Author: Tim Starling <tstarling@wikimedia.org>
 14+# Based on Lucid /etc/init.d/skeleton
 15+
 16+# PATH should only include /usr/* if it runs after the mountnfs.sh script
 17+PATH=/sbin:/usr/sbin:/bin:/usr/bin
 18+DESC="UDP log receiver (udp2log)"
 19+NAME=udp2log
 20+DAEMON=/usr/bin/$NAME
 21+DAEMON_ARGS="--daemon"
 22+PIDFILE=/var/run/$NAME.pid
 23+SCRIPTNAME=/etc/init.d/$NAME
 24+CONFFILE=/etc/udp2log
 25+
 26+# Exit if the package is not installed
 27+[ -x "$DAEMON" ] || exit 0
 28+
 29+# Read configuration variable file if it is present
 30+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
 31+
 32+# Load the VERBOSE setting and other rcS variables
 33+. /lib/init/vars.sh
 34+
 35+# Define LSB log_* functions.
 36+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
 37+. /lib/lsb/init-functions
 38+
 39+#
 40+# Function that starts the daemon/service
 41+#
 42+do_start()
 43+{
 44+ # Return
 45+ # 0 if daemon has been started
 46+ # 1 if daemon was already running
 47+ # 2 if daemon could not be started
 48+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
 49+ || return 1
 50+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
 51+ --config-file=$CONFFILE $DAEMON_ARGS \
 52+ || return 2
 53+}
 54+
 55+#
 56+# Function that stops the daemon/service
 57+#
 58+do_stop()
 59+{
 60+ # Return
 61+ # 0 if daemon has been stopped
 62+ # 1 if daemon was already stopped
 63+ # 2 if daemon could not be stopped
 64+ # other if a failure occurred
 65+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
 66+ RETVAL="$?"
 67+ [ "$RETVAL" = 2 ] && return 2
 68+ # Wait for children to finish too if this is a daemon that forks
 69+ # and if the daemon is only ever run from this initscript.
 70+ # If the above conditions are not satisfied then add some other code
 71+ # that waits for the process to drop all resources that could be
 72+ # needed by services started subsequently. A last resort is to
 73+ # sleep for some time.
 74+ start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
 75+ [ "$?" = 2 ] && return 2
 76+ # Many daemons don't delete their pidfiles when they exit.
 77+ rm -f $PIDFILE
 78+ return "$RETVAL"
 79+}
 80+
 81+#
 82+# Function that sends a SIGHUP to the daemon/service
 83+#
 84+do_reload() {
 85+ start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE --name $NAME
 86+ return 0
 87+}
 88+
 89+case "$1" in
 90+ start)
 91+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
 92+ do_start
 93+ case "$?" in
 94+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
 95+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
 96+ esac
 97+ ;;
 98+ stop)
 99+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
 100+ do_stop
 101+ case "$?" in
 102+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
 103+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
 104+ esac
 105+ ;;
 106+ status)
 107+ status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
 108+ ;;
 109+ reload|force-reload)
 110+ log_daemon_msg "Reloading $DESC" "$NAME"
 111+ do_reload
 112+ log_end_msg $?
 113+ ;;
 114+ restart)
 115+ log_daemon_msg "Restarting $DESC" "$NAME"
 116+ do_stop
 117+ case "$?" in
 118+ 0|1)
 119+ do_start
 120+ case "$?" in
 121+ 0) log_end_msg 0 ;;
 122+ 1) log_end_msg 1 ;; # Old process is still running
 123+ *) log_end_msg 1 ;; # Failed to start
 124+ esac
 125+ ;;
 126+ *)
 127+ # Failed to stop
 128+ log_end_msg 1
 129+ ;;
 130+ esac
 131+ ;;
 132+ *)
 133+ echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 134+ exit 3
 135+ ;;
 136+esac
 137+
 138+:
Property changes on: trunk/udplog/debian/udp2log.init
___________________________________________________________________
Added: svn:eol-style
1139 + native
Index: trunk/udplog/srcmisc/delta.cpp
@@ -2,7 +2,10 @@
33 #include <map>
44 #include <stdint.h>
55 #include <boost/lexical_cast.hpp>
 6+#include <cstring>
67
 8+using std::strtok;
 9+
710 int main(int argc, char** argv)
811 {
912 using namespace std;
Index: trunk/udplog/udp2log/udp2log.conf.default
@@ -0,0 +1 @@
 2+# Configuration for udp2log goes here.
Property changes on: trunk/udplog/udp2log/udp2log.conf.default
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: trunk/udplog/udp2log/udp2log.cpp
@@ -1,16 +1,27 @@
22 // UDP -> stdout receiver
33
4 -#include <stdio.h>
 4+#include <cstdio>
55 #include <iostream>
 6+#include <fstream>
67 #include <boost/program_options.hpp>
78 #include <string>
89 #include <boost/shared_ptr.hpp>
910 #include <signal.h>
 11+#include <unistd.h>
 12+#include <sys/types.h>
 13+#include <sys/stat.h>
 14+#include <fcntl.h>
 15+#include <pwd.h>
 16+#include <cstdlib>
 17+
 18+#include "../srclib/Exception.h"
1019 #include "../srclib/Socket.h"
1120 #include "Udp2LogConfig.h"
1221
13 -
1422 std::string configFileName("/etc/udp2log");
 23+std::string logFileName("/var/log/udp2log/udp2log.log");
 24+std::string pidFileName("/var/run/udp2log.pid");
 25+std::string daemonUserName("udp2log");
1526
1627 Udp2LogConfig config;
1728
@@ -24,20 +35,96 @@
2536 config.fixBrokenProcessors = true;
2637 }
2738
 39+pid_t Daemonize()
 40+{
 41+ // Open PID file as root
 42+ std::ofstream pidFile(pidFileName.c_str());
 43+ if (!pidFile.good()) {
 44+ throw libc_error("Error opening PID file");
 45+ }
 46+
 47+ // Fetch details of new user
 48+ struct passwd * userData = getpwnam(daemonUserName.c_str());
 49+ if (!userData) {
 50+ throw std::runtime_error(
 51+ std::string("No such user: ") + daemonUserName);
 52+ }
 53+
 54+ // Change user
 55+ if (setgid(userData->pw_gid) == -1
 56+ || setuid(userData->pw_uid) == -1)
 57+ {
 58+ throw libc_error("Error changing user ID");
 59+ }
 60+
 61+ // Open files for new standard file handles
 62+ int logFd = open(logFileName.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
 63+ if (logFd == -1) {
 64+ throw libc_error("Error opening log file");
 65+ }
 66+ int nullFd = open("/dev/null", O_WRONLY);
 67+ if (nullFd == -1) {
 68+ throw libc_error("Error opening /dev/null");
 69+ }
 70+
 71+ // Fork
 72+ pid_t pid = fork();
 73+ if (pid == -1) {
 74+ throw libc_error("Error creating new process");
 75+ } else if (pid) {
 76+ // This is the parent process
 77+ // Write PID file
 78+ pidFile << pid << std::endl;
 79+ return pid;
 80+ }
 81+
 82+ // Redirect standard file handles
 83+ dup2(nullFd, STDIN_FILENO);
 84+ dup2(logFd, STDOUT_FILENO);
 85+ dup2(logFd, STDERR_FILENO);
 86+
 87+ // Set session
 88+ setsid();
 89+
 90+ // Change directory
 91+ chdir("/");
 92+ return 0;
 93+}
 94+
 95+void MakeAbsolutePath(std::string & path) {
 96+ if (path.size() && path[0] != '/' ) {
 97+ char * cwd = getcwd(NULL, 0);
 98+ if (cwd) {
 99+ path = std::string(cwd) + "/" + path;
 100+ free(cwd);
 101+ }
 102+ }
 103+}
 104+
28105 int main(int argc, char** argv)
29106 {
30107 using namespace std;
31108 using namespace boost::program_options;
32109 unsigned int port = 8420;
 110+ bool daemon = false;
33111
 112+ // Process command line
34113 options_description optDesc;
35114 optDesc.add_options()
36 - ("port,p", value<unsigned int>(&port)->default_value(port), "port")
 115+ ("help", "Show help message.")
 116+ ("port,p", value<unsigned int>(&port)->default_value(port), "UDP port.")
37117 ("config-file,f", value<string>(&configFileName)->default_value(configFileName),
38 - "config file location" );
 118+ "Config file location.")
 119+ ("daemon", "Run as a background process.")
 120+ ("log-file", value<string>(&logFileName)->default_value(logFileName),
 121+ "The log file, for internal udp2log messages. Used only if --daemon is specified.")
 122+ ("pid-file", value<string>(&pidFileName)->default_value(pidFileName),
 123+ "The location to write the new PID, if --daemon is specified.")
 124+ ("user", value<string>(&daemonUserName)->default_value(daemonUserName),
 125+ "User to switch to, after daemonizing");
39126
 127+ variables_map vm;
40128 try {
41 - variables_map vm;
42129 store(command_line_parser(argc, argv).options(optDesc).run(), vm);
43130 notify(vm);
44131 } catch (exception & e) {
@@ -46,10 +133,36 @@
47134 " [-p <port>] [-f <config_file>]\n";
48135 return 1;
49136 }
 137+ if (vm.count("help")) {
 138+ cerr << optDesc << "\n";
 139+ return 1;
 140+ }
50141 if (port > 65535) {
51142 cerr << "Invalid port number \"" << argv[2] << "\"\n";
52143 return 1;
53144 }
 145+ if (vm.count("daemon")) {
 146+ daemon = true;
 147+ }
 148+
 149+ // Guard against chdir("/")
 150+ MakeAbsolutePath(configFileName);
 151+ MakeAbsolutePath(logFileName);
 152+ MakeAbsolutePath(pidFileName);
 153+
 154+ // Fork
 155+ if (daemon) {
 156+ try {
 157+ if (Daemonize()) {
 158+ return 0;
 159+ }
 160+ } catch (runtime_error & e) {
 161+ cerr << e.what() << endl;
 162+ return 1;
 163+ }
 164+ }
 165+
 166+ // Read configuration and open log files and pipes
54167 try {
55168 config.Open(configFileName);
56169 } catch (runtime_error & e) {
@@ -61,6 +174,7 @@
62175 signal(SIGALRM, OnAlarm);
63176 signal(SIGPIPE, SIG_IGN);
64177
 178+ // Open the receiving socket
65179 IPAddress any(INADDR_ANY);
66180 SocketAddress saddr(any, (unsigned short int)port);
67181 UDPSocket socket;
@@ -70,6 +184,7 @@
71185 }
72186 socket.Bind(saddr);
73187
 188+ // Process received packets
74189 boost::shared_ptr<SocketAddress> address;
75190 const size_t bufSize = 65536;
76191 char buffer[bufSize];
Index: trunk/udplog/srclib/Exception.h
@@ -4,11 +4,12 @@
55 #include <stdexcept>
66 #include <string>
77 #include <cerrno>
 8+#include <cstring>
89
910 class libc_error : public std::runtime_error {
1011 public:
1112 libc_error(const std::string & what_arg)
12 - : std::runtime_error(std::string(what_arg).append(": ").append(strerror(errno)))
 13+ : std::runtime_error(std::string(what_arg).append(": ").append(std::strerror(errno)))
1314 {}
1415
1516 const char* what() {
Index: trunk/udplog/srclib/SocketAddress.h
@@ -5,6 +5,7 @@
66 #include "IPAddress.h"
77 #include <boost/shared_ptr.hpp>
88 #include <stdexcept>
 9+#include <cstring>
910
1011 class SocketAddress
1112 {
@@ -40,13 +41,13 @@
4142 switch (ip.GetType()) {
4243 case AF_INET:
4344 data.v4.sin_family = AF_INET;
44 - memcpy(&data.v4.sin_addr, ip.GetBinaryData(), ip.GetBinaryLength());
 45+ std::memcpy(&data.v4.sin_addr, ip.GetBinaryData(), ip.GetBinaryLength());
4546 data.v4.sin_port = htons(port);
4647 length = sizeof(sockaddr_in);
4748 break;
4849 case AF_INET6:
4950 data.v6.sin6_family = AF_INET6;
50 - memcpy(&data.v6.sin6_addr, ip.GetBinaryData(), ip.GetBinaryLength());
 51+ std::memcpy(&data.v6.sin6_addr, ip.GetBinaryData(), ip.GetBinaryLength());
5152 data.v6.sin6_port = htons(port);
5253 length = sizeof(sockaddr_in6);
5354 break;

Status & tagging log