Tip des Tages: Öfters mal Logfiles rotieren

Tomcat Logfiles können lang werden, daher sollte man diese desöftern rotieren.

Ganz unproblematisch ist das beim Tomcat aber nicht, denn im Gegensatz zu PHP Webanwendungen, stehen hier die Sessioninfos im RAM und nicht auf der Platte. Das hat beim Tomcat einen enormen Vorteil, weil der Server deutlich schneller an Infos kommt, als es z.B. PHP kann.

Der Nachteil liegt auf der Hand:  ein Neustart zerstört auch immer die Sessioninformationen. Gerade bei Shops ist das ein Problem. Hier muß die Sessionverwaltung dann auf Datenbanken ausgelagert werden, was bei verteilten Webanwendungen ohnehin gemacht werden muß.

Wo würde man daher das Logrotate ansetzen ?

Wer Serverdienste einsetzt, der braucht auch immer ein Startscript. Tomcat kommt zwar mit seinem eigenen startup.sh daher, aber auf ein klassisches Startscript ala init.d kann man eigentlich nicht verzichten. Hier ein Ausschnitt:

export CATALINA_HOME=/java/tomcat

ulimit -v unlimited -d unlimited -s unlimited -n 20000

PATH=$PATH:/usr/local/bin/

# See how we were called.
case "$1" in
 start)
 echo -n "Starting tomcat : "
 daemon /java/tomcat/bin/startup.sh
 RETVAL=$?
 echo
 ;;
 stop)
 echo -n "Stopping tomcat : "
 killtomcat
 RETVAL=$?
 echo
 ;;
 status)
 status tomcat
 RETVAL=$?
 ;;
 restart)
 $0 stop
 $0 start
 RETVAL=$?
 ;;
 *)
 echo "Usage: tomcat {start|stop|status|restart}"
 exit 1
esac

exit $RETVAL

und genau hier setzen wir an :

# See how we were called.
case "$1" in
 start)
 echo -n "Rotating Logs : "
 cd /usr/java/apache-tomcat/logs/
 echo "Deleting old files : "
 find . -ctime +100 -name "catalina.out*" -exec rm -fv {} \;
 COUNTER=0
 while [ $COUNTER -lt 99 ]; do
       echo The counter is $COUNTER
       let COUNTER=COUNTER+1
       if [ ! -f "catalina.out.$COUNTER" ]; then
           FILENAME="catalina.out.$COUNTER";
           break;
       fi
 done
 echo "Benutze $FILENAME";
 mv catalina.out $FILENAME
 echo "Compressing Logfile : $FILENAME"
 bzip2 -9 $FILENAME
 echo -n "Starting tomcat : "
 daemon /java/tomcat/bin/startup.sh
 RETVAL=$?
 echo
 ;;

Dieses Script ist natürlich nur ein Beispiel. Ihr müßt es noch anpassen an Eure Pfade und Präferenzen. Es wird Logfiles löschen, die älter als 100 Tage sind und maximal bis .99 zählen. Das kann je nach Häufigkeit des Starts Eures Tomcats dann eventuell nicht passen. Da müßt Ihr jetzt Eure Erfahrungen für Eurer System berücksichtigen.

Bitte beachtet, daß BZIP2 ein echter Zeitfresser ist, besonders in der Kombination mit 8 GB Logfile und -9 Option. Das packt hier auf einem nicht langsamen Server bereits seit 50 MInuten 😉 Das Ergebnis ist allerdings genial:

catalina.out.5: 53.987:1, 0.148 bits/byte, 98.15% saved, 8.250.838.531 in, 152.828.685 out.

Unter 2 % sind vom Logfile übrig geblieben 🙂

Wer jetzt meint, daß dieser Beitrag den 50 Minuten geschuldet ist, hat recht 😀 War leider ein echter Blocker.

 

Servlet und JSP verbinden

Kleine Exkursion in die Welt von JavaServerPages und Servlets und wie man dazwischen Daten austauschen kann. Zunächst mal die einfache Seite, die JSP :

<%@ page import="java.net.IDN,misc.*,web.*,java.util.*,rsi.*,hash.*,sendmail.Sendmail,java.io.*,server.*,org.json.JSONArray,org.json.JSONObject,ordb.Pandora_server" pageEncoding="UTF-8"
%><%@ include file="cookies.jsp"
%><jsp:useBean id="daten" scope="session" class="hash.StringHash"
/>

Der JSP:useBean Tag ermöglicht u.a. sessionbasierte Objekte in einer JSP zu verarbeiten. Überall wo man den Tag angibt, ist das Objekt verfügbar. Da kann man dann ganz normal drauf zugreifen und mit arbeiten.

if ( daten.checkContent() ) out.write("Daten wurden geprüft und für OK befunden");

Wenn nun ein zweiter Teil der Anwendung in einem Servlet geschrieben wurde,  möchte man ggf. Daten zwischen beiden Teilen der Anwendung austauschen. Ein Servlet ist nichts anderes als eine Klasse, deren vordefinierte Methoden das Request- und Responseobjekt des Webaufrufes bekommen.

