Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

10. Nach der Installation: das Betriebshandbuch

Der Installer hinterlässt Ihnen eine Site, die ihre erste Anfrage beantwortet. Dieses Kapitel macht daraus eine Site, die Sie betreiben können: das Administratorkonto absichern, die Adressen der Site richtig einstellen…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/install/10-after-installing.md

On this page

This page is a translation. Read the English original

10. Nach der Installation: das Betriebshandbuch

Der Installer hinterlässt Ihnen eine Site, die ihre erste Anfrage beantwortet. Dieses Kapitel macht daraus eine Site, die Sie betreiben können: das Administratorkonto absichern, die Adressen der Site richtig einstellen, die Cronjobs einplanen, die veröffentlichen, benachrichtigen und aufräumen, echte Mails versenden, wissen, welcher Cache wann zu leeren ist, die Autoloads der Klassen und den Suchindex aktuell halten, die Logs lesen und rotieren, Sicherungen anlegen, die Sie tatsächlich wiederhergestellt haben, die Site überwachen, sie auf Geschwindigkeit trimmen, Extensions und ihre Reihenfolge verwalten und Sprachen hinzufügen. Jeder Teil erklärt, was der Mechanismus tut, nennt die Befehle mit den Einstellungen, die sie lesen, und endet mit einer Möglichkeit, das Ergebnis zu prüfen. Arbeiten Sie das Kapitel nach der Installation einmal der Reihe nach durch; danach dient es als Nachschlagewerk.

Warnung .htaccess bremst jede Anfrage. Sind .htaccess-Dateien erlaubt (AllowOverride alles außer None), geschweige denn genutzt, sucht Apache sie bei jeder Anfrage in jedem Verzeichnis des Pfads und liest und wertet sie aus, und die Ladezeiten der Seiten steigen drastisch (gemessen). Die einzige wirkliche Abhilfe ist, die Funktion für den virtuellen Host abzuschalten: AllowOverride None im virtuellen HTTPS-Host, und die Regeln in der Konfiguration des virtuellen Hosts selbst als mod_rewrite-Regeln. Das ist in Geschwindigkeitstests im Produktivbetrieb weit schneller und die Zeit für die Optimierung einer Produktivkonfiguration unbedingt wert. Stellen Sie sofort um: Übernehmen Sie die Regeln des Beispiels für einen virtuellen HTTPS-Host in Ihren virtuellen Host (mit dem statischen Cache auch staticcache_offload.conf), setzen Sie AllowOverride None, führen Sie apachectl configtest aus, laden Sie Apache neu und testen Sie die Website. Dieselben Regeln für andere Server: nginx, LiteSpeed, Caddy, IIS, Velocity (eingebaut); wohin Regeln für virtuelle Hosts in einem Control Panel gehören: Plesk, cPanel, DirectAdmin, ISPConfig. Unter LiteSpeed oder OpenLiteSpeed kann zusätzlich der Seiten-Cache des Servers anonyme Besucher und Crawler ohne PHP bedienen: Seiten-Caching mit LiteSpeed und OpenLiteSpeed.

Inhalt · Zurück: 9. Datenbanken · Weiter: 11. Upgrade

Inhalt

