https://bz.apache.org/bugzilla/show_bug.cgi?id=60632
Bug ID: 60632
Summary: Last logs lost when running Tomcat with systemd and
journald
Product: Tomcat 8
Version: 8.5.x-trunk
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: Catalina
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ----
Many people run Tomcat from systemd, and will be using 'journalctl' to manage
Tomcat's stdout. journalctl has a not-easily-fixed bug that causes the last few
stdout/stderr lines to be 'lost'. This is a problem, as the last few lines are
usually the most important. Here I suggest a small workaround in
bin/catalina.sh that I feel would be safe and worthwhile.
A simple example: let's deploy a Tomcat instance running as a dedicated user:
# useradd -s /bin/bash -d /tmp testtomcat
# su - testtomcat
curl -sLO
http://www-us.apache.org/dist/tomcat/tomcat-8/v8.5.11/bin/apache-tomcat-8.5.11.tar.gz
tar xf apache-tomcat-8.5.11.tar.gz
cd apache-tomcat-8.5.11
If we run 'bin/catalina.sh run' it starts normally.
testtomcat@jturner-desktop:~/apache-tomcat-8.5.11$ ./bin/catalina.sh run
Using CATALINA_BASE: /tmp/apache-tomcat-8.5.11
Using CATALINA_HOME: /tmp/apache-tomcat-8.5.11
Using CATALINA_TMPDIR: /tmp/apache-tomcat-8.5.11/temp
Using JRE_HOME: /usr/lib/jvm/java-8-oracle
Using CLASSPATH:
/tmp/apache-tomcat-8.5.11/bin/bootstrap.jar:/tmp/apache-tomcat-8.5.11/bin/tomcat-juli.jar
...
Let's introduce an error. Say we got JAVA_HOME wrong. We get an error message
as expected:
testtomcat@jturner-desktop:~/apache-tomcat-8.5.11$ JAVA_HOME=/incorrect/path
./bin/catalina.sh run
Using CATALINA_BASE: /tmp/apache-tomcat-8.5.11
Using CATALINA_HOME: /tmp/apache-tomcat-8.5.11
Using CATALINA_TMPDIR: /tmp/apache-tomcat-8.5.11/temp
Using JRE_HOME: /incorrect/path
Using CLASSPATH:
/tmp/apache-tomcat-8.5.11/bin/bootstrap.jar:/tmp/apache-tomcat-8.5.11/bin/tomcat-juli.jar
./bin/catalina.sh: 1: exec: /incorrect/path/bin/java: not found
testtomcat@jturner-desktop:~/apache-tomcat-8.5.11$
All find and dandy.
Now let's run Tomcat via systemd. Create a minimal service file as root and
load it:
# cat > /etc/systemd/system/testtomcat.service <<EOF
[Service]
Type=simple
User=testtomcat
ExecStart=/tmp/apache-tomcat-8.5.11/bin/catalina.sh run
EOF
# systemctl daemon-reload
(an aside: see https://jdebp.eu/FGA/systemd-house-of-horror/tomcat.html for why
we call catalina.sh run from systemd instead of startup.sh)
Start it, and see the status:
# systemctl start testtomcat
# systemctl status testtomcat -n5
● testtomcat.service
Loaded: loaded (/etc/systemd/system/testtomcat.service; static; vendor
preset: enabled)
Active: active (running) since Tue 2017-01-24 12:43:18 AEDT; 47s ago
Main PID: 30648 (java)
Tasks: 33
Memory: 109.2M
CPU: 3.979s
CGroup: /system.slice/testtomcat.service
└─30648 /usr/bin/java
-Djava.util.logging.config.file=/tmp/apache-tomcat-8.5.11/conf/logging.properties
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djdk.tls.ephemeralDHKeySize=2
Jan 24 12:43:20 jturner-desktop catalina.sh[30648]: 24-Jan-2017 12:43:20.173
INFO [localhost-startStop-1]
org.apache.catalina.startup.HostConfig.deployDirectory Deploying web
application directory /tmp/apache-to
Jan 24 12:43:20 jturner-desktop catalina.sh[30648]: 24-Jan-2017 12:43:20.182
INFO [localhost-startStop-1]
org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web
application directory /tmp/apach
Jan 24 12:43:20 jturner-desktop catalina.sh[30648]: 24-Jan-2017 12:43:20.184
INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler
[http-nio-8180]
Jan 24 12:43:20 jturner-desktop catalina.sh[30648]: 24-Jan-2017 12:43:20.187
INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler
[ajp-nio-8109]
Jan 24 12:43:20 jturner-desktop catalina.sh[30648]: 24-Jan-2017 12:43:20.188
INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 649 ms
Happiness. All working normally.
Now let's introduce an error. Any error that prevents Tomcat startup will do
(e.g. incorrect permissions), but let's go with our invalid JAVA_HOME example:
cat > /etc/systemd/system/testtomcat.service <<EOF
[Service]
Type=simple
User=testtomcat
Environment=JAVA_HOME=/incorrect/path
ExecStart=/tmp/apache-tomcat-8.5.11/bin/catalina.sh run
EOF
# systemctl daemon-reload
# systemctl restart testtomcat
# systemctl status testtomcat -n5
● testtomcat.service
Loaded: loaded (/etc/systemd/system/testtomcat.service; static; vendor
preset: enabled)
Active: failed (Result: exit-code) since Tue 2017-01-24 12:44:40 AEDT; 6s
ago
Process: 30846 ExecStart=/tmp/apache-tomcat-8.5.11/bin/catalina.sh run
(code=exited, status=127)
Main PID: 30846 (code=exited, status=127)
Jan 24 12:44:40 jturner-desktop systemd[1]: Started testtomcat.service.
Jan 24 12:44:40 jturner-desktop systemd[1]: testtomcat.service: Main process
exited, code=exited, status=127/n/a
Jan 24 12:44:40 jturner-desktop systemd[1]: testtomcat.service: Unit entered
failed state.
Jan 24 12:44:40 jturner-desktop systemd[1]: testtomcat.service: Failed with
result 'exit-code'.
Unhappiness, as expected, but note one important detail: the actual error
"./bin/catalina.sh: 1: exec: /incorrect/path/bin/java: not found" is missing in
the logs.
Again, the above is just an example. The last log message from ANY failure,
generated by scripts or Tomcat itself, will be lost.
Here's what's going on. The logs are not actually 'lost', but just not "tagged"
as belonging to the testtomcat unit (i.e. you can see them if you 'journalctl
-f' before start). This is due to a systemd bug marked cant-fix:
https://github.com/systemd/systemd/issues/1347
which I was referred to when questioning this behaviour on stackoverflow:
https://superuser.com/questions/1169906/systemd-bug-stdout-not-tagged-as-belonging-to-unit-when-non-root-user-specifie
The systemd bug isn't going to be fixed soon, as it relies on kernel additions.
Here's what Tomcat can do. A simple workaround is to 'sleep' for a short period
after emitting our last output, to give systemd a chance to tag it. Put this
near the top of bin/catalina.sh:
# If running in systemd, give it a chance to tag the last output.
https://github.com/systemd/systemd/issues/1347
trap 'sleep 0.1' INT TERM EXIT
and now when we 'systemctl status testtomcat' (or 'journalctl -u testtomcat')
we see the final error message:
# systemctl restart testtomcat
# systemctl status testtomcat
● testtomcat.service
Loaded: loaded (/etc/systemd/system/testtomcat.service; static; vendor
preset: enabled)
Active: failed (Result: exit-code) since Tue 2017-01-24 12:58:39 AEDT; 6s
ago
Process: 32326 ExecStart=/tmp/apache-tomcat-8.5.11/bin/catalina.sh run
(code=exited, status=127)
Main PID: 32326 (code=exited, status=127)
Jan 24 12:58:39 jturner-desktop systemd[1]: Started testtomcat.service.
Jan 24 12:58:39 jturner-desktop catalina.sh[32326]:
/tmp/apache-tomcat-8.5.11/bin/catalina.sh: 1: exec: /incorrect/path/bin/java:
not found
Jan 24 12:58:39 jturner-desktop systemd[1]: testtomcat.service: Main process
exited, code=exited, status=127/n/a
Jan 24 12:58:39 jturner-desktop systemd[1]: testtomcat.service: Unit entered
failed state.
Jan 24 12:58:39 jturner-desktop systemd[1]: testtomcat.service: Failed with
result 'exit-code'.
I'm not a POSIX guru but AFAIK 'trap' and '/bin/sleep' are pretty vanilla. The
choice of a 0.1s delay is not very scientific. It fixes the problem on my
system.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]