Ein kleines, stark vereinfachtes Beispiel:

public class HTMLDispatcher extends HttpServlet {

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
    doRequest(req,res);
}

public void doPut(HttpServletRequest req, HttpServletResponse res)
throws IOException {
    doRequest(req,res);
}

public void doDelete(HttpServletRequest req, HttpServletResponse res)
throws IOException {
    doRequest(req,res);
}

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException {
    doRequest(req,res);
}

...
}

Das Servlet kann man dann im Tomcat ( WebApplicationServer ) als Ziel für verschiedene Webaufrüfe definieren (siehe unten). In meinem Fall habe ich gesagt, daß mein Servlet für HTML Aufrüfe zuständig ist. Mein Servlet wertet dann die URL aus und macht mit dem HTML File noch einiges, bevor es ausgegeben wird.

public void doRequest(HttpServletRequest request, HttpServletResponse res)
throws IOException {

res.setContentType("text/html");
Writer out = new BufferedWriter(new OutputStreamWriter(res.getOutputStream(), "UTF-8"));

String method = request.getMethod();
String uri = request.getRequestURI();
String[] args = uri.split("/",-1); // Alles splitten, auch wenn es leer ist

StringHash daten = (StringHash) request.getSession().getAttribute("daten");
if ( daten == null ) daten = new StringHash();

Um an die Daten aus der JSP zu kommen, setze ich „request.getSession().getAttribute(„daten“)“ ein. Das geht aber nur mit Sessionobjekten so. Da die Methode getAttribute() ein klassenloses Objekt zurück gibt, muß selbst den TypeCast machen. Wenn noch keine Session aufgebaut wurde, kann es auch noch kein Bean geben, das wir uns krallen könnten. Damit die Anwendung dann nicht abschmiert, lege ich hier ein Objekt an. Natürlich kann man an der Stelle auch eine Fehlermeldung oder einen Redirect auslösen. Das ist situationsabhängig.

O== Warum überhaupt Servlet und JSP mischen ?

Servlets müssen kompiliert und der WAS Server üblicherweise neu gestartet werden, um die Änderungen anzunehmen. Wenn man JSP Seiten benutzt kümmert sich Jasper darum. Das spart im Einzelfall eine Menge Zeit und man verliert dabei auch keine Sessionobjekte, d.h. kleinere Fehler kann man direkt beheben und weitermachen. Zweifelsfrei eine zeitsparende Methode seine Webseiten zu bauen.

O== Wofür setzt man ein Servlet ein ?

Servlets können auf spezielle Webanfragen eingestellt werden, d.b. bspw. alle Files die auf .jos enden, könnten eine serialisierte Repräsentation des JavaObjekts einer Seite ausgeben, statt HTML Code. Das bekommt man mit reinen JSP Seiten nicht hin.

O== Wie aktiviert man ein Servlet ?

Im WEB-INF Verzeichnis der Anwendung liegt die web.xml Datei. In dieser Datei kann man ein Servlet ganz leicht hinzufügen:

    <servlet>
        <servlet-name>HTMLDispatcher</servlet-name>
        <servlet-class>servlet.HTMLDispatcher</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HTMLDispatcher</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

Die nötigen Klassen müssen dann im dortigen classes Verzeichnis hinterlegt sein.

Tomcat: Manager App nicht verfügbar

Kleine Ursache, großes Tralala

Einer meiner Tomcats hat mich heute mit der Meldung beglückt, daß er die Resource „/manager/html“ nicht zur Verfügung stellen könne, obwohl die Anwendung installiert ist. Das ist ist immer, da diese zum Defaultzustand eines Tomcats dazugehört. Darüber lassen sich Webanwendungen als WAR File installieren.

Jetzt findet man im Netz alle erdenklichen Ansätze, leider half heute nicht einer.

Das erste was auffiel war, daß das Manager Verzeichnis zwar da war, aber die anderen normalen Verzeichnisse im webapps Verzeichnis  nicht:

drwxr-xr-x  5 root root     4096 13. Aug 2013  host-manager
drwxr-xr-x  5 root root     4096 13. Aug 2013  manager
drwxr-xr-x  3 root root     4096 18. Feb 2012  plattform
drwxr-xr-x  3 root root     4096 13. Aug 2013  ROOT

Wenn das nicht der Fall ist, kann es gehen, muß aber nicht. Diese holt man sich aus dem Tomcat ZIP/TGZ File. Wenn man dies nicht mehr zur Hand hat, einfach nochmal von der Webseite runterladen.

Die eigentliche Störungsquelle

Damit habe ich dann nicht gerechnet. Die eigentliche Störungsquelle war trivialer Natur. Die früher installierte Webanwendung war defekt und verhinderte den korrekten Start des Tomcats, obwohl im Logfile dazu kein Hinweis stand! Mit sowas rechnet man nicht, daß bis dato die Webanwendung lief.

In dem Fall einfach von Hand die alte WAR Datei aus dem Webapps Verzeichnis entfernen und den Tomcat neustarten.

Danach war auch der Manager wieder erreichbar.