Konventionen in diesem Kapitel

  • Jeder Befehl wird im Installationsverzeichnis ausgeführt, dem Verzeichnis, das index.php enthält.
  • php bin/php/console ist die Befehlskonsole; viele Installationen verlinken sie als ./console. php bin/php/console list zeigt jeden Befehl, php bin/php/console list cron einen Namensraum.
  • Skripte verweigern die Ausführung als root, sofern sie nicht --allow-root-user erhalten. Führen Sie Routinearbeiten und vor allem Cron als eigenen Benutzer der Site aus; dann ist die Option nicht nötig, und Dateien werden mit dem richtigen Eigentümer angelegt. Die Beispiele enthalten die Option, damit sie sich unverändert kopieren lassen. bin/php/ezpgenerateautoloads.php hat keine eigene root-Prüfung; es akzeptiert die Option, damit dieselbe Gewohnheit auch dort funktioniert (10.7).
  • Dateien, die root anlegt, gehören root. Eine Cache- oder Log-Datei, die root angelegt hat und die der Benutzer des Webservers nicht überschreiben kann, ist die häufigste Ursache für Fehler nach Wartungsarbeiten (Kapitel 12). Wenn Sie als root arbeiten müssen, führen Sie den Befehl stattdessen als Benutzer der Site aus: sudo -u <site user> php ....
  • Einstellungen werden nie in settings/*.ini bearbeitet. Overrides gehören nach settings/override/<file>.ini.append.php (die ganze Installation) oder settings/siteaccess/<name>/<file>.ini.append.php (ein Siteaccess). php bin/php/console exp:ini liest und schreibt sie in jedem Geltungsbereich (exp:ini); führen Sie nach einer Bearbeitung von Hand php bin/php/ezcache.php --clear-tag=ini --allow-root-user aus.
  • site und admin stehen für die Namen Ihres öffentlichen Siteaccess und Ihres Administrations-Siteaccess (die Voreinstellungen von exp:install).

10.1 Erste Anmeldung und das Administratorpasswort

  1. Adresse und Passwort finden. Die Zusammenfassung des Installers hat die Adresse der Admin-Anmeldung (beim voreingestellten URL-Zugriff /admin/user/login unterhalb der Adresse der Site) und den Benutzer admin ausgegeben. Ein generiertes Passwort wurde einmal angezeigt und in var/log/initial-admin-password geschrieben, nur für dessen Eigentümer lesbar.

  2. Melden Sie sich an und ändern Sie das Passwort sofort: in der Administration über Passwort ändern im Benutzermenü oder direkt unter /admin/user/password. Die Seite listet die Anforderungen neben dem Feld auf: mindestens [UserSettings] MinPasswordLength Zeichen (ausgeliefert 10, settings/site.ini), kein bekanntes oder gängiges Passwort (WeakPasswordCheck, seit 6.0.15) und die Regeln aus [PasswordSettings], die Sie eingeschaltet haben. Wählen Sie ein langes, zufälliges Passwort. Der Benutzer erhält eine E-Mail darüber, dass das Passwort geändert wurde (ChangeNotificationMail); das ist zugleich der erste Test Ihrer Mail-Einstellungen (10.4).

  3. Entfernen Sie die Passwortdatei, sobald Sie sich mit dem neuen Passwort angemeldet haben:

    rm var/log/initial-admin-password
  4. Geben Sie dem Administrator eine echte E-Mail-Adresse (bearbeiten Sie das Benutzerobjekt des Administrators in der Administration), damit das Zurücksetzen des Passworts per Mail jemanden erreicht.

Ein verlorenes Passwort wird auf der Kommandozeile zurückgesetzt. Als root-Benutzer des Betriebssystems ist keine weitere Anmeldung nötig:

php bin/php/resetuserpassword.php -u admin -g --allow-root-user

-u nennt den Benutzer (Voreinstellung admin); -g generiert ein Passwort (-l <length>, Voreinstellung 16) und gibt es aus; -p <password> setzt eines; -a <login> mit -ap <password> autorisiert das Zurücksetzen stattdessen mit der Anmeldung eines anderen Administrators, für den Fall, dass Sie nicht root des Betriebssystems sind. Ein mit -p übergebenes Passwort ist in der Prozessliste und in der Shell-Historie sichtbar; verwenden Sie lieber -g und ändern Sie das Passwort nach der Anmeldung. Siehe Ein Benutzerpasswort zurücksetzen und Ihr Passwort ändern. Alle Wege, es zu ändern, die Voreinstellung je Installationsmethode und wie Sie die Anmeldung admin stilllegen: Das Administratorpasswort ändern, Das voreingestellte Administratorpasswort.

10.2 Siteaccesses und Adressen der Site

Ein Siteaccess ist ein Zugang zur Installation: ein Name, ein Satz Einstellungen in settings/siteaccess/<name>/ und eine Regel, welche Anfragen er beantwortet. Der Installer legt mindestens den öffentlichen Siteaccess und die Administration an. Die Regeln stehen in site.ini [SiteAccessSettings]:

SchlüsselAusgeliefertBedeutung
AvailableSiteAccessList[]vom Installer gesetztJeder Siteaccess, den die Installation kennt.
MatchOrderuri;host;portDie Arten, wie eine Anfrage zugeordnet wird, der Reihe nach versucht: uri, host, host_uri, port, servervar.
URIMatchType, URIMatchElementelement, 1Mit uri: Das erste Pfadelement nennt den Siteaccess (/admin/...).
HostMatchType, HostMatchMapItems[]mapMit host: Ein Hostname wird einem Siteaccess zugeordnet, HostMatchMapItems[]=www.example.com;site.
RelatedSiteAccessList[]Siteaccesses, die sich eine Datenbank teilen.
ForceVirtualHostfalsetrue, wenn der Webserver jede Adresse auf index.php umschreibt, wie es die ausgelieferten Regeln und Velocity tun. Jede Installation (Setup-Assistent, Kickstarter, exp:install, jedes Seitenpaket) schreibt true in settings/override/site.ini.append.php, wenn der Server umschreibt, damit kein generierter Link /index.php enthält. Nur auf einem Server ohne Rewrite-Regeln wieder auf false setzen.
RemoveSiteAccessIfDefaultAccessdisabledenabled lässt den Namen des voreingestellten Siteaccess in generierten Links weg.
RequireUserLogintrue in site.iniWird je Siteaccess überschrieben; eine öffentliche Site setzt es auf false.

In site.ini [SiteSettings] jedes Siteaccess:

SchlüsselBedeutung
SiteURLDie Adresse der Site ohne Schema (www.example.com, oder www.example.com/admin bei URL-Zugriff). Wird in Mails, Feeds, Sitemaps und von exp:benchmark verwendet.
DefaultAccessDer Siteaccess, den eine Anfrage erhält, wenn keine Regel gegriffen hat.
SiteList[]Die öffentlichen Siteaccesses, von der Administration für Vorschauen und Links verwendet.

Der Installer hat eines von drei Schemata gewählt (exp:install --access=url|host|port):

  • URL (/admin): ein Hostname für alles; am einfachsten hinter jedem Webserver.
  • Host (admin.example.com): ein Hostname je Siteaccess; am besten für den Produktivbetrieb und für HTTPS-Zertifikate je Host.
  • Port (:8081): ein Port je Siteaccess; nützlich für die lokale Arbeit.

Um nach der Installation von URL- auf Host-Zugriff umzustellen, zum Beispiel:

# settings/override/site.ini.append.php
[SiteAccessSettings]
MatchOrder=host;uri
HostMatchType=map
HostMatchMapItems[]
HostMatchMapItems[]=www.example.com;site
HostMatchMapItems[]=admin.example.com;admin

und in settings/siteaccess/site/site.ini.append.php und settings/siteaccess/admin/site.ini.append.php [SiteSettings] SiteURL=www.example.com bzw. admin.example.com setzen. Leeren Sie den INI-Cache, tragen Sie die Hostnamen beim Webserver (Kapitel 8) und im DNS ein und prüfen Sie, welchen Siteaccess eine Adresse erreicht. Die Administration verlangt eine Anmeldung, die öffentliche Site nicht, was den Unterschied leicht erkennbar macht:

php bin/php/ezcache.php --clear-tag=ini --allow-root-user
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' https://admin.example.com/
curl -s -o /dev/null -w '%{http_code}\n' https://www.example.com/

Erwarten Sie vom Admin-Host eine Weiterleitung auf .../user/login (oder die Anmeldeseite selbst) und vom öffentlichen Host 200. Antworten beide gleich, greift die Host-Zuordnung nicht: Der Hostname, den der Browser sendet, muss genau dem in HostMatchMapItems[] entsprechen, ohne Port und in Kleinbuchstaben.

Hinter einem Proxy oder Load Balancer. Das Schema (http oder https) und der Hostname, den der Besucher angefragt hat, werden nur dann aus weitergeleiteten Headern (X-Forwarded-Proto, X-Forwarded-Host, ...) übernommen, wenn die Anfrage von einer Adresse in site.ini [HTTPHeaderSettings] TrustedProxies[] kommt (ausgeliefert: 127.0.0.1 und ::1, ein Proxy auf demselben Rechner); die Adresse des Besuchers wird nur dann aus X-Forwarded-For gelesen, wenn zusätzlich ClientIpByCustomHTTPHeader=X-Forwarded-For gesetzt ist. Jeder kann diese Header senden, deshalb wird ihnen nur von den Proxys geglaubt, die Sie auflisten. Ein Proxy auf einem anderen Rechner muss hinzugefügt werden, sonst behandelt die Site HTTPS-Anfragen als einfaches HTTP und verzeichnet die Adresse des Proxys als die jedes Besuchers:

# settings/override/site.ini.append.php
[HTTPHeaderSettings]
TrustedProxies[]
TrustedProxies[]=127.0.0.1
TrustedProxies[]=::1
TrustedProxies[]=10.0.0.5
ClientIpByCustomHTTPHeader=X-Forwarded-For

Die leere Zeile TrustedProxies[] ersetzt die ausgelieferte Liste; wiederholen Sie daher die Loopback-Einträge, wenn Sie sie weiterhin brauchen. Siehe Kapitel 8 und Vertrauenswürdige Proxys.

Einstellungen je Site innerhalb einer Extension, um mehrere Sites aus einer Installation zu betreiben, werden unter Einstellungen je Site innerhalb von Extensions erklärt.

10.3 Cronjobs

Cronjobs erledigen die Arbeit, auf die kein Besucher wartet: Sie veröffentlichen und verbergen Inhalte nach Zeitplan, versenden Benachrichtigungen, setzen Inhaltsjobs fort, führen die Wartung des Audit-Protokolls aus, importieren Feeds, indizieren Inhalte und räumen auf. Ohne sie funktioniert eine Site zwar, aber geplante Inhalte erscheinen nie, Benachrichtigungen gehen nie hinaus, und Caches und Entwürfe stapeln sich auf der Festplatte.

Wie runcronjobs.php funktioniert

runcronjobs.php führt Teile aus: benannte Listen von Skripten in settings/cronjob.ini. Extensions fügen über [CronjobSettings] ExtensionDirectories[] eigene Teile und Verzeichnisse hinzu. Ohne Namen eines Teils aufgerufen, führt es die Skripte aus [CronjobSettings] Scripts[] aus, den Standardteil.

php runcronjobs.php --list --allow-root-user                       # every part and its scripts
php runcronjobs.php -s site frequent --allow-root-user              # one part
php runcronjobs.php -s site --script=notification.php --allow-root-user   # one script
php runcronjobs.php -s site --allow-root-user                       # the default part

-s (--siteaccess) wählt den Siteaccess, dessen Einstellungen die Skripte lesen; verwenden Sie den öffentlichen Siteaccess, sofern ein Teil nichts anderes verlangt (die Oracle-Teile wollen die Administration). -q unterdrückt die Ausgabe außer Fehlern. In --list erscheint jedes Skript einmal je durchsuchtem Verzeichnis; diese Wiederholung ist normal. Jeder Teil hat außerdem einen Konsolen-Alias, php bin/php/console cron:<part> (zum Beispiel cron:frequent), und die Administration führt jeden Teil unter Setup > Cronjobs aus; dort lässt sich die Ausgabe während des Laufs verfolgen, und die Seite schlägt Crontab-Zeilen vor. Teile, die in [AdminSettings] ForbiddenParts[] aufgeführt sind (ausgeliefert: cluster_maintenance, unlock), lassen sich dort nicht starten. MaxScriptExecutionTime (ausgeliefert 43200 Sekunden) begrenzt die Laufzeit eines Skripts.

Die Teile und ihre Skripte

Die Teile des Kernels (settings/cronjob.ini):

TeilSkriptWas es tut
defaultunpublish.phpFührt geplante Aktionen zum Zurückziehen der Veröffentlichung aus.
defaultrssimport.phpHolt die konfigurierten RSS-Importe in den Inhaltsbaum.
defaultindexcontent.phpIndiziert Inhalte, deren Indizierung verzögert wurde ([SearchSettings] DelayedIndexing).
defaulthide.phpFührt geplante Aktionen zum Verbergen und Wiederanzeigen aus.
defaultinternal_drafts_cleanup.phpEntfernt interne Entwürfe, die älter als das konfigurierte Alter sind.
frequentnotification.phpVerarbeitet ausstehende Benachrichtigungsereignisse und versendet die Nachrichten und Sammelmails.
frequentworkflow.phpFührt ausstehende Workflow-Ereignisse aus und bringt hängende Workflows voran.
frequentcontentjobs.phpSetzt Inhaltsjobs fort, deren Worker abgestürzt ist, und startet wartende (umfangreiches Entfernen und Kopieren).
frequentaudit.phpDas Audit-Protokoll: Sink-Spools, Alarmregeln, Rotation nach Tag, Archive, Aufbewahrung, Prüfpunkte.
frequentmailbounces.phpLiest das Bounce-Postfach: Harte Bounces und Beschwerden kommen auf die Sperrliste.
infrequentbasket_cleanup.phpEntfernt verlassene Warenkörbe des Shops.
infrequentlinkcheck.phpPrüft die internen und externen Links in veröffentlichten Inhalten.
infrequentmailpreferences.phpAufbewahrung der E-Mail-Präferenzen: Einwilligungsprotokoll, abgelaufene Bestätigungen, alte Einträge der Sperrliste.
cache_cleanupcachecleanup.php, httpcache_cleanup.phpEntfernt View-Cache- und Cache-Block-Dateien, die nie wieder ausgeliefert werden können, sowie abgelaufene Einträge des HTTP-Caches ([CacheCleanupSettings] MaxAge, ausgeliefert zwei Tage).
cleanuprsscleanuprss.phpKürzt per RSS importierte Inhalte auf die neuesten Einträge jedes Feeds; tut nichts, solange content.ini [RSSImportCleanupSettings] keine Klassen nennt.
cluster_maintenanceclusterpurge.phpLöscht abgelaufene Dateien eines Datenbank-Cluster-Backends endgültig.
unlockunlock.phpGibt Inhaltsobjekte frei, die in einem gesperrten Bearbeitungszustand hängen.

Einzelne Teile gibt es für contentjobs, audit, notification, mailpreferences und mailbounces, sodass jeder nach eigenem Zeitplan laufen kann. cronjobs/ enthält weitere Skripte, die kein ausgelieferter Teil aufführt; sie werden mit --script= ausgeführt oder einem eigenen Teil hinzugefügt: session_gc.php (abgelaufene Sitzungen, siehe unten), old_drafts_cleanup.php, trashpurge.php (leert den Papierkorb, oder mit content.ini [TrashSettings] KeepItemsForDays nur das, was älter ist), staticcache_cleanup.php, subtreeexpirycleanup.php und updateviewcount.php.

Aktive Extensions fügen weitere Teile hinzu; php bin/php/console list cron zeigt sie mit einer Beschreibung, zum Beispiel die Newsletter-Teile (10.5), die Sitemap-Teile von bcgooglesitemaps und xrowmetadata sowie die Oracle-Teile (Kapitel 9).

Eine Crontab

Installieren Sie sie in der Crontab des Benutzers der Site (crontab -e -u <site user> oder php bin/php/console crontab:edit; crontab:list zeigt die aktuelle):

# m   h  dom mon dow  command
*/5   *  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site frequent >> var/log/cron-frequent.log 2>&1
*/15  *  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site >> var/log/cron-default.log 2>&1
17    *  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site infrequent >> var/log/cron-infrequent.log 2>&1
40    3  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site cache_cleanup >> var/log/cron-cleanup.log 2>&1
50    3  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site --script=session_gc.php >> var/log/cron-cleanup.log 2>&1
  • Verwenden Sie dasselbe PHP-Binary, das der Webserver verwendet (/opt/.../php auf Hosts mit mehreren PHP-Versionen); php -v in der Cron-Umgebung kann von dem Ihrer Shell abweichen.
  • frequent alle paar Minuten ist das, was Benachrichtigungen und Inhaltsjobs erwarten; infrequent stündlich oder täglich.
  • session_gc.php entfernt Sitzungen, die älter als site.ini [Session] SessionTimeout sind (ausgeliefert 31104000 s, 360 Tage), wo die Sitzungsbereinigung von PHP durch das Betriebssystem nicht läuft. Dasselbe von Hand: php bin/php/ezsessiongc.php --allow-root-user.
  • Rotieren Sie die Dateien cron-*.log mit logrotate des Systems (10.10).

