Nginx-Protokollierung in access.log.1 anstelle von access.log, Logrotate-Fehler?


20

Ich habe eine Nginx-Instanz, die den Zugriff auf /var/log/nginx/access.log und Fehler auf /var/log/nginx/errors.log protokolliert, aber sobald Logrotate jede Woche ausgeführt wird, wird die Datei verschoben * .log.1 und die neue * .log-Datei werden erstellt, aber nginx protokolliert weiterhin in der log.1-Datei anstelle der neuen .log-Datei (und es wird nichts gezippt). Das erste Mal, dass ich das bemerkte, war es 3 Wochen her, dass sich das Holz drehte und es riesig wurde. Beim Ausführen von kill -HUP `cat /run/nginx.pid`nginx wurde die Protokollierung erneut am richtigen Ort gestartet, das Problem trat jedoch in der nächsten Woche erneut auf.

Der wichtigere Grund, warum dies frustrierend ist, ist, dass ich die Protokolle so eingestellt habe, dass sie über rsyslog auf Loggly hochgeladen werden. Wenn nginx aufhört, in die Datei zu protokollieren, habe ich rsyslog-Polling, dann werden die Dinge nicht mehr hochgeladen und ich erhalte keine Warnungen.

Ich vermute, es hat etwas mit dem Neustart von nginx oder dem erneuten Laden der Konfiguration zu tun, da es nicht gestartet wurde, bis ich eine Konfigurationsänderung vorgenommen und die Konfiguration auf eine Weise neu geladen hatte, die ich für normal hielt. Ich habe versucht, auszuführen, kill -USR1 `cat /run/nginx.pid`aber die Dateien wurden weiterhin an der falschen Stelle protokolliert, bis ich ausgeführt kill -HUP `cat /run/nginx.pid`wurde. Ich weiß, dass dies das Problem nicht löst.

Irgendeine Idee, was los ist? Ich gebe zu, dass ich kein Experte für die Verwaltung von Logrotate oder Nginx bin, aber meine Googles haben mich in diesem Fall im Stich gelassen.

Hier ist mein Nginx-Logrotate-Skript, und lassen Sie mich wissen, ob Sie noch etwas sehen möchten. Die nginx.conf hat nichts Besonderes in Bezug auf die Protokollierung, außer das Definieren der Ausgabeorte.

/var/log/nginx/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
        endscript
}

EDIT: Ich denke, ich habe das Problem gefunden. Hier ist die Ausgabe der Ausführung von logrotate im Debug-Modus:

$ sudo logrotate --force -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx

Handling 1 logs

