diff --git a/installer/resources/i2prouter b/installer/resources/i2prouter index 6c05a291c..806404665 100644 --- a/installer/resources/i2prouter +++ b/installer/resources/i2prouter @@ -29,6 +29,7 @@ # should have been replaced by the izpack installer. # If you did not run the installer, replace them with the appropriate path. I2P="%INSTALL_PATH" +I2P_CONFIG_DIR="$HOME/.i2p" I2PTEMP="%SYSTEM_java_io_tmpdir" # PORTABLE installation: # Use the following instead. @@ -44,9 +45,10 @@ GETTEXT=$(which gettext) # If specified, the Wrapper will be run as the specified user. # IMPORTANT - Make sure that the user has the required privileges to write -# the PID file and wrapper.log files. Failure to be able to write the log -# file will cause the Wrapper to exit without any way to write out an error -# message. +# the PID file and wrapper.log files and that the directories exist. +# Failure to write the pid file will cause the Wrapper to exit. +# Failure to write the log file will cause the Wrapper to use CWD for the log file location. +# # NOTE - This will set the user which is used to run the Wrapper as well as # the JVM and is not useful in situations where a privileged resource or # port needs to be allocated prior to the user being changed. @@ -60,8 +62,14 @@ WRAPPER_CONF="$I2P/wrapper.config" # nice is only used if a priority is specified. PRIORITY= -# Location of the pid file. -PIDDIR="$I2PTEMP" +# Location of the pid and status files. +PIDDIR="$I2P_CONFIG_DIR" +#PIDDIR="$I2PTEMP" + +# Location of the wrapper.log file +LOGDIR="$I2P_CONFIG_DIR" +#LOGDIR="$I2PTEMP" +LOGFILE="$LOGDIR/wrapper.log" # If you'd like to run I2P as root (not recommended), uncomment the # following line @@ -590,6 +598,9 @@ else COMMANDPROP= fi +# Build the log file clause. +LOGPROP="wrapper.logfile=\"$LOGFILE\"" + if [ ! -n "$WAIT_FOR_STARTED_STATUS" ] then WAIT_FOR_STARTED_STATUS=true @@ -864,9 +875,10 @@ launchdinternal() { if [ "X$pid" = "X" ] then prepAdditionalParams "$@" + mkdir -p "$PIDDIR" "$LOGDIR" # The string passed to eval must handles spaces in paths correctly. - COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP $ADDITIONAL_PARA" + COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP $LOGPROP $ADDITIONAL_PARA" eval $COMMAND_LINE else eval echo `gettext '$APP_LONG_NAME is already running.'` @@ -887,9 +899,10 @@ console() { trap '' 3 2 prepAdditionalParams "$@" + mkdir -p "$PIDDIR" "$LOGDIR" # The string passed to eval must handles spaces in paths correctly. - COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" $ANCHORPROP $STATUSPROP $COMMANDPROP $LOCKPROP $ADDITIONAL_PARA" + COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" $ANCHORPROP $STATUSPROP $COMMANDPROP $LOCKPROP $LOGPROP $ADDITIONAL_PARA" eval $COMMAND_LINE if [ "$?" -ne "0" ]; then failed @@ -1012,9 +1025,10 @@ start() { if [ "X$pid" = "X" ] then prepAdditionalParams "$@" + mkdir -p "$PIDDIR" "$LOGDIR" # The string passed to eval must handles spaces in paths correctly. - COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP $ADDITIONAL_PARA" + COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=\"$APP_NAME\" wrapper.java.command=\"$JAVABINARY\" wrapper.pidfile=\"$PIDFILE\" wrapper.name=\"$APP_NAME\" wrapper.displayname=\"$APP_LONG_NAME\" wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $STATUSPROP $COMMANDPROP $LOCKPROP $LOGPROP $ADDITIONAL_PARA" eval $COMMAND_LINE if [ "$?" -ne "0" ]; then failed diff --git a/installer/resources/wrapper.config b/installer/resources/wrapper.config index 873b114c7..07c837b93 100644 --- a/installer/resources/wrapper.config +++ b/installer/resources/wrapper.config @@ -133,8 +133,10 @@ wrapper.console.format=PM wrapper.console.loglevel=INFO # Log file to use for wrapper output logging. -# You may wish to change this on linux so the log is -# preserved across OS restarts. +# You may wish to change this. +# NOTE: On Linux/Mac this is overridden in the i2prouter script; changes here will have no effect. +# Windows users may wish to change this to %APPDATA%\I2P\wrapper.log +# System temp directory: wrapper.logfile=$SYSTEM_java_io_tmpdir/wrapper.log # PORTABLE installation: # Use the following instead. I2P will find the logfile here, @@ -205,7 +207,11 @@ wrapper.use_system_time=false # you should copy this file, change the location or file name, # and edit the i2prouter script to change the WRAPPER_CONF setting # to point to the new wrapper.config location. -wrapper.java.pidfile=$SYSTEM_java_io_tmpdir/routerjvm.pid +# Windows users may wish to uncomment. +# Linux/Mac users, do not set here, see settings in the i2prouter script. +# Directory must exist or the wrapper will fail to start. +# System temp directory: +#wrapper.java.pidfile=$SYSTEM_java_io_tmpdir/routerjvm.pid # PORTABLE installation: # Use the following instead. #wrapper.java.pidfile=$INSTALL_PATH/routerjvm.pid @@ -219,7 +225,11 @@ wrapper.java.pidfile=$SYSTEM_java_io_tmpdir/routerjvm.pid # # This means i2prouter looks for './i2p.pid'. # See comments above for wrapper.java.pidfile -wrapper.pidfile=$SYSTEM_java_io_tmpdir/i2p.pid +# Windows users may wish to uncomment. +# Linux/Mac users, do not set here, see settings in the i2prouter script. +# Directory must exist or the wrapper will fail to start. +# System temp directory: +#wrapper.pidfile=$SYSTEM_java_io_tmpdir/i2p.pid # PORTABLE installation: # Use the following instead. #wrapper.pidfile=$INSTALL_PATH/i2p.pid diff --git a/router/java/src/net/i2p/router/RouterLaunch.java b/router/java/src/net/i2p/router/RouterLaunch.java index 069ee3ec5..7bbfed86d 100644 --- a/router/java/src/net/i2p/router/RouterLaunch.java +++ b/router/java/src/net/i2p/router/RouterLaunch.java @@ -1,43 +1,16 @@ package net.i2p.router; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; - -import net.i2p.util.SecureFileOutputStream; - /** * This is the class called by the runplain.sh script on linux * and the i2p.exe launcher on Windows. * (i.e. no wrapper) * - * If there is no -Dwrapper.log=/path/to/wrapper.log on the java command line - * to specify a log file, check for existence of wrapper.log in CWD, - * for backward compatibility in old installations (don't move it). - * Otherwise, use (system temp dir)/wrapper.log. - * Create if it doesn't exist, and append to it if it does. - * Put the location in the environment as an absolute path, so logs.jsp can find it. + * Setup of wrapper.log file is moved to WorkingDir.java + * Until WorkingDir is called, the existing stdout / stderr will be used. */ public class RouterLaunch { - private static final String PROP_WRAPPER_LOG = "wrapper.logfile"; - private static final String DEFAULT_WRAPPER_LOG = "wrapper.log"; public static void main(String args[]) { - String path = System.getProperty(PROP_WRAPPER_LOG); - File logfile; - if (path != null) { - logfile = new File(path); - } else { - logfile = new File(DEFAULT_WRAPPER_LOG); - if (!logfile.exists()) - logfile = new File(System.getProperty("java.io.tmpdir"), DEFAULT_WRAPPER_LOG); - } - System.setProperty(PROP_WRAPPER_LOG, logfile.getAbsolutePath()); - try { - System.setOut(new PrintStream(new SecureFileOutputStream(logfile, true))); - } catch (IOException ioe) { - ioe.printStackTrace(); - } Router.main(args); } } diff --git a/router/java/src/net/i2p/router/startup/WorkingDir.java b/router/java/src/net/i2p/router/startup/WorkingDir.java index a1f414ac2..2e3500cc1 100644 --- a/router/java/src/net/i2p/router/startup/WorkingDir.java +++ b/router/java/src/net/i2p/router/startup/WorkingDir.java @@ -7,6 +7,7 @@ import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.PrintStream; import java.io.PrintWriter; import java.util.Properties; @@ -52,10 +53,14 @@ public class WorkingDir { private final static String WORKING_DIR_DEFAULT_DAEMON = "i2p-config"; /** we do a couple of things differently if this is the username */ private final static String DAEMON_USER = "i2psvc"; + private static final String PROP_WRAPPER_LOG = "wrapper.logfile"; + private static final String DEFAULT_WRAPPER_LOG = "wrapper.log"; /** * Only call this once on router invocation. * Caller should store the return value for future reference. + * + * This also redirects stdout and stderr to a wrapper.log file if there is no wrapper present. */ public static String getWorkingDir(Properties envProps, boolean migrateOldConfig) { String dir = null; @@ -96,27 +101,32 @@ public class WorkingDir { File oldDirf = new File(cwd); File test = new File(oldDirf, "hosts.txt"); if (!test.exists()) { + setupSystemOut(cwd); System.err.println("ERROR - Cannot find I2P installation in " + cwd + " - Will probably be just a router with no apps or console at all!"); - // until we move reseeding from the console to the router, we - // won't be able to reseed, so we are probably doomed + // we are probably doomed... return cwd; } // apparently configured for "portable" ? try { - if (oldDirf.getCanonicalPath().equals(dirf.getCanonicalPath())) + if (oldDirf.getCanonicalPath().equals(dirf.getCanonicalPath())) { + setupSystemOut(cwd); return cwd; + } } catch (IOException ioe) {} // where we want to go String rv = dirf.getAbsolutePath(); if (dirf.exists()) { if (dirf.isDirectory()) { - if (isSetup(dirf)) + if (isSetup(dirf)) { + setupSystemOut(rv); return rv; // all is good, we found the user directory + } } else { + setupSystemOut(null); System.err.println("Wanted to use " + rv + " for a working directory but it is not a directory"); return cwd; } @@ -131,15 +141,19 @@ public class WorkingDir { oldInstall = test.exists(); } // keep everything where it is, in one place... - if (oldInstall && !migrateOldConfig) + if (oldInstall && !migrateOldConfig) { + setupSystemOut(cwd); return cwd; + } boolean migrateOldData = false; // this is a terrible idea if (!dirf.exists() && !dirf.mkdir()) { + setupSystemOut(null); System.err.println("Wanted to use " + rv + " for a working directory but could not create it"); return cwd; } + setupSystemOut(dirf.getAbsolutePath()); // Do the copying if (migrateOldData) System.err.println("Migrating data files to new user directory " + rv); @@ -184,6 +198,44 @@ public class WorkingDir { return false; } + /** + * Redirect stdout and stderr to a wrapper.log file if there is no wrapper. + * + * If there is no -Dwrapper.log=/path/to/wrapper.log on the java command line + * to specify a log file, check for existence of wrapper.log in CWD, + * for backward compatibility in old installations (don't move it). + * Otherwise, use (system temp dir)/wrapper.log. + * Create if it doesn't exist, and append to it if it does. + * Put the location in the environment as an absolute path, so logs.jsp can find it. + * + * @param dir if null, use Java temp dir; System property wrapper.logfile overrides + * @since 0.8.13 + */ + private static void setupSystemOut(String dir) { + if (System.getProperty("wrapper.version") != null) + return; + String path = System.getProperty(PROP_WRAPPER_LOG); + File logfile; + if (path != null) { + logfile = new File(path); + } else { + logfile = new File(DEFAULT_WRAPPER_LOG); + if (!logfile.exists()) { + if (dir == null) + dir = System.getProperty("java.io.tmpdir"); + logfile = new File(dir, DEFAULT_WRAPPER_LOG); + } + } + System.setProperty(PROP_WRAPPER_LOG, logfile.getAbsolutePath()); + try { + PrintStream ps = new PrintStream(new SecureFileOutputStream(logfile, true)); + System.setOut(ps); + System.setErr(ps); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + /** * files and directories from the base install to copy over * None of these should be included in i2pupdate.zip