Prüfen Sie, dass die Jobs laufen: Die Dateien wachsen, Setup > Cronjobs zeigt die letzte Ausgabe, und der Statusbefehl der Benachrichtigungen meldet den letzten Lauf (10.5).

Velocity hat einen eigenen Scheduler, der Handler-Funktionen zu bestimmten Zeiten oder in Intervallen ausführt, solange der Server läuft. Er ersetzt den System-Cron für diese Teile nicht von Haus aus: Er braucht einen Handler, den Sie schreiben, und er holt keine Zeitpunkte nach, die verpasst wurden, während der Server nicht lief.

10.4 Mail: der Datei-Transport und echter Versand

Exponential versendet Mails bei Passwortänderungen, Registrierungen, Formularen, Benachrichtigungen und Newslettern. Der Transport des Kernels wird in site.ini [MailSettings] festgelegt:

SchlüsselAusgeliefertBedeutung
Transportsendmailsendmail, SMTP oder file (TransportAlias[] ordnet sie eZSendmailTransport, eZSMTPTransport, eZFileTransport zu).
TransportServer, TransportPortleer, 25Der SMTP-Server. Gesichertes SMTP läuft meist über 465 (ssl) oder 587 (tls).
TransportConnectionTypeleerleer (keine Verschlüsselung), ssl oder tls.
TransportUser, TransportPasswordleerSMTP-Anmeldung.
SenderHostlocalhostDer Name, der im SMTP-EHLO angegeben wird.
AdminEmailein PlatzhalterDie Adresse des Administrators; der Absender, wenn nichts anderes gesetzt ist. Ändern Sie sie.
EmailSender, EmailReplyToleerFrom und Reply-To, sofern ein Template sie nicht setzt.
UserAgentleerDer Header User-Agent jeder Mail (sendmail, SMTP und file), z. B. der Name des Portals; nur ASCII. Leer: Exponential, Version <version> (sendmail, file) und Apache Zeta Components (SMTP). eZMail::setUserAgent() setzt ihn weiterhin für eine einzelne Mail, auch über SMTP.
ContentType, OutputCharsettext/plain, utf-8
SendmailOptions[]leerZusätzliche Optionen für sendmail, eine pro Zeile, z. B. -f mit dem Envelope-Absender.
SendmailEnvelopeSenderenableddisabled lässt das -f <sender> weg, das der sendmail-Transport hinzufügt, für msmtp mit --read-envelope-from; eine Mail ohne eigenen Absender erhält dann einen From-Header mit EmailSender, andernfalls AdminEmail.
DebugSending, DebugReceiverEmaildisabledenabled sendet jede Mail an eine Testadresse statt an ihre Empfänger.
ExcludeHeaders[]leerHeader, die vor dem Versand über SMTP entfernt werden (fügen Sie bcc hinzu, wenn Ihr Server ihn nicht ausblendet).

Der Datei-Transport schreibt jede Mail als Datei, statt sie zu versenden: Transport=file legt sie in var/log/mail/ ab (oder im Verzeichnis aus [MailSettings] FileTransportDirectory), eine Datei <time>-<random>.mail je Nachricht. Verwenden Sie ihn auf einer Test- oder Staging-Site, um genau zu sehen, was hinausgehen würde, ohne dass jemand es erhält:

ls -lt var/log/mail/ | head

Echter Versand. Verwenden Sie im Produktivbetrieb SMTP zum Mailserver Ihrer Organisation oder zu einem Relay-Dienst:

# settings/override/site.ini.append.php
[MailSettings]
Transport=SMTP
TransportServer=smtp.example.com
TransportPort=587
TransportConnectionType=tls
TransportUser=<smtp user>
TransportPassword=<smtp password>
SenderHost=www.example.com
AdminEmail=[email protected]
EmailSender=[email protected]

Mails, die echte Postfächer erreichen sollen, brauchen eine Absenderadresse einer Domain, die Sie kontrollieren, mit SPF-Einträgen (und vorzugsweise DKIM und DMARC), die den sendenden Server zulassen, und zwar für jede Adressfamilie, über die der Server sendet: Sendet der Server über IPv6 und listet der SPF-Eintrag nur IPv4-Adressen, weisen große Anbieter die Mail zurück. Senden Sie eine Testmail, indem Sie das Passwort eines Testbenutzers ändern oder ein Formular mit einem E-Mail-Empfänger absenden, und lesen Sie das Log des Mailservers.

Einige Extensions haben eigene Transport-Einstellungen. Die der Newsletter-Extension sind in 10.5 beschrieben; das System der E-Mail-Präferenzen (Kategorien, Einwilligung, Sperrliste, das Bounce-Postfach) unter E-Mail-Präferenzen: Einrichtung und Betrieb. php bin/php/console exp:mailstatus zeigt den Zustand des Präferenzsystems.

10.5 Benachrichtigungen und Newsletter

Benachrichtigungen

Benutzer abonnieren Teilbäume; das Veröffentlichen erzeugt Ereignisse; das Skript notification.php (in frequent und als Teil notification) macht aus Ereignissen Mails und Sammelmails. Die Einstellungen stehen in settings/notification.ini.

php runcronjobs.php -s site notification --allow-root-user          # run it once by hand
php bin/php/console exp:notificationstatus                          # pending events, last runs, problems
php bin/php/console exp:notificationrun --dry-run                   # who would get what, nothing sent

Die Statusseite in der Administration und der Statusbefehl melden die üblichen Fehler: Ereignisse, die warten, ohne dass ein Lauf verzeichnet ist (Cron ist nicht eingerichtet), ein fehlgeschlagener Lauf, eine überfällige Sammelmail, der noch aktive Datei-Transport, ein fehlender Absender. Das vollständige Vorgehen mit jedem Fehler und seiner Behebung steht unter Benachrichtigungen: Betrieb und Fehlerbehebung.

Newsletter (cjw_newsletter)

Wenn die Newsletter-Extension cjw_newsletter aktiv ist, ist der Versand ein zweistufiger Job, den Cron ausführt:

