Grails
  1. Grails
  2. GRAILS-2730

Location of stacktrace.log in WAR deployed app on Tomcat 6 running non-root is invalid

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: 1.0.1, 1.0.2, 2.0-RC1
    • Fix Version/s: 2.1.4, 2.2.1, 2.3-M1
    • Component/s: Configuration
    • Labels:
      None

      Description

      Running grails 1.0.1 and Tomcat 6.0 war deployed. Tomcat is not running as root but as another user. This user has the appropriate permissions for the entire tomcat directory and temp areas.

      Upon startup this error occurs. When running tomcat as root the error does not occur.

      The location of the stacktrace.log should be configurable during the grails war process, or written somewhere relative from where the WAR is deployed.

      log4j:ERROR setFile(null,true) call failed.
      java.io.FileNotFoundException: stacktrace.log (Permission denied)
      at java.io.FileOutputStream.openAppend(Native Method)
      at java.io.FileOutputStream.<init>(FileOutputStream.java:177)
      at java.io.FileOutputStream.<init>(FileOutputStream.java:102)
      at org.apache.log4j.FileAppender.setFile(FileAppender.java:290)
      at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:164)
      at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:257)
      at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:133)
      at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:97)
      at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:689)
      at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:647)
      at org.apache.log4j.PropertyConfigurator.parseCatsAndRenderers(PropertyConfigurator.java:568)
      at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:442)
      at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:476)
      at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:471)
      at org.apache.log4j.LogManager.<clinit>(LogManager.java:125)
      at org.apache.log4j.Logger.getLogger(Logger.java:105)
      at org.apache.commons.logging.impl.Log4JLogger.getLogger(Log4JLogger.java:283)
      at org.apache.commons.logging.impl.Log4JLogger.<init>(Log4JLogger.java:108)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
      at org.apache.commons.logging.impl.LogFactoryImpl.createLogFromClass(LogFactoryImpl.java:1040)
      at org.apache.commons.logging.impl.LogFactoryImpl.discoverLogImplementation(LogFactoryImpl.java:838)
      at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:601)
      at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:333)
      at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl

        Issue Links

          Activity

          InterZ created issue -
          Graeme Rocher made changes -
          Field Original Value New Value
          Fix Version/s 1.0.3 [ 14124 ]
          Hide
          Graeme Rocher added a comment -

          Surely this is deployment specific issue? If you need to configure a different location for the file just do so

          Show
          Graeme Rocher added a comment - Surely this is deployment specific issue? If you need to configure a different location for the file just do so
          Hide
          Peter Ledbrook added a comment -

          This can already be done in Grails. You have a couple of options. First, you can specify the location of the file on a per-environment basis:

          log4j {
              ...
              appender.errors = "org.apache.log4j.FileAppender"
              appender.'errors.layout'="org.apache.log4j.PatternLayout"
              appender.'errors.layout.ConversionPattern'='[%r] %c{2} %m%n'
              rootLogger="error,stdout"
              ...
          }
          
          environments {
              development {
                  log4j.appender.'errors.File'="stacktrace.log"
              }
              production {
                  log4j.appender.'errors.File'="/var/log/myapp/stacktrace.log"
              }
          }
          

          The other option is to remove the log4j configuration from Config.groovy and use a separate log4j.properties file by using something like this in Config.groovy:

          environments {
              development {
                  grails.config.locations = [ "classpath:log4j.properties" ]
              }
              production {
                  grails.config.locations = [ "file:/etc/myapp/log4j.properties" ]
              }
          }
          

          This latter option is preferred as it allows someone other than the packager of the application to change the Log4J settings after the web app has been installed.

          If you have any questions about this, please direct them to the user mailing list.

          Show
          Peter Ledbrook added a comment - This can already be done in Grails. You have a couple of options. First, you can specify the location of the file on a per-environment basis: log4j { ... appender.errors = "org.apache.log4j.FileAppender" appender.'errors.layout'= "org.apache.log4j.PatternLayout" appender.'errors.layout.ConversionPattern'='[%r] %c{2} %m%n' rootLogger= "error,stdout" ... } environments { development { log4j.appender.'errors.File'= "stacktrace.log" } production { log4j.appender.'errors.File'= "/ var /log/myapp/stacktrace.log" } } The other option is to remove the log4j configuration from Config.groovy and use a separate log4j.properties file by using something like this in Config.groovy: environments { development { grails.config.locations = [ "classpath:log4j.properties" ] } production { grails.config.locations = [ "file:/etc/myapp/log4j.properties" ] } } This latter option is preferred as it allows someone other than the packager of the application to change the Log4J settings after the web app has been installed. If you have any questions about this, please direct them to the user mailing list.
          Peter Ledbrook made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Resolution Won't Fix [ 2 ]
          Contegix Support made changes -
          Project Import Thu Mar 24 21:22:24 CDT 2011 [ 1301019744151 ]
          Hide
          Graeme Rocher added a comment -

          Bulk closing bunch of resolved issues

          Show
          Graeme Rocher added a comment - Bulk closing bunch of resolved issues
          Graeme Rocher made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          Burt Beckwith made changes -
          Workflow jira [ 30638 ] Grails [ 43564 ]
          Burt Beckwith made changes -
          Workflow Grails [ 43564 ] Copy of Grails [ 51018 ]
          Burt Beckwith made changes -
          Workflow Copy of Grails [ 51018 ] Grails [ 58428 ]
          Burt Beckwith made changes -
          Workflow Grails [ 58428 ] Grails2 [ 66006 ]
          Hide
          Lari Hotari added a comment -

          This issue is still open in Grails 2.0RC1.

          Stacktrace from catalina.out

          17.11.2011 7:27:34 org.apache.catalina.startup.HostConfig deployWAR
          INFO: Deploying web application archive petclinic-0.1.war
          log4j:ERROR setFile(null,true) call failed.
          java.io.FileNotFoundException: stacktrace.log (Permission denied)
                  at java.io.FileOutputStream.openAppend(Native Method)
                  at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
                  at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
                  at org.apache.log4j.FileAppender.setFile(FileAppender.java:294)
                  at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:165)
                  at org.apache.log4j.spi.OptionHandler$activateOptions.call(Unknown Source)
                  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
                  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
                  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
                  at org.codehaus.groovy.grails.plugins.log4j.Log4jConfig.createFullstackTraceAppender(Log4jConfig.groovy:229)
                  at org.codehaus.groovy.grails.plugins.log4j.Log4jConfig.configure(Log4jConfig.groovy:193)
                  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                  at java.lang.reflect.Method.invoke(Method.java:597)
                  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
                  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:64)
                  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
                  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
                  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
                  at org.codehaus.groovy.grails.plugins.log4j.Log4jConfig.initialize(Log4jConfig.groovy:70)
                  at org.codehaus.groovy.grails.plugins.log4j.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:48)
                  at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
                  at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226)
                  at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221)
                  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
                  at java.util.concurrent.FutureTask.run(FutureTask.java:138)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
                  at java.lang.Thread.run(Thread.java:662)
          

          It looks like Grails is creating a stacktrace.log in the default
          working directory by default:
          https://github.com/grails/grails-core/blob/2.0.x/grails-plugin-log4j/src/main/groovy/org/codehaus/groovy/grails/plugins/log4j/Log4jConfig.groovy#L227
          Because of this you should currently always configure custom Grails Log4J with an appender named "stacktrace".

          blog post about the problem:
          http://haxx.sinequanon.net/2008/09/grails-stacktracelog/

          Show
          Lari Hotari added a comment - This issue is still open in Grails 2.0RC1. Stacktrace from catalina.out 17.11.2011 7:27:34 org.apache.catalina.startup.HostConfig deployWAR INFO: Deploying web application archive petclinic-0.1.war log4j:ERROR setFile( null , true ) call failed. java.io.FileNotFoundException: stacktrace.log (Permission denied) at java.io.FileOutputStream.openAppend(Native Method) at java.io.FileOutputStream.<init>(FileOutputStream.java:192) at java.io.FileOutputStream.<init>(FileOutputStream.java:116) at org.apache.log4j.FileAppender.setFile(FileAppender.java:294) at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:165) at org.apache.log4j.spi.OptionHandler$activateOptions.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112) at org.codehaus.groovy.grails.plugins.log4j.Log4jConfig.createFullstackTraceAppender(Log4jConfig.groovy:229) at org.codehaus.groovy.grails.plugins.log4j.Log4jConfig.configure(Log4jConfig.groovy:193) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:64) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) at org.codehaus.groovy.grails.plugins.log4j.Log4jConfig.initialize(Log4jConfig.groovy:70) at org.codehaus.groovy.grails.plugins.log4j.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:48) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang. Thread .run( Thread .java:662) It looks like Grails is creating a stacktrace.log in the default working directory by default: https://github.com/grails/grails-core/blob/2.0.x/grails-plugin-log4j/src/main/groovy/org/codehaus/groovy/grails/plugins/log4j/Log4jConfig.groovy#L227 Because of this you should currently always configure custom Grails Log4J with an appender named "stacktrace". blog post about the problem: http://haxx.sinequanon.net/2008/09/grails-stacktracelog/
          Lari Hotari made changes -
          Resolution Won't Fix [ 2 ]
          Status Closed [ 6 ] Reopened [ 4 ]
          Lari Hotari made changes -
          Fix Version/s 1.0.3 [ 11004 ]
          Affects Version/s 2.0-RC1 [ 12803 ]
          Lari Hotari made changes -
          Link This issue relates to GRAILS-1635 [ GRAILS-1635 ]
          Lari Hotari made changes -
          Link This issue relates to GRAILS-4376 [ GRAILS-4376 ]
          Hide
          Lari Hotari added a comment -

          There is also a problem when several apps are installed on the same Tomcat instance. They are share the same stacktrace.log file.

          Show
          Lari Hotari added a comment - There is also a problem when several apps are installed on the same Tomcat instance. They are share the same stacktrace.log file.
          Hide
          Lari Hotari added a comment -

          Reproducing problem:

          Go to some root owned directory before starting tomcat, for example:

          cd /usr
          ~/apache-tomcat-7.0.22/bin/catalina.sh start
          

          Grails tries to write stacktrace.log in /usr (and that fails).

          Show
          Lari Hotari added a comment - Reproducing problem: Go to some root owned directory before starting tomcat, for example: cd /usr ~/apache-tomcat-7.0.22/bin/catalina.sh start Grails tries to write stacktrace.log in /usr (and that fails).
          Burt Beckwith made changes -
          Workflow Grails2 [ 66006 ] jira [ 71371 ]
          Burt Beckwith made changes -
          Workflow jira [ 71371 ] Grails2 [ 79716 ]
          Peter Ledbrook made changes -
          Last Reviewed 01/Jan/10
          Peter Ledbrook made changes -
          Workflow Grails2 [ 79716 ] jira [ 87796 ]
          Peter Ledbrook made changes -
          Workflow jira [ 87796 ] Grails2 [ 96027 ]
          Hide
          Peter Ledbrook added a comment -

          Some suggestions:

          1. Use logDir = new File(System.getProperty('catalina.home'), 'logs') (Tomcat-specific)
          2. Use java.io.tmpdir - sometimes too hard to track down
          3. Disable stacktrace.log in WAR mode
          4. Catch the permission exception and log a warning to configure the 'stacktrace' logger
          5. Log to console in WAR deploy mode

          The default should perhaps also include the name of the application in the filename, for the cases where a single container hosts more than one Grails app.

          Show
          Peter Ledbrook added a comment - Some suggestions: Use logDir = new File(System.getProperty('catalina.home'), 'logs') (Tomcat-specific) Use java.io.tmpdir - sometimes too hard to track down Disable stacktrace.log in WAR mode Catch the permission exception and log a warning to configure the 'stacktrace' logger Log to console in WAR deploy mode The default should perhaps also include the name of the application in the filename, for the cases where a single container hosts more than one Grails app.
          Hide
          Lari Hotari added a comment - - edited

          More solutions in the currently active email thread: http://grails.1312388.n4.nabble.com/stacktrace-log-tt4635524.html#a4635533 . I like Burt's solution for Tomcat. I usually add "appName" to the filename too.

          Show
          Lari Hotari added a comment - - edited More solutions in the currently active email thread: http://grails.1312388.n4.nabble.com/stacktrace-log-tt4635524.html#a4635533 . I like Burt's solution for Tomcat. I usually add "appName" to the filename too.
          Hide
          Alex Anderson added a comment -

          Have been bitten by this (last week, grails 2.0.3, Tomcat ??).

          Show
          Alex Anderson added a comment - Have been bitten by this (last week, grails 2.0.3, Tomcat ??).
          Hide
          Lari Hotari added a comment -

          Yet another stackoverflow question http://stackoverflow.com/a/12393628/166062 with solutions.

          Show
          Lari Hotari added a comment - Yet another stackoverflow question http://stackoverflow.com/a/12393628/166062 with solutions.
          Hide
          cdeszaq added a comment -

          This is still an issue in v2.2.0. At the very least, adding a commented out block to the logging configuration that either alerts the user to the potential issue when deploying, or better yet, provides a good solution that works in a multi-app tomcat install.

          I realize that logging is not slated to be dealt with quite yet, but sooner rather than later, since this seems to bite just about everyone who doesn't already know to look for it.

          Show
          cdeszaq added a comment - This is still an issue in v2.2.0. At the very least, adding a commented out block to the logging configuration that either alerts the user to the potential issue when deploying, or better yet, provides a good solution that works in a multi-app tomcat install. I realize that logging is not slated to be dealt with quite yet, but sooner rather than later, since this seems to bite just about everyone who doesn't already know to look for it.
          Graeme Rocher made changes -
          Fix Version/s 2.2.1 [ 13323 ]
          Fix Version/s 2.3 [ 13311 ]
          Priority Major [ 3 ] Blocker [ 1 ]
          Graeme Rocher made changes -
          Status Reopened [ 4 ] In Progress [ 3 ]
          Graeme Rocher made changes -
          Status In Progress [ 3 ] Closed [ 6 ]
          Fix Version/s 2.1.4 [ 13420 ]
          Resolution Fixed [ 1 ]

            People

            • Assignee:
              Graeme Rocher
              Reporter:
              InterZ
            • Votes:
              16 Vote for this issue
              Watchers:
              12 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Last Reviewed:

                Development