rotating pattern: /var/log/nginx/*.log  forced from command line (52 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/nginx/access.log
  log needs rotating
considering log /var/log/nginx/error.log
  log needs rotating
rotating log /var/log/nginx/access.log, log->rotateCount is 52
dateext suffix '-20141023'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
previous log /var/log/nginx/access.log.1 does not exist
renaming /var/log/nginx/access.log.52.gz to /var/log/nginx/access.log.53.gz (rotatecount 52, logstart 1, i 52), 
renaming /var/log/nginx/access.log.51.gz to /var/log/nginx/access.log.52.gz (rotatecount 52, logstart 1, i 51), 
renaming /var/log/nginx/access.log.50.gz to /var/log/nginx/access.log.51.gz (rotatecount 52, logstart 1, i 50), 
renaming /var/log/nginx/access.log.49.gz to /var/log/nginx/access.log.50.gz (rotatecount 52, logstart 1, i 49), 
renaming /var/log/nginx/access.log.48.gz to /var/log/nginx/access.log.49.gz (rotatecount 52, logstart 1, i 48), 
renaming /var/log/nginx/access.log.47.gz to /var/log/nginx/access.log.48.gz (rotatecount 52, logstart 1, i 47), 
renaming /var/log/nginx/access.log.46.gz to /var/log/nginx/access.log.47.gz (rotatecount 52, logstart 1, i 46), 
renaming /var/log/nginx/access.log.45.gz to /var/log/nginx/access.log.46.gz (rotatecount 52, logstart 1, i 45), 
renaming /var/log/nginx/access.log.44.gz to /var/log/nginx/access.log.45.gz (rotatecount 52, logstart 1, i 44), 
renaming /var/log/nginx/access.log.43.gz to /var/log/nginx/access.log.44.gz (rotatecount 52, logstart 1, i 43), 
renaming /var/log/nginx/access.log.42.gz to /var/log/nginx/access.log.43.gz (rotatecount 52, logstart 1, i 42), 
renaming /var/log/nginx/access.log.41.gz to /var/log/nginx/access.log.42.gz (rotatecount 52, logstart 1, i 41), 
renaming /var/log/nginx/access.log.40.gz to /var/log/nginx/access.log.41.gz (rotatecount 52, logstart 1, i 40), 
renaming /var/log/nginx/access.log.39.gz to /var/log/nginx/access.log.40.gz (rotatecount 52, logstart 1, i 39), 
renaming /var/log/nginx/access.log.38.gz to /var/log/nginx/access.log.39.gz (rotatecount 52, logstart 1, i 38), 
renaming /var/log/nginx/access.log.37.gz to /var/log/nginx/access.log.38.gz (rotatecount 52, logstart 1, i 37), 
renaming /var/log/nginx/access.log.36.gz to /var/log/nginx/access.log.37.gz (rotatecount 52, logstart 1, i 36), 
renaming /var/log/nginx/access.log.35.gz to /var/log/nginx/access.log.36.gz (rotatecount 52, logstart 1, i 35), 
renaming /var/log/nginx/access.log.34.gz to /var/log/nginx/access.log.35.gz (rotatecount 52, logstart 1, i 34), 
renaming /var/log/nginx/access.log.33.gz to /var/log/nginx/access.log.34.gz (rotatecount 52, logstart 1, i 33), 
renaming /var/log/nginx/access.log.32.gz to /var/log/nginx/access.log.33.gz (rotatecount 52, logstart 1, i 32), 
renaming /var/log/nginx/access.log.31.gz to /var/log/nginx/access.log.32.gz (rotatecount 52, logstart 1, i 31), 
renaming /var/log/nginx/access.log.30.gz to /var/log/nginx/access.log.31.gz (rotatecount 52, logstart 1, i 30), 
renaming /var/log/nginx/access.log.29.gz to /var/log/nginx/access.log.30.gz (rotatecount 52, logstart 1, i 29), 
renaming /var/log/nginx/access.log.28.gz to /var/log/nginx/access.log.29.gz (rotatecount 52, logstart 1, i 28), 
renaming /var/log/nginx/access.log.27.gz to /var/log/nginx/access.log.28.gz (rotatecount 52, logstart 1, i 27), 
renaming /var/log/nginx/access.log.26.gz to /var/log/nginx/access.log.27.gz (rotatecount 52, logstart 1, i 26), 
renaming /var/log/nginx/access.log.25.gz to /var/log/nginx/access.log.26.gz (rotatecount 52, logstart 1, i 25), 
renaming /var/log/nginx/access.log.24.gz to /var/log/nginx/access.log.25.gz (rotatecount 52, logstart 1, i 24), 
renaming /var/log/nginx/access.log.23.gz to /var/log/nginx/access.log.24.gz (rotatecount 52, logstart 1, i 23), 
renaming /var/log/nginx/access.log.22.gz to /var/log/nginx/access.log.23.gz (rotatecount 52, logstart 1, i 22), 
renaming /var/log/nginx/access.log.21.gz to /var/log/nginx/access.log.22.gz (rotatecount 52, logstart 1, i 21), 
renaming /var/log/nginx/access.log.20.gz to /var/log/nginx/access.log.21.gz (rotatecount 52, logstart 1, i 20), 
renaming /var/log/nginx/access.log.19.gz to /var/log/nginx/access.log.20.gz (rotatecount 52, logstart 1, i 19), 
renaming /var/log/nginx/access.log.18.gz to /var/log/nginx/access.log.19.gz (rotatecount 52, logstart 1, i 18), 
renaming /var/log/nginx/access.log.17.gz to /var/log/nginx/access.log.18.gz (rotatecount 52, logstart 1, i 17), 
renaming /var/log/nginx/access.log.16.gz to /var/log/nginx/access.log.17.gz (rotatecount 52, logstart 1, i 16), 
renaming /var/log/nginx/access.log.15.gz to /var/log/nginx/access.log.16.gz (rotatecount 52, logstart 1, i 15), 
renaming /var/log/nginx/access.log.14.gz to /var/log/nginx/access.log.15.gz (rotatecount 52, logstart 1, i 14), 
renaming /var/log/nginx/access.log.13.gz to /var/log/nginx/access.log.14.gz (rotatecount 52, logstart 1, i 13), 
renaming /var/log/nginx/access.log.12.gz to /var/log/nginx/access.log.13.gz (rotatecount 52, logstart 1, i 12), 
renaming /var/log/nginx/access.log.11.gz to /var/log/nginx/access.log.12.gz (rotatecount 52, logstart 1, i 11), 
renaming /var/log/nginx/access.log.10.gz to /var/log/nginx/access.log.11.gz (rotatecount 52, logstart 1, i 10), 
renaming /var/log/nginx/access.log.9.gz to /var/log/nginx/access.log.10.gz (rotatecount 52, logstart 1, i 9), 
renaming /var/log/nginx/access.log.8.gz to /var/log/nginx/access.log.9.gz (rotatecount 52, logstart 1, i 8), 
renaming /var/log/nginx/access.log.7.gz to /var/log/nginx/access.log.8.gz (rotatecount 52, logstart 1, i 7), 
renaming /var/log/nginx/access.log.6.gz to /var/log/nginx/access.log.7.gz (rotatecount 52, logstart 1, i 6), 
renaming /var/log/nginx/access.log.5.gz to /var/log/nginx/access.log.6.gz (rotatecount 52, logstart 1, i 5), 
renaming /var/log/nginx/access.log.4.gz to /var/log/nginx/access.log.5.gz (rotatecount 52, logstart 1, i 4), 
renaming /var/log/nginx/access.log.3.gz to /var/log/nginx/access.log.4.gz (rotatecount 52, logstart 1, i 3), 
renaming /var/log/nginx/access.log.2.gz to /var/log/nginx/access.log.3.gz (rotatecount 52, logstart 1, i 2), 
renaming /var/log/nginx/access.log.1.gz to /var/log/nginx/access.log.2.gz (rotatecount 52, logstart 1, i 1), 
renaming /var/log/nginx/access.log.0.gz to /var/log/nginx/access.log.1.gz (rotatecount 52, logstart 1, i 0), 
rotating log /var/log/nginx/error.log, log->rotateCount is 52
dateext suffix '-20141023'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
previous log /var/log/nginx/error.log.1 does not exist
renaming /var/log/nginx/error.log.52.gz to /var/log/nginx/error.log.53.gz (rotatecount 52, logstart 1, i 52), 
renaming /var/log/nginx/error.log.51.gz to /var/log/nginx/error.log.52.gz (rotatecount 52, logstart 1, i 51), 
renaming /var/log/nginx/error.log.50.gz to /var/log/nginx/error.log.51.gz (rotatecount 52, logstart 1, i 50), 
renaming /var/log/nginx/error.log.49.gz to /var/log/nginx/error.log.50.gz (rotatecount 52, logstart 1, i 49), 
renaming /var/log/nginx/error.log.48.gz to /var/log/nginx/error.log.49.gz (rotatecount 52, logstart 1, i 48), 
renaming /var/log/nginx/error.log.47.gz to /var/log/nginx/error.log.48.gz (rotatecount 52, logstart 1, i 47), 
renaming /var/log/nginx/error.log.46.gz to /var/log/nginx/error.log.47.gz (rotatecount 52, logstart 1, i 46), 
renaming /var/log/nginx/error.log.45.gz to /var/log/nginx/error.log.46.gz (rotatecount 52, logstart 1, i 45), 
renaming /var/log/nginx/error.log.44.gz to /var/log/nginx/error.log.45.gz (rotatecount 52, logstart 1, i 44), 
renaming /var/log/nginx/error.log.43.gz to /var/log/nginx/error.log.44.gz (rotatecount 52, logstart 1, i 43), 
renaming /var/log/nginx/error.log.42.gz to /var/log/nginx/error.log.43.gz (rotatecount 52, logstart 1, i 42), 
renaming /var/log/nginx/error.log.41.gz to /var/log/nginx/error.log.42.gz (rotatecount 52, logstart 1, i 41), 
renaming /var/log/nginx/error.log.40.gz to /var/log/nginx/error.log.41.gz (rotatecount 52, logstart 1, i 40), 
renaming /var/log/nginx/error.log.39.gz to /var/log/nginx/error.log.40.gz (rotatecount 52, logstart 1, i 39), 
renaming /var/log/nginx/error.log.38.gz to /var/log/nginx/error.log.39.gz (rotatecount 52, logstart 1, i 38), 
renaming /var/log/nginx/error.log.37.gz to /var/log/nginx/error.log.38.gz (rotatecount 52, logstart 1, i 37), 
renaming /var/log/nginx/error.log.36.gz to /var/log/nginx/error.log.37.gz (rotatecount 52, logstart 1, i 36), 
renaming /var/log/nginx/error.log.35.gz to /var/log/nginx/error.log.36.gz (rotatecount 52, logstart 1, i 35), 
renaming /var/log/nginx/error.log.34.gz to /var/log/nginx/error.log.35.gz (rotatecount 52, logstart 1, i 34), 
renaming /var/log/nginx/error.log.33.gz to /var/log/nginx/error.log.34.gz (rotatecount 52, logstart 1, i 33), 
renaming /var/log/nginx/error.log.32.gz to /var/log/nginx/error.log.33.gz (rotatecount 52, logstart 1, i 32), 
renaming /var/log/nginx/error.log.31.gz to /var/log/nginx/error.log.32.gz (rotatecount 52, logstart 1, i 31), 
renaming /var/log/nginx/error.log.30.gz to /var/log/nginx/error.log.31.gz (rotatecount 52, logstart 1, i 30), 
renaming /var/log/nginx/error.log.29.gz to /var/log/nginx/error.log.30.gz (rotatecount 52, logstart 1, i 29), 
renaming /var/log/nginx/error.log.28.gz to /var/log/nginx/error.log.29.gz (rotatecount 52, logstart 1, i 28), 
renaming /var/log/nginx/error.log.27.gz to /var/log/nginx/error.log.28.gz (rotatecount 52, logstart 1, i 27), 
renaming /var/log/nginx/error.log.26.gz to /var/log/nginx/error.log.27.gz (rotatecount 52, logstart 1, i 26), 
renaming /var/log/nginx/error.log.25.gz to /var/log/nginx/error.log.26.gz (rotatecount 52, logstart 1, i 25), 
renaming /var/log/nginx/error.log.24.gz to /var/log/nginx/error.log.25.gz (rotatecount 52, logstart 1, i 24), 
renaming /var/log/nginx/error.log.23.gz to /var/log/nginx/error.log.24.gz (rotatecount 52, logstart 1, i 23), 
renaming /var/log/nginx/error.log.22.gz to /var/log/nginx/error.log.23.gz (rotatecount 52, logstart 1, i 22), 
renaming /var/log/nginx/error.log.21.gz to /var/log/nginx/error.log.22.gz (rotatecount 52, logstart 1, i 21), 
renaming /var/log/nginx/error.log.20.gz to /var/log/nginx/error.log.21.gz (rotatecount 52, logstart 1, i 20), 
renaming /var/log/nginx/error.log.19.gz to /var/log/nginx/error.log.20.gz (rotatecount 52, logstart 1, i 19), 
renaming /var/log/nginx/error.log.18.gz to /var/log/nginx/error.log.19.gz (rotatecount 52, logstart 1, i 18), 
renaming /var/log/nginx/error.log.17.gz to /var/log/nginx/error.log.18.gz (rotatecount 52, logstart 1, i 17), 
renaming /var/log/nginx/error.log.16.gz to /var/log/nginx/error.log.17.gz (rotatecount 52, logstart 1, i 16), 
renaming /var/log/nginx/error.log.15.gz to /var/log/nginx/error.log.16.gz (rotatecount 52, logstart 1, i 15), 
renaming /var/log/nginx/error.log.14.gz to /var/log/nginx/error.log.15.gz (rotatecount 52, logstart 1, i 14), 
renaming /var/log/nginx/error.log.13.gz to /var/log/nginx/error.log.14.gz (rotatecount 52, logstart 1, i 13), 
renaming /var/log/nginx/error.log.12.gz to /var/log/nginx/error.log.13.gz (rotatecount 52, logstart 1, i 12), 
renaming /var/log/nginx/error.log.11.gz to /var/log/nginx/error.log.12.gz (rotatecount 52, logstart 1, i 11), 
renaming /var/log/nginx/error.log.10.gz to /var/log/nginx/error.log.11.gz (rotatecount 52, logstart 1, i 10), 
renaming /var/log/nginx/error.log.9.gz to /var/log/nginx/error.log.10.gz (rotatecount 52, logstart 1, i 9), 
renaming /var/log/nginx/error.log.8.gz to /var/log/nginx/error.log.9.gz (rotatecount 52, logstart 1, i 8), 
renaming /var/log/nginx/error.log.7.gz to /var/log/nginx/error.log.8.gz (rotatecount 52, logstart 1, i 7), 
renaming /var/log/nginx/error.log.6.gz to /var/log/nginx/error.log.7.gz (rotatecount 52, logstart 1, i 6), 
renaming /var/log/nginx/error.log.5.gz to /var/log/nginx/error.log.6.gz (rotatecount 52, logstart 1, i 5), 
renaming /var/log/nginx/error.log.4.gz to /var/log/nginx/error.log.5.gz (rotatecount 52, logstart 1, i 4), 
renaming /var/log/nginx/error.log.3.gz to /var/log/nginx/error.log.4.gz (rotatecount 52, logstart 1, i 3), 
renaming /var/log/nginx/error.log.2.gz to /var/log/nginx/error.log.3.gz (rotatecount 52, logstart 1, i 2), 
renaming /var/log/nginx/error.log.1.gz to /var/log/nginx/error.log.2.gz (rotatecount 52, logstart 1, i 1), 
renaming /var/log/nginx/error.log.0.gz to /var/log/nginx/error.log.1.gz (rotatecount 52, logstart 1, i 0), 
running prerotate script
running script with arg /var/log/nginx/*.log : "
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi \
"
renaming /var/log/nginx/access.log to /var/log/nginx/access.log.1
creating new /var/log/nginx/access.log mode = 0640 uid = 33 gid = 4
renaming /var/log/nginx/error.log to /var/log/nginx/error.log.1
creating new /var/log/nginx/error.log mode = 0640 uid = 33 gid = 4
running postrotate script
running script with arg /var/log/nginx/*.log : "
        [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
"
removing old log /var/log/nginx/access.log.53.gz
error: error opening /var/log/nginx/access.log.53.gz: No such file or directory

Es gibt jedoch nur Archive bis zu etwa * .log.8.gz, sodass logrotate bei der Interaktion mit fehlschlägt /var/log/nginx/access.log.53.gz. Warum um alles in der Welt versucht es das zu tun? Ich nehme an, ich muss gefälschte Dateien anfassen, um sie auszufüllen. Das scheint irgendwie falsch.


Es gibt keinen Grund, warum diese logrotierte Konferenz jede Nacht mit der weeklyFrequenz ausgeführt wird. Überprüfen Sie, ob Sie noch etwas mit Nginx zu tun haben.
Xavier Lucas

@Xavier Ah, es soll wöchentlich laufen, aber ich habe mich verwirrt. Ich habe gestern versucht, es zu beheben, aber das Problem ist über Nacht aufgetreten. Ich nehme an, ich habe den Tag gewählt, bevor das Protokoll für die Änderung auf Rotation eingestellt war, und da es sich letzte Nacht geändert hat, habe ich (ohne zu beachten) angenommen, dass es für die nächtliche Rotation eingestellt war. Ich habe meinen Beitrag aktualisiert, um genauer darzustellen, was gerade passiert.
Ben Torell

Scheint mir ein Fehler zu sein oder deine Statusdatei ist beschädigt ( /var/lib/logrotate/status). Durch Entfernen und erneutes Versuchen kann das Problem behoben werden. Wenn dies nicht der Fall ist, öffnen Sie ein Ticket.
Xavier Lucas

Antworten:


38

Bah, ich habe nach langer Zeit endlich die Antwort gefunden. Das Problem war in meinem Fall nicht, dass die Logrotation fehlschlug. Diese Fehlermeldung ist in Ordnung und hört tatsächlich nicht auf zu logrotieren. Das Problem bestand darin, dass nginx das Datei-Handle beim Empfang des -USR1Signals von nicht an die Protokolldatei weitergab kill. Kurz gesagt, der Grund, warum die Protokolldateien nicht erneut geladen wurden, war, dass der /var/log/nginxOrdner nicht demselben Benutzer gehörte wie die Nginx-Worker-Prozesse (im Besitz von www-data, ausgeführt unter Web). Ich habe keine Ahnung, wie sich dies geändert hat (möglicherweise, weil dieser Server kürzlich neu erstellt wurde), aber das Ändern des Ordners, dessen Eigentümer derselbe Benutzer wie der der Nginx-Worker-Prozesse ist (und das Reparieren der Logrotate-Datei, um neue Protokolle als Web-Protokolle zu erstellen), hat das Problem behoben.


Hatte dieses Problem für einige Zeit (vielleicht immer!) - und dachte, der Täter muss irgendwo in der logrotate-Konfiguration begraben werden. Gut gemacht!
Ring Ø

3
Vielleicht erwähnenswert: Nach dem Festlegen der Berechtigungen tun service nginx reload. Danach sind meine Logs angekommen .logund nicht.log.1
Soupdiver

Stellen Sie sicher, dass nicht nur Ihre Datei access.logund error.logdas /var/log/nginxVerzeichnis über Zugriffsberechtigungen verfügen, sondern auch über Ausführungsberechtigungen.
Yuvaraj Loganathan

2

Ich habe das gleiche Problem in Ubuntu 14.04, aber nachdem ich Ihre Antwort gelesen habe, habe ich überprüft, ob mein Nginx unter www-data läuft, wem der Ordner gehört, also ...

Ich habe jedoch diesen Fehler gefunden , der auf den Fehler im Postrotate-Abschnitt in /etc/logrotate.d/nginx hinweist.

Um das Problem zu beheben, können Sie einen Kommentar abgeben

invoke-rc.d nginx rotate >/dev/null 2>&1

und verwenden Sie stattdessen eine der folgenden Optionen (aus Kommentaren in diesem Fehler):

  • start-stop-daemon --stop --signal USR1 --quiet --pidfile /run/nginx.pid --name nginx
  • nginx -s neu laden
  • service nginx reload> / dev / null 2> & 1

-1

Eine weitere Ursache für dieses Problem kann das Auffüllen der Festplatte sein .

HINWEIS: Dies kann sogar passieren, wenn sich das Zugriffsprotokoll plötzlich füllt! DoS vielleicht?

Um dies zu reproduzieren können Sie Ihr Zugriffsprotokoll fill haben bis ganz plötzlich mit vielen Anfragen, einmal logrotateFeuer wird es bewegt access.logzu access.log.1, wird aber nicht die nächste Datei zu komprimieren und somit nicht das senden USR1Signal an nginx.

Wie beheben Sie das Problem?

  • Wenn Sie sich für Protokolle interessieren, leiten Sie die Datei über ssh + compress dorthin und bringen Sie sie zurück. Analysieren Sie unbedingt, warum sich die Zugriffs- oder Fehlerprotokolle so schnell füllen.
  • Wenn Sie nicht egal, gestutzt auf die Datei und reload nginx oder löschen und Neustart , sollten Sie nicht löschen und neu laden , da dies nicht die Inode freigeben wird (bitte nicht sagen Griff , ist es ein Windows - term)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.