TeilSkripteWas es tut
cjw_newslettercjw_newsletter_mailqueue_create.php, cjw_newsletter_mailqueue_process.phpPrüft ausstehende Abonnenten, baut die Mail-Warteschlange der fälligen Ausgaben auf und versendet sie.
cjw_newsletter_mailqueue_createcjw_newsletter_mailqueue_create.phpBaut nur die Warteschlange auf.
cjw_newsletter_mailqueue_processcjw_newsletter_mailqueue_process.phpVersendet nur, was in der Warteschlange wartet.
cjw_newsletter_mailboxcjw_newsletter_mailbox.phpHolt die Mails der Bounce-Konten ab und wertet sie aus (nicht Teil von cjw_newsletter).
*/10  *  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site cjw_newsletter >> var/log/cron-newsletter.log 2>&1
25    *  *   *   *    cd /path/to/installation && php runcronjobs.php -q -s site cjw_newsletter_mailbox >> var/log/cron-newsletter.log 2>&1

Die Extension hat eigene Transporte, in cjw_newsletter.ini [NewsletterMailSettings] (Override in settings/override/cjw_newsletter.ini.append.php):

SchlüsselAusgeliefertVerwendet für
TransportMethodCronjobfiledie Newsletter-Ausgaben, die der Cronjob versendet
TransportMethodPreviewsendmailTest-Newsletter aus dem Editor
TransportMethodDirectlyfileBestätigungen von Abonnements und Info-Mails
FileTransportMailDirvar/log/mailwohin der Datei-Transport schreibt, eine .eml-Datei je Mail
SmtpTransportServer, SmtpTransportPort, SmtpTransportUser, SmtpTransportPassword, SmtpTransportConnectionTypedie SMTP-Verbindung, wenn eine Methode smtp ist

Eine frische Installation simuliert also den Newsletter-Versand: Die Ausgaben und Bestätigungen landen als Dateien in var/log/mail/, sodass Sie Abonnement, Double-Opt-in, Versand und Abmeldung ohne Mailserver und ohne echte Empfänger testen können. Um wirklich zu versenden, setzen Sie die Methoden auf smtp (mit den Schlüsseln SmtpTransport*) oder sendmail. Das Verzeichnis muss für den Benutzer des Webservers und für den Cron-Benutzer beschreibbar sein. Zustellbarkeit, Drosselung und Bounce-Behandlung sind bei der Extension und in der Spezifikation von cjw_newsletter dokumentiert.

10.6 Caches

Exponential cacht auf vielen Ebenen, und die meisten Fragen der Art „meine Änderung erscheint nicht“ sind Cache-Fragen. Die Regel lautet: Leeren Sie den kleinsten Cache, der das Problem erklärt, und leeren Sie Caches vor PHP erst, nachdem PHP den neuen Code ausführt.

Die Caches nach Id und Tag

bin/php/ezcache.php leert nach Id (ein Cache) oder Tag (jeder Cache, der ihn trägt). Die folgende Liste ist das, was --list-ids --verbose auf einer Standardinstallation ausgibt, mit den Tags aus kernel/classes/ezcache.php und den [Cache_*]-Blöcken der Extensions:

IdWas er enthältTagsLeeren, wenn
contentder View-Cache der Inhalte (der Hauptbereich gerenderter Seiten)contentInhalte veraltet aussehen; geschieht beim Veröffentlichen automatisch
exphttpcacheder rollenbewusste HTTP-Cache (wenn httpcache.ini ihn einschaltet)content, templatenach einer Template-Änderung, sofern er eingeschaltet ist
querycacheErgebnisse von SQL-Abfragen (wenn querycache.ini ihn einschaltet)content, iniDaten außerhalb von Exponential geändert wurden
global_inider globale INI-Cacheinieine Einstellung sich geändert hat
inider INI-Cacheinieine Einstellung sich geändert hat
codepageZuordnungen von Zeichensätzencodepageselten
classidNachschlagen von Klassenbezeichnerncontentein Klassenbezeichner sich geändert hat
sortkeyNachschlagen von Sortierschlüsselncontent
urlaliasWildcard-Cache der URL-AliasecontentURL-Aliase sich falsch verhalten
chartransTabellen für Zeichentransformationen (URL-Aliase)i18nTransformationsregeln sich geändert haben
imagealiaserzeugte Bildvariantenimageeine Alias-Definition in image.ini sich geändert hat
templatekompilierte Templatestemplateeine .tpl sich geändert hat, während das Cachen der Kompilate eingeschaltet ist
template-blockAusgabe von {cache-block}template, contentMenüs oder Blöcke veraltet aussehen; ein Stylesheet sich geändert hat (der gepackte Link ist in einem solchen Block gecacht)
template-overridedie Override-Regeln aus override.initemplateeine neue Template-Datei oder Override-Regel (sonst: eine Seite mit 200 und leerem Inhaltsbereich)
texttoimageAusgabe von Text-zu-Bildtemplate
rss_cacheerzeugte Feedscontent
user_info_cacheBenutzer- und RolleninformationenuserRollen oder Richtlinien sich geändert haben und ein Benutzer es nicht sieht
content_tree_menudas Baummenü der Administration im Browsercontent
state_limitationsEinschränkungen nach Objektzustandcontent
content_languagedie Liste der Sprachencontenteine Sprache hinzugefügt wurde
design_basedie Liste der Design-Verzeichnissetemplateein Design oder eine Extension hinzugefügt wurde
active_extensionsdie Liste der aktiven ExtensionsiniActiveExtensions sich geändert hat
translationkompilierte .ts-Übersetzungeni18neine Übersetzungsdatei sich geändert hat
sslzonesEinstellungen der SSL-Zonenini
rest, rest-routesCaches der REST-Anwendung und der Routencontent, rest / restdie REST-Konfiguration sich geändert hat
ezjscore-packergepackte JavaScript- und CSS-Dateiencontent, templateein Skript oder Stylesheet des Packers sich geändert hat

Die Tags sind also content, template, ini, codepage, i18n, image, user und rest.

php bin/php/ezcache.php --list-ids --verbose --allow-root-user
php bin/php/ezcache.php --clear-tag=ini --allow-root-user
php bin/php/ezcache.php --clear-id=template-override,design_base --allow-root-user
php bin/php/ezcache.php --clear-all --allow-root-user
# remove the files for real (saves disk space), only those older than two days:
php bin/php/ezcache.php --clear-id=content --purge --expiry="-2 days" --allow-root-user

Ohne --purge verschiebt ein Leeren nur einen Ablaufzeitstempel (oder schiebt ein Verzeichnis beiseite) und ist daher sofort erledigt; der Cron-Teil cache_cleanup entfernt, was nie wieder ausgeliefert werden kann. -s <siteaccess> leert den Cache im var-Verzeichnis eines anderen Siteaccess.

Welcher Cache zu leeren ist

Sie haben geändertLeeren
eine .ini-Einstellung--clear-tag=ini (nicht --clear-id=ini, das den globalen INI-Cache auslässt)
eine .tpl-Datei--clear-tag=template: Kompilierte Templates werden nicht mit ihrer Quelle verglichen, außer bei [TemplateSettings] DevelopmentMode=enabled, das Live-Sites ausgeschaltet lassen sollten
eine neue .tpl-Datei, eine Override-Regel, eine Extension oder ein Design--clear-id=template-override,design_base
ein Stylesheet oder Skript--clear-id=ezjscore-packer,template-block, dann den Velocity-Cache
Inhalte sehen veraltet aus--clear-tag=content
Rollen und Richtlinien--clear-tag=user
eine Bild-Alias-Definition--clear-id=imagealias
eine Übersetzung--clear-tag=i18n
unsicher--clear-all (kostet danach einen langsameren ersten Aufruf jeder Seite)

Die Caches vor PHP

php bin/php/cache.php (Konsole: exp:cache) führt jede Aktion von Setup > Cache auf der Kommandozeile aus, endet mit PASS oder FAIL, akzeptiert --dry-run und --json und erreicht auch die Caches, die ezcache.php nicht erreicht:

php bin/php/cache.php list --sizes --allow-root-user     # every cache, its tag, size and how it is cleared
php bin/php/cache.php status --allow-root-user           # static, HTTP, query, Velocity, precompress, PHP caches
php bin/php/cache.php velocity clear --allow-root-user   # Velocity's response cache
php bin/php/cache.php httpcache status --allow-root-user
php bin/php/cache.php opcache status --allow-root-user

Der Antwort-Cache von Velocity beantwortet wiederholte anonyme Anfragen im Elternprozess des Servers, ohne PHP. Leeren Sie ihn nach einer Änderung an Templates oder Stylesheets (kein Neustart nötig):

php bin/php/console exp:velocity cache clear --apply --allow-root-user
php bin/php/console exp:velocity cache stats --allow-root-user

Die Reihenfolge nach einer Code-Änderung

Eine Seite, die zwischen dem Leeren eines Caches und dem Neuladen von PHP noch vom alten Code gerendert wird, wird erneut gecacht und sieht so aus, als hätte die Änderung nicht gewirkt. Die Reihenfolge lautet: INI- und Template-Caches, dann PHP-FPM neu laden und Velocity neu starten, und erst dann die Inhalts-, HTTP-, Template-Block- und Antwort-Caches. Unter Velocity erledigt das ein einziger Befehl, mit PASS oder FAIL je Schritt und einem Abbruch beim ersten Fehler:

