# Java und Syslog (Linux)



## gutenacht-steph (8. Okt 2010)

Hallo,

ich möchte in meinem Programm bestimmte Aktionen loggen. Geloggt werden soll es unter den Syslog logs von Linux (Ubuntu).

Im Internet gab es vorgefertigte Klassen dafür. Habe mir diese runtergeladen und versucht auszuführen. Was allerdings fehlschlägt.

Er gibt mir jedesmal die Exception "ICMP Port unreachable". Das bedeutet doch, er könne zum Port 514 keine Verbindung aufbauen, da er nicht geöffnet sei!?

Jedenfalls kann ich manuell in der Shell ohne Probleme etwas loggen, auch wenn ich den Parameter -d (dass die Nachricht als Datagram geschickt wird) mit angebe. 

Ich verstehe nicht, warum der Code (Benutzerdefiniertes Logging: Syslog) bei mir nicht funktioniert. Habe im Internet schon nach der Exception geschaut, werde aber nicht schlau daraus.

Würde mich sehr freuen wenn ihr mir helfen könntet.

Hier der Code

DatagramHandler:

```
public class DatagramHandler extends Handler {

    DatagramSocket socket;
    SocketAddress address;
    InetAddress i;
    int p;

    /**
     * Erzeugt einen DatagramHandler, der seine Eintr�ge an einen
     * bestimmten Host und Port schickt.
     */
    public DatagramHandler(String host, int port) throws SocketException, UnknownHostException {
        // Erzeuge DatagramSocket mit Verbindung zum Logging-Host
        socket = new DatagramSocket();
        address = new InetSocketAddress(host, port);
        socket.connect(address);
    }

    /**
     * Schlie�t den zugrundeliegenden Socket.
     */
    public void close() {
        // Schlie�en des Socket
        socket.close();
    }

    public void flush() {
        // Leeren von Puffern nicht notwendig,
        // da alle Daten direkt geschrieben werden.
    }

    /**
     * Schreibt den �bergebenen LogRecord zum Ziel.
     */
    public void publish(LogRecord rec) {
        if (isLoggable(rec)) {
            try {
                // Formatiere Nachricht
                Formatter formatter = getFormatter();
                String message = formatter.format(rec);
                byte[] data = message.getBytes();
                // Addressiere Paket und setze Daten

                DatagramPacket packet = new DatagramPacket(data, data.length, address);
                // Verschicke das Paket

                socket.send(packet);
            } catch (Exception ex) {
                reportError(ex.getMessage(), ex,
                        ErrorManager.WRITE_FAILURE);
            }
        }
    }
}
```

SyslogFormatter:

```
public class SyslogFormatter extends Formatter {

    private static SimpleDateFormat dateFormatter;
    private static Map levelMap;
    String hostname;

    static {
        // F�lle Puffer mit Zuordnungen von Java-Log-Levels zu
        // Syslog-Priorit�ten. Die Syslog-Priorit�t berechnet sich
        // aus Facility * 8 + Severity. Als Facility wird "User-Level"
        // vorausgesetzt (Wert 1).
        levelMap = new HashMap();
        // Error-Message
        levelMap.put(Level.SEVERE, "11");
        // Warning-Message
        levelMap.put(Level.WARNING, "12");
        // Information-Message
        levelMap.put(Level.INFO, "14");
        // Config-Messages gibt es in Syslog nicht, deshalb
        // werden sie als Information-Message behandelt
        levelMap.put(Level.CONFIG, "14");
        // Debug-Messages
        levelMap.put(Level.FINE, "15");
        levelMap.put(Level.FINER, "15");
        levelMap.put(Level.FINEST, "15");
        // Initialisiere Datum-Formatierer mit Syslog-Format
        dateFormatter = new SimpleDateFormat("MMM dd HH:mm:ss");
    }

    public SyslogFormatter() throws UnknownHostException {
        // Hole lokale Adresse zum sp�teren Einbauen in
        // die formatierte Nachricht.
        InetAddress localhost = InetAddress.getLocalHost()  ;
        hostname = localhost.getHostName();
    }

    /**
     * F�hrt die Formatierung des �bergebenen Log-Eintrags durch und gibt
     * den formatierten Eintrag zur�ck.
     */
    public String format(LogRecord rec) {
        StringBuffer message = new StringBuffer();
        try {
            // Priorit�t
            message.append("<");
            message.append(levelMap.get(rec.getLevel()));
            message.append(">");
            // Datum
            message.append(dateFormatter.format(new Date(rec.getMillis())));
            message.append(" ");
            // Hostname
            message.append(hostname);
            message.append(" ");
            // Message
            message.append(rec.getSourceClassName());
            message.append(".");
            message.append(rec.getSourceMethodName());
            message.append(": ");
            message.append(rec.getLevel());
            message.append(" ");
            message.append(rec.getMessage());
            message.append("\n");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // Syslog Nachrichten sind max. 1024 Bytes lang
        if (message.length() > 1024) {
            return message.substring(0, 1024);
        }
        return message.toString();
    }
}
```

Main:

```
public class Main {

    public static void main(String args[]) {
        try {
            Logger logger = Logger.getLogger("");
            Handler h = new DatagramHandler("127.0.0.1",514);
            h.setFormatter(new SyslogFormatter());
            
            logger.addHandler(h);
            logger.info("Syslog setup OK");

            LogRecord lr = new LogRecord(Level.parse("14"), "Abgeschickt");
            h.publish(lr);

        } catch (SocketException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnknownHostException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }


    }
}
```


Meine Exception:
[XML]java.util.logging.ErrorManager: 1: ICMP Port Unreachable
java.net.PortUnreachableException: ICMP Port Unreachable
        at java.net.PlainDatagramSocketImpl.send(Native Method)
        at java.net.DatagramSocket.send(DatagramSocket.java:629)
        at DatagramHandler.publish(DatagramHandler.java:61)
        at Main.main(Main.java:32)[/XML]


----------



## tuxedo (8. Okt 2010)

http://de.wikipedia.org/wiki/Internet_Control_Message_Protocol#Port_Unreachable hat gesagt.:
			
		

> Gängige Konvention ist das Absetzen eines „Port Unreachable“ als Antwort auf einen Verbindungsversuch zu einem nicht von einem Dienst geöffneten UDP-Port.



Ich würde mal blind drauf tippen, dass ein Syslog keine UDP Nachrichten auf Port 514 auf localhost entgegen nimmt ?!

Vielleicht muss man Syslog erst beibringen Log-Meldungen via Ethernet zu erhalten?!

- Alex


----------



## tuxedo (8. Okt 2010)

Hab mal schnell auf meinem Debian System geschaut...

in /etc/rsyslog.conf gibts es recht weit oben folgende Config-Zeilen:


```
# provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514

# provides TCP syslog reception
#$ModLoad imtcp
#$InputTCPServerRun 514
```

Die "#" ist wie bei den meisten Config-Files zum auskommentieren einer Option gedacht.
Wenn das bei dir genau so ist, solltest du die "#" entsprechend entfernen.

So, jetzt stellt sich nur noch die Frage: Wieso konnte ich das mit 5min googeln rausfinden und du nicht? Bin ja auch kein Syslog Experte ...

- Alex


----------



## gutenacht-steph (8. Okt 2010)

Danke tuxedo.

Das entfernen der "#" hat mein Problem gelöst.


----------