php bin/php/console exp:velocity deploy --dry-run --allow-root-user   # what it would do
php bin/php/console exp:velocity deploy --allow-root-user             # do it
php bin/php/console exp:velocity deploy --kernel --allow-root-user    # a kernel class was added or renamed

--packer leert zusätzlich die gepackten Skripte und Styles; --no-fpm, --no-velocity und --no-autoload überspringen Schritte. Der PHP-FPM-Dienst, den der Befehl neu lädt, ist velocity.ini [DeploySettings] PhpFpmService (auto findet ihn). Siehe Velocity-Engines: eine PHP-Änderung bereitstellen.

10.7 Autoloads der Klassen

Exponential findet Klassen über generierte Autoload-Arrays in autoload/ (der Kernel) und var/autoload/ (die Extensions). Eine Klasse, die in keinem Array steht, wird nicht gefunden, selbst wenn ihre Datei vorhanden ist: „Class ... not found“ direkt nach dem Hinzufügen einer Extension oder einer Klasse ist das klassische Symptom.

php bin/php/ezpgenerateautoloads.php -e        # extensions: after adding, renaming or removing a class
php bin/php/ezpgenerateautoloads.php -k        # the kernel: only when kernel/ or lib/ changed
php bin/php/ezpgenerateautoloads.php -o        # kernel overrides
php bin/php/ezpgenerateautoloads.php -e -n     # dry run: report, write nothing
php bin/php/ezpgenerateautoloads.php -e -p     # with progress output

Das Skript hat keine root-Prüfung; es akzeptiert --allow-root-user (ohne Wirkung), damit die Option wie bei jedem anderen Skript angegeben werden kann. Eine Option, die es nicht kennt, beendet es mit Exit-Status 1, ohne etwas zu schreiben:

$ php bin/php/ezpgenerateautoloads.php -e --bogus
The referenced parameter '--bogus' is not registered.

Ältere Releases gaben bei einer unbekannten Option ihre Hilfe aus und endeten mit 0, --allow-root-user eingeschlossen, sodass ein Deployment-Skript nie bemerkte, dass nichts generiert worden war. Wenn eines Ihrer Deployment-Skripte den Generator aufgerufen und nichts geprüft hat, prüfen Sie es jetzt einmal von Hand. Führen Sie ihn als Benutzer der Site aus: Die Arrays, die er in var/autoload/ schreibt, müssen für den nächsten Lauf beschreibbar bleiben.

Welche Verzeichnisse er durchläuft, begrenzt .autoloadignore im Installationsverzeichnis, ein Verzeichnis pro Zeile, verankert am Installationsverzeichnis, # für Kommentare. Die ausgelieferte Datei schließt vendor aus (Composer löst diese Klassen selbst auf), außerdem ai, var und .claude (Arbeitskopien, die sonst jede Kernel-Klasse auf eine Kopie abbilden würden). Tragen Sie dort ein Verzeichnis ein, wenn es PHP-Dateien enthält, die keine Anwendungsklassen sind; --exclude tut dasselbe für einen einzelnen Lauf.

Leeren Sie nach dem Neugenerieren den INI-Cache und starten Sie unter Velocity die Worker neu: Sie behalten die Arrays, die sie beim Start geladen haben. exp:velocity deploy (mit --kernel für das Kernel-Array) erledigt alle drei Schritte. php bin/php/console exp:checkclasses lädt jede deklarierte Klasse und meldet die, deren Laden PHP verweigert.

10.8 Suchindex und Bildverarbeitung

Suche

Die eingebaute Engine ist eZSearchEngine (site.ini [SearchSettings] SearchEngine); sie hält ihren Index in der Datenbank. Inhalte werden beim Veröffentlichen indiziert, es sei denn, DelayedIndexing ist enabled (oder classbased mit DelayedIndexingClassList[]): Dann stellt das Veröffentlichen sie nur in eine Warteschlange, und indexcontent.php aus dem Standardteil von Cron indiziert sie später, was das Veröffentlichen großer Objekte beschleunigt.

Die Warteschlange ist die Tabelle ezpending_actions: index_object indiziert das Objekt neu, index_moved_node das Objekt und jedes Objekt unterhalb seines Hauptknotens (für eine Suchmaschine, die Pfade speichert, wie den Solr von ezfind). Jede Zeile trägt den Zeitpunkt, zu dem sie eingereiht wurde (created); der Cronjob nimmt die älteste zuerst und entfernt eine Zeile, sobald sie indiziert ist. Was ein Vorgang bei verzögerter Indizierung einreiht:

VorgangeZSearchEngine (eingebaut)Eine Engine mit addNodeAssignment() (ezfind)
Ein neues Objekt oder eine neue Version veröffentlichen (mit oder ohne Benachrichtigung, beliebig viele Orte)ein index_objectein index_object
Eine Version veröffentlichen, die einen Ort verschiebt (ein Elternknoten im Bearbeitungsformular geändert)ein index_objectein index_moved_node
Verschieben (content/move)nichts: Der Index enthält keine Pfadeindex_moved_node und index_object
Einen Ort hinzufügen, tauschennichtsindex_object
Verbergen, wieder anzeigennichtsezfind indiziert sofort und reiht eine eigene Aktion für den Teilbaum ein
In den Papierkorb verschieben, löschenentfernt die eingereihten Zeilen index_object und index_moved_node des Objektsdasselbe

Bauen Sie den ganzen Index nach einem Import, einem Datenbankumzug oder bei falschen Suchergebnissen neu auf:

php bin/php/updatesearchindex.php --clean --allow-root-user      # --clean removes the old index first

Suchstatistiken (LogSearchStats) sind standardmäßig ausgeschaltet, weil sie jeden Suchbegriff speichern, den Besucher eingeben, was personenbezogene Daten sein können. Einen Solr-Server steuert php bin/php/console exp:solr, sobald er installiert und konfiguriert ist.

Bilder

Hochgeladene Bilder liegen in var/<site var dir>/storage/images; ihre Varianten (Aliase) werden beim ersten Gebrauch erzeugt. Die Regeln stehen in settings/image.ini:

  • [AliasSettings] AliasList[] nennt die Aliase (reference, small, tiny, medium, large, rss und die Ihres Designs), jeden mit einem Block von Filtern.
  • [ImageConverterSettings] ImageConverters[] listet die Konverter der Reihe nach: GD zuerst (die eigene Erweiterung von PHP, kein externes Programm je Bild), ImageMagick als Rückfall für Formate, die GD nicht lesen kann (PSD, TIFF, PDF, WebP), und für Filter, die nur es hat. [ImageMagick] ExecutablePath und Executable (convert) finden das Programm; prüfen Sie mit convert -version.
  • [OutputSettings] AllowedOutputFormat[] (JPEG, PNG, WebP, GIF) listet die Formate, die Seiten anzeigen dürfen.
  • [ImageConverterSettings] LockTimeout (ausgeliefert 60): Sekunden, die ein Prozess wartet, während ein anderer denselben Alias erzeugt; danach beendet der wartende Prozess den anderen und erzeugt den Alias selbst.

Entfernen Sie nach der Änderung einer Alias-Definition die erzeugten Varianten, damit sie neu erstellt werden:

php bin/php/cache.php imagealias clear --allow-root-user

10.9 Sicherung und Wiederherstellung

Eine Sicherung besteht aus der Datenbank und den Dateien, im selben Moment erstellt. Dateien, auf die es ankommt:

PfadWarum
var/storage und var/<site>/storagehochgeladene Bilder und Dateien
settings/override, settings/siteaccessdie Einstellungen der Installation (sie enthalten Passwörter: Halten Sie die Sicherung vertraulich)
Ihre eigenen Extensions und Designsfalls sie nicht in einem Repository liegen
var/storage/sqlite3/die Datenbank, bei SQLite (separat gesichert, siehe unten)
var/logoptional, für spätere Untersuchungen

Caches (var/cache, var/<site>/cache) brauchen keine Sicherung: Sie werden neu erzeugt.

Vorgehen

  1. Versetzen Sie die Site in den Wartungsmodus, damit zwischen der Sicherung der Datenbank und der der Dateien nichts geschrieben wird. Besucher erhalten eine 503-Seite; --allow-admin hält die Administration erreichbar, --allow-ip lässt angegebene Adressen durch:

    php bin/php/maintenance.php on --message="Back soon" --until=30m --allow-root-user
    php bin/php/maintenance.php status --allow-root-user
  2. Sichern Sie die Datenbank mit dem Werkzeug ihrer Engine:

    EngineSicherungWiederherstellung
    SQLitesqlite3 var/storage/sqlite3/exponential.db ".backup '/backup/db.sqlite'"sqlite3 var/storage/sqlite3/exponential.db ".restore '/backup/db.sqlite'"
    MySQL, MariaDBmysqldump --single-transaction -u USER -p DATABASE > /backup/db.sqlmysql -u USER -p DATABASE < /backup/db.sql
    PostgreSQLpg_dump -U USER -Fc DATABASE > /backup/db.dumppg_restore -U USER -d DATABASE --clean /backup/db.dump
    MongoDBmongodump --uri="mongodb://USER@HOST/DATABASE" --out=/backup/mongomongorestore --uri="..." --drop /backup/mongo
    Oraclephp bin/php/console ext:ezoracle:datapump --export=db.dmp (oder expdp)ext:ezoracle:datapump --import=db.dmp

    -p lässt den Client nach dem Passwort fragen; schreiben Sie es nie in die Kommandozeile. Lesen Sie für SQLite die Einzelheiten in Kapitel 9: Die Online-Sicherung ist sicher, während die Site läuft, eine einfache Kopie einer viel benutzten Datei nicht.

  3. Sichern Sie die Dateien:

    tar czf /backup/files-$(date +%F).tar.gz var/storage settings/override settings/siteaccess

    (fügen Sie var/<site>/storage hinzu, wenn das var-Verzeichnis der Site separat ist, sowie Ihre eigenen Extensions).

  4. Schalten Sie die Wartung aus: php bin/php/maintenance.php off --allow-root-user.

Bewahren Sie Sicherungen außerhalb des Servers auf und behalten Sie mehrere Generationen. Bei SQLite und bei MySQL mit InnoDB ist die Datenbanksicherung auch ohne Wartungsmodus konsistent; der Wartungsmodus sorgt dafür, dass Datenbank und Dateien zueinander passen.

Wiederherstellung

  1. Wartung ein. Unter Velocity halten Sie außerdem den Server an (php bin/php/console exp:velocity stop --allow-root-user), damit kein Worker die alte Datenbank festhält.

  2. Stellen Sie die Datenbank wieder her (Tabelle oben) und entpacken Sie die Dateien über die Installation; korrigieren Sie Eigentümer und Modus (Kapitel 8).

  3. Leeren Sie jeden Cache und generieren Sie die Autoloads neu:

    php bin/php/ezcache.php --clear-all --allow-root-user
    php bin/php/ezpgenerateautoloads.php -e
  4. Starten Sie Velocity, leeren Sie seinen Antwort-Cache, schalten Sie die Wartung aus und öffnen Sie die Startseite und die Administration.

Testen Sie eine Wiederherstellung mindestens einmal auf einem anderen Rechner und nach jedem größeren Upgrade: Eine Sicherung, die nie wiederhergestellt wurde, ist eine Hoffnung, keine Sicherung. Siehe Wartungsmodus und Eine Site betreiben, Teil 6.

Wartungsfenster

Nehmen Sie für ein Upgrade, einen Import oder eine Wiederherstellung die öffentliche Site unter Setup > Wartung vom Netz (Meldung, voraussichtliche Dauer, wer weiterhin Zugang hat, eine Vorschau und eine Bestätigung) oder mit php bin/php/maintenance.php on|off|status. Besucher erhalten eine 503-Wartungsseite, die Administration unter /admin bleibt erreichbar, und das Löschen von var/maintenance.json beendet den Wartungsmodus, was auch immer sonst nicht stimmt. Die vollständige Anleitung: Wartungsmodus.

10.10 Logs und Log-Rotation

Datei (unter var/log/, sofern nicht anders angegeben)Geschrieben vonLesen Sie sie für
error.logdem Kernel, immer (site.ini [DebugSettings] AlwaysLog[]=error)Fehler: die erste Anlaufstelle
warning.log, notice.log, debug.log, strict.logdem Kernel, wenn eingeschaltetUntersuchungen
setup.log, kickstart.log, exp-install-<date>.iniden Installern: ein Eintrag je Installationslauf (setup.log), die vollständige Ausgabe jedes exp:kickstarter-Laufs (kickstart.log, frühere Läufe in .1 bis .9), die Konfiguration, die exp:install verwendet hat; Passwörter sind in allen dreien maskiertInstallationsprobleme
mail/den Datei-Transportendie Mails, die hinausgegangen wären
oracle-slow.logezoracle, mit SlowQueryThresholdlangsame Oracle-Anweisungen
cron-*.logIhren Umleitungen in der CrontabCron-Ausgaben
<site var dir>/log/cronjobs/output.log, error.logJobs, die unter Setup > Cronjobs gestartet wurden (cronjob.ini [AdminSettings] LogFile, ErrorFile)im Browser gestartete Jobs
Die Logs von Velocitydem Server (velocity.ini [LogSettings])den Anwendungsserver
das Audit-Protokollaudit.php; lesen mit php bin/php/audit.phpwer was getan hat
tail -n 50 var/log/error.log
php bin/php/audit.php status --allow-root-user
php bin/php/audit.php tail --channel=access --lines=20 --allow-root-user

Eingebaute Rotation. Der Kernel rotiert seine eigenen Logs: Wenn eine Datei 200 KB überschreitet, wird sie zu .1, die älteren rücken auf, und drei werden behalten (error.log.1 bis error.log.3). Ändern Sie die Grenzen in config.php, der PHP-Konfigurationsdatei der Installation (config.php-RECOMMENDED listet sie auf):

define( 'EZPUBLISH_LOG_MAX_FILE_SIZE', 10485760 );   // 10 MB per file
define( 'EZPUBLISH_LOG_ROTATE_FILES', 10 );          // keep ten; 0 switches built-in rotation off
define( 'CUSTOM_LOG_MAX_FILE_SIZE', 10485760 );       // logs written through eZLog
define( 'CUSTOM_LOG_ROTATE_FILES', 10 );

Ohne Editor schreibt die Konsole dieselben Zeilen (vorher eine Sicherung von config.php, eine Prüfung mit php -l, bevor die Datei ersetzt wird); ./console exp:setup:config --apply legt config.php aus der Vorlage an, wenn es noch keine gibt:

./console exp:config:set EZPUBLISH_LOG_MAX_FILE_SIZE 10485760 --apply
./console exp:config:set EZPUBLISH_LOG_ROTATE_FILES 10 --apply
./console exp:config:list --only-set

Siehe .htaccess und config.php von der Konsole aus einrichten.

System-Rotation. Dateien, die der Kernel nicht selbst schreibt (Ihre Dateien cron-*.log), brauchen logrotate des Systems. Wenn Sie die eingebaute Rotation ausschalten, übernimmt logrotate auch die Logs des Kernels:

# /etc/logrotate.d/exponential
/path/to/installation/var/log/cron-*.log {
    weekly
    rotate 8
    compress
    missingok
    notifempty
    copytruncate
    su <site user> <site group>
}

copytruncate, weil die schreibenden Prozesse die Datei offen halten. Lassen Sie [DebugSettings] DebugOutput=enabled im Produktivbetrieb nie eingeschaltet: Es zeigt Besuchern Interna und schreibt sehr viel.

10.11 Überwachung und Zustandsprüfungen

Es gibt keine einzelne Health-URL; kombinieren Sie eine Prüfung von außen mit den Statusbefehlen im Inneren. Jeder der folgenden Befehle endet mit einem erkennbaren Status, und die meisten bieten --json für ein Überwachungssystem.

PrüfungBefehlGesund
Die Site antwortetcurl -s -o /dev/null -w '%{http_code} %{time_total}\n' https://www.example.com/200 und eine Zeit, die Sie kennen
Die Administration antwortetcurl -s -o /dev/null -w '%{http_code}\n' https://www.example.com/admin/user/login200
Die Cachesphp bin/php/cache.php status --json --allow-root-userendet mit PASS
Velocityphp bin/php/console exp:velocity status --json --allow-root-userläuft, Worker wie konfiguriert
Benachrichtigungenphp bin/php/console exp:notificationstatuskeine Ereignisse, die ohne einen kürzlichen Lauf warten
Das Audit-Protokollphp bin/php/audit.php verify --allow-root-userExit-Status 0 (die Kette jedes Kanals intakt; 1 bedeutet gebrochen)
Neue Fehlertail -n 100 var/log/error.lognichts, was Sie nicht erklären können
Cronphp bin/php/console crontab:list und die Daten der cron-*.logEinträge vorhanden, Logs aktuell
Festplattedf -h /path/to/installationPlatz für Caches, Logs und eine Sicherung
Die Datenbankje nach Engine; SQLite: Kapitel 9; Oracle: ext:ezoracle:health
Performancephp bin/php/console exp:benchmark --baseline=var/benchmark/base.jsonExit-Status 0 (keine Regression)

Ein kleines Skript in der Crontab des Benutzers der Site, das diese Prüfungen ausführt und bei einem Exit-Status ungleich null eine Mail schickt, genügt für einen einzelnen Server. In der Administration zeigt Setup > Systeminformationen Versionen, PHP und die Server-Engine.

10.12 Performance-Tuning

Messen Sie vor und nach jeder Änderung. exp:benchmark fragt die Startseite, die ersten Menüseiten, die Suchseite (wenn Besucher suchen dürfen) und die Admin-Anmeldeseite ab, immer in dieser Reihenfolge, jeweils 100-mal nach 5 Aufwärmanfragen, 4 gleichzeitig, und gibt Median, p90, p99, Minimum, Maximum und Standardabweichung aus; der Modus kernel misst die Bestandteile einer Seite im Prozess (Bootvorgang, Rendern kalt und warm, Laden der INI, Abrufen von Inhalten, Datenbank-Roundtrip, Schreiben und Lesen des Caches), und der Modus micro misst reine PHP-Hot-Paths ohne HTTP oder Datenbank:

php bin/php/console exp:benchmark --save=var/benchmark/base.json --allow-root-user
# ... make a change ...
php bin/php/console exp:benchmark --baseline=var/benchmark/base.json --threshold=15 --allow-root-user
php bin/php/console exp:benchmark --runs=200 --warmup=10 --format=json --allow-root-user > var/benchmark/run.json
php bin/php/console exp:benchmark kernel --repeat=30 --allow-root-user
php bin/php/console exp:benchmark micro --allow-root-user                 # no web server, no database
php bin/php/console exp:benchmark --compare=https://www.example.com,https://www.example.com:8443 --allow-root-user
php bin/php/console exp:benchmark --cold --requests=50 --allow-root-user   # past the response caches

Jeder Lauf zeichnet seine Umgebung auf (PHP, OPcache und JIT, Xdebug, CPUs, Last, den Commit, das Datum), und ein Vergleich mit einer Baseline, die unter einem anderen Aufbau entstanden ist, weist darauf hin. Für vergleichbare Zahlen gilt: derselbe Rechner, nichts anderes läuft, OPcache wie im Produktivbetrieb, Xdebug aus, und beurteilen Sie zwei Server nur anhand von Läufen, die direkt nacheinander gemacht wurden. Die CI des Repositorys führt den Modus micro gegen tests/benchmark/baseline.json als Prüfung aus, die nur warnt.

Standardmäßig ist es rücksichtsvoll: Gegen einen anderen Host als diesen Rechner brauchen mehr als 1000 Anfragen je URL oder mehr als 16 gleichzeitig --force. Die Anleitung Benchmarking von Exponential lehrt jeden Einsatz mit echten Ausgaben: Median, p90 und p99 lesen, Läufe fair vergleichen, die Checkliste gegen Messrauschen, Arbeitsabläufe für eine Code-Änderung, Apache gegen Velocity und ein Deployment sowie die CI-Prüfung; Benchmark: exp:benchmark ist die Referenz.

Die Hebel, nach Wirkung geordnet

  1. Mit Velocity ausliefern, samt seinem Antwort-Cache (Kapitel 8). Eine gecachte anonyme Seite wird ohne PHP beantwortet; persistente Worker (ForkPerRequest=disabled) halten die Anwendung, die Datenbankverbindung und die kompilierten Dateien warm.
  2. View-Cache der Inhalte und Template-Block-Cache eingeschaltet lassen ([ContentSettings] ViewCaching=enabled, [TemplateSettings] TemplateCache=enabled, beide ausgeliefert). Wärmen Sie die Site nach einem Leeren auf: php bin/php/warm.php --allow-root-user ruft jede veröffentlichte Seite ab.
  3. OPcache (nächster Teil).
  4. APCu für die Speicherstufe des Antwort-Caches von Velocity und den SQL-Abfrage-Cache im Modus shared: velocity.ini [PHPSettings] IniOptions[]=apc.shm_size=256M ist ausgeliefert; ist er zu klein, verdrängen sich die beiden gegenseitig.
  5. Der SQL-Abfrage-Cache (querycache.ini [QueryCacheSettings] Mode=request oder shared), gemessen auf Ihrer Site (SQL-Abfrage-Cache).
  6. Die Datenbank: Kapitel 9 (SQLite ANALYZE, persistente Verbindungen und DRCP bei Oracle).

Lassen Sie den statischen Cache aus. [ContentSettings] StaticCache=disabled ist der ausgelieferte Wert, und der Installer schreibt ihn so. Mit eingeschaltetem statischem Cache erzeugte jedes Veröffentlichen jede betroffene Seite auf jedem öffentlichen Siteaccess über HTTP innerhalb der Anfrage des Redakteurs neu, sodass ein Veröffentlichen, das nichts änderte, Sekunden statt eines Bruchteils davon dauerte. Der Antwort-Cache von Velocity bietet Besuchern denselben Vorteil ohne diese Kosten.

OPcache

Unter PHP-FPM schalten Sie OPcache in der php.ini des Pools ein (OPcache-Konfiguration):

opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.interned_strings_buffer=32
; keep timestamp checks on: Exponential rewrites PHP cache files (INI caches,
; compiled templates, expiry.php) under the same name
opcache.validate_timestamps=1
opcache.revalidate_freq=2

Setzen Sie auf einer Exponential-Site niemals opcache.validate_timestamps=0: Eine nach einem Leeren neu geschriebene Cache-Datei würde in ihrer alten Form ausgeliefert, bis PHP neu startet.

Unter Velocity übergibt der Server seine eigenen PHP-Optionen (settings/velocity.ini [PHPSettings] IniOptions[]), und zwei davon weichen aus einem Grund von PHP-FPM ab, den zu verstehen sich lohnt. OPcache vergleicht die Zeit einer Datei mit der Startzeit der Anfrage, und ein Velocity-Worker ist eine einzige lange Anfrage, die mit dem Worker begann:

  • opcache.revalidate_freq=0: Mit der Voreinstellung 2 prüfte ein Worker eine Datei nie wieder, sodass eine neu geschriebene Cache-Datei so ausgeliefert wurde, wie sie war, als der Worker sie zum ersten Mal kompilierte.
  • opcache.file_update_protection=0: OPcache behält kein Skript, das weniger als so viele Sekunden vor dem Start der Anfrage geändert wurde. Für einen Worker galt jede nach seinem Start geschriebene Datei (INI-Caches, Override-Caches, kompilierte Templates, alle nach einem Deployment oder Leeren neu erzeugt) während seiner gesamten Lebensdauer als „zu neu“ und wurde bei jedem Include erneut kompiliert: Der Cache bediente nur wenige Prozent der Includes, und ein Rendern brauchte etwa viermal so viel CPU wie unter PHP-FPM. Der Schutz ist nicht nötig, weil der Server Includes vollständig liest und die gecachte Kopie einer in den letzten zwei Sekunden geänderten Datei selbst verwirft.

Die ausgelieferte velocity.ini setzt beide, zusammen mit opcache.enable_cli=1 (das Kommandozeilen-PHP, das den Server ausführt, hat OPcache womöglich systemweit ausgeschaltet), memory_consumption=256, max_accelerated_files=20000 und interned_strings_buffer=32. Prüfen Sie mit php bin/php/cache.php opcache status --allow-root-user; wie Sie es profilieren, lesen Sie unter Velocity und der Opcode-Cache. Jede PHP-Einstellung, die mit „der Anfragezeit“ vergleicht, verhält sich in einem Velocity-Worker wie eingefroren; verdächtigen Sie das zuerst, wenn etwas unter PHP-FPM funktioniert und unter Velocity nicht.

10.13 Verwaltung von Extensions

Extensions liegen in extension/<name>/ (weitere Wurzelverzeichnisse mit site.ini [ExtensionSettings] AdditionalExtensionDirectories[]). Die meisten kommen über Composer (composer.json); einige werden hineinkopiert.

Aktivieren. Eine Extension tut nichts, bis sie aktiv ist:

# settings/override/site.ini.append.php
[ExtensionSettings]
ActiveExtensions[]=myextension

ActiveAccessExtensions[] in der site.ini.append.php eines Siteaccess aktiviert eine Extension nur für diesen Siteaccess (geladen, nachdem der Siteaccess bestimmt ist). Die Administration tut dasselbe unter Setup > Extensions. Nach dem Aktivieren:

php bin/php/ezpgenerateautoloads.php -e
php bin/php/ezcache.php --clear-tag=ini --allow-root-user
php bin/php/ezcache.php --clear-id=template-override,design_base,active_extensions --allow-root-user

und starten Sie Velocity neu (oder führen Sie exp:velocity deploy aus). Bringt die Extension Datenbanktabellen mit, installieren Sie sie so, wie es ihre Dokumentation beschreibt (oft share/db_schema.dba mit bin/php/ezsqlinsertschema.php).

Reihenfolge. Wenn zwei Extensions dieselbe Einstellung, dasselbe Template oder dieselbe Design-Datei bereitstellen, gewinnt die frühere in ActiveExtensions[]: Das Einstellungsverzeichnis jeder Extension wird der Reihe nach vorangestellt, sodass eine spätere Extension am Ende eine niedrigere Priorität hat. settings/override/ gewinnt immer gegen jede Extension. Die Einstellungen eines Siteaccess gewinnen gegen die Vorgaben und gegen die Extensions in seinem ActiveAccessExtensions[], aber nicht gegen die in ActiveExtensions[], die nach ihm gelesen werden (Konfigurieren, Abschnitt 2). [ExtensionSettings] ExtensionOrdering=enabled (ausgeliefert) sortiert Extensions zusätzlich nach den Abhängigkeiten, die sie in extension.xml deklarieren, was nicht jeden Fall lösen kann (es ordnet nicht über ActiveExtensions und ActiveAccessExtensions hinweg um). Daher:

  • Eine Site- oder Theme-Extension, die eine andere überschreiben soll, steht vor ihr;
  • eine Extension, die nur Einstellungen zu einer Extension ergänzt, die eine vollständige Datei mitbringt (zum Beispiel Verbindungseinstellungen für ezoracle), steht vor dieser Extension;
  • ändern Sie die Reihenfolge unter Setup > Extensions, Karte Ladereihenfolge, die nur ActiveExtensions speichert und eine Sicherungskopie anlegt (Ladereihenfolge der Extensions).

Prüfen Sie nach jeder Änderung der Reihenfolge den wirksamen Wert einer Einstellung mit php bin/php/console exp:ini get <file>/<Block>/<Key> --allow-root-user. Die installierten Versionen, Lizenzen und Websites stehen auf der About-Seite (/ezinfo/about), die die im aktuellen Siteaccess aktiven Extensions und die auf der Festplatte vorhandenen zählt (zum Beispiel „63 aktiv in diesem Siteaccess, 85 auf der Festplatte“), dieselben Zahlen wie das Dashboard. Eigene Extensions erstellen und veröffentlichen: Extensions.

Die Job-Warteschlange und Exponential Intelligence. expqueue und expai liegen nach composer install auf der Festplatte und sind inaktiv, bis Sie sie einschalten:

  1. ActiveExtensions[]=expqueue in settings/override/site.ini.append.php (die Warteschlange muss überall aktiv sein, wo Jobs eingereiht und ausgeführt werden), dann ./console ext:expqueue:install-schema.
  2. ActiveAccessExtensions[]=expai in der site.ini.append.php jedes Admin-Siteaccess (oder ActiveExtensions[]=expai für alle), dann php extension/expai/bin/php/expaischema.php --install -s <admin siteaccess>.
  3. Der Schlüssel des Anbieters in settings/override/expai.ini.append.php (Modus 0640, nie committet): [AISettings] Enabled=true und ApiKey=..., oder ein lokales Modell (lokale Modelle).
  4. Autoloads, Caches und exp:velocity deploy --packer wie oben; die Richtlinie expai/write für Redakteure.
  5. Cron, beide mit dem Admin-Siteaccess, wenn expai nur dort aktiv ist: * * * * * ... php runcronjobs.php -q -s <admin siteaccess> expqueue und */5 * * * * ... php runcronjobs.php -q -s <admin siteaccess> expai.

Einzelheiten: Exponential Intelligence, die Job-Warteschlange.

10.14 Mehrsprachige Sites

Inhaltssprachen und Sprachen der Oberfläche sind getrennt:

  • Inhaltssprachen sind die Sprachen, in die Objekte übersetzt werden (die Anleitung). Fügen Sie eine in der Administration unter Setup > Sprachen hinzu (die View content/translations); danach können Redakteure Objekte in diese Sprache übersetzen.
  • Die Sprache der Oberfläche eines Siteaccess ist site.ini [RegionalSettings] Locale (ausgeliefert eng-GB); ein Administrator kann in den Benutzereinstellungen seine eigene wählen.

Je Siteaccess entscheidet [RegionalSettings], was ein Besucher sieht:

# settings/siteaccess/site_de/site.ini.append.php
[RegionalSettings]
Locale=ger-DE
ContentObjectLocale=ger-DE
# the languages shown, in order of preference; the first that exists is used
SiteLanguageList[]
SiteLanguageList[]=ger-DE
SiteLanguageList[]=eng-GB
# disabled: objects in none of these languages are not shown
ShowUntranslatedObjects=disabled
TextTranslation=enabled

Eine typische mehrsprachige Site hat einen öffentlichen Siteaccess je Sprache (site_en, site_de), zugeordnet über ein URL-Element oder einen Hostnamen (10.2), und führt sie alle in RelatedSiteAccessList[] auf, weil sie sich eine Datenbank teilen. Ändern Sie ContentObjectLocale einer bestehenden Site nicht leichtfertig: Objekte, die in der neuen Standardsprache nicht existieren, verschwinden aus Auflistungen. Geben Sie bei der Installation jede Sprache in --languages= an (oder in Languages[] in kickstart.ini): Ein Site-Paket, dessen Inhalte ein nicht installiertes Locale verwenden, zeigt Seiten ohne Bilder oder Unterelemente.

Übersetzungen der Oberfläche: php bin/php/ezchecktranslation.php ger-DE --allow-root-user meldet, wie vollständig eine ist, und nach einer Änderung an einer .ts-Datei leeren Sie --clear-tag=i18n. Siehe Übersetzungen und Sprachen.

10.15 Eine Checkliste für die erste Woche

  1. Das Administratorpasswort ist geändert, var/log/initial-admin-password ist entfernt, die E-Mail-Adresse des Administrators ist echt.
  2. AdminEmail und der Mail-Transport sind gesetzt; eine Mail zur Passwortänderung ist in einem echten Postfach angekommen.
  3. Die Crontab führt frequent, den Standardteil, infrequent und cache_cleanup aus; die Logs wachsen.
  4. php bin/php/cache.php status --allow-root-user endet mit PASS.
  5. Eine Sicherung wurde erstellt und auf einem anderen Rechner wiederhergestellt.
  6. var/log/error.log enthält nichts, was Sie nicht erklären können.
  7. Eine Benchmark-Baseline ist in var/benchmark/ gespeichert.
  8. Die Logs rotieren (eingebaute Grenzen in config.php, siehe ./console exp:config:list --only-set; logrotate für Cron-Logs).
  9. Hinter einem Proxy auf einem anderen Rechner: Seine Adresse steht in TrustedProxies[], und HTTPS-Seiten verlinken auf https://.

10.16 Wenn etwas nicht funktioniert

Die Fehler, die in den ersten Wochen am häufigsten auftreten, mit dem Teil dieses Kapitels, der sie erklärt. Die vollständige Liste steht in Kapitel 12.

SymptomWahrscheinliche UrsacheSiehe
Geplante Inhalte erscheinen nie, Benachrichtigungen kommen nie andie Crontab fehlt oder läuft als anderer Benutzer oder mit einem anderen PHP10.3
Es kommt keine Mail an, und im Log des Mailservers steht nichtsTransport=file: Die Mail liegt in var/log/mail/10.4
Große Anbieter weisen Mails zurückdie Domain des Absenders hat keinen SPF-Eintrag für diesen Server, oder der Server sendet über IPv6 und SPF listet nur IPv410.4
Eine geänderte Einstellung wirkt nichtder INI-Cache, oder Velocity-Worker, die noch die alten Einstellungen halten10.6
„Class ... not found“ nach dem Hinzufügen einer Extensiondas Autoload-Array der Extensions wurde nicht neu generiert10.7
Eine neue Template-Datei ergibt eine Seite mit leerem Inhaltsbereichder Template-Override-Cache10.6
Links auf einer HTTPS-Site zeigen auf http://der vorgeschaltete Proxy steht nicht in TrustedProxies[]10.2
Eine Änderung wirkt für einige Neuladevorgänge, dann kehrt die alte Seite zurückein Cache vor PHP wurde geleert, bevor PHP den neuen Code ausführte10.6, „Die Reihenfolge nach einer Code-Änderung“
Fehler über Dateien, die nach Wartungsarbeiten nicht geschrieben werden könnenein Skript lief als root und hat Dateien in var/ hinterlassen, die root gehörenKapitel 12

Bei einer öffentlichen Demo (Umgebungsvariable EXP_DEMO_MODE=1) gelten die obigen Schritte zur Änderung des Administratorpassworts nicht: Das veröffentlichte Passwort soll bestehen bleiben und kann im Demo-Modus weder geändert noch zurückgesetzt werden. Prüfen Sie stattdessen, dass das Banner Demo-Modus in der Administration erscheint und dass var/log/security.log Zeilen mit demo/mode für den Webserver und für Cron enthält (Demo-Modus, Probleme mit dem Demo-Modus).

Referenzen

In diesem Repository:

Extern:

Inhalt · Zurück: 9. Datenbanken · Weiter: 11. Upgrade

Werden Sie Exponential-Partner

Partner teilen ihre Informationen, stellen Mittel bereit, geben Beiträge zurück und entwickeln die Produkte mit uns, und so wächst Exponential. Eine Partner-Website und ein Dashboard sind für Mitte 2027 geplant: Werden Sie noch heute Partner, damit wir schneller wachsen und neue Funktionen früher liefern.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x