One place for hosting & domains

      So indizieren, teilen und bearbeiten Sie Zeichenfolgen in JavaScript


      Einführung

      Eine Zeichenfolge ist eine Sequenz von einem oder mehreren Zeichen, die aus Buchstaben, Zahlen oder Symbolen bestehen kann. Auf jedes Zeichen in einer JavaScript-Zeichenfolge kann über eine Indexnummer zugegriffen werden, und allen Zeichenfolgen stehen Methoden und Eigenschaften zur Verfügung.

      In diesem Tutorial lernen wir den Unterschied zwischen Zeichenfolgenprimitiven und dem Zeichenfolgenobjekt kennen, wie Zeichenfolgen indiziert werden, wie auf Zeichen in einer Zeichenfolge zugegriffen wird und welche allgemeinen Eigenschaften und Methoden für Zeichenfolgen verwendet werden.

      Zeichenfolgenprimitive und Zeichenfolgenobjekte

      Zuerst werden wir die beiden Arten von Zeichenfolgen klären. JavaScript unterscheidet zwischen der Zeichenfolgenprimitive, einem unveränderlichen Datentyp und dem Zeichenfolgenobjekt.

      Um den Unterschied zwischen den beiden zu testen, initialisieren wir eine Zeichenfolgenprimitive und ein Zeichenfolgenobjekt.

      // Initializing a new string primitive
      const stringPrimitive="A new string."
      
      // Initializing a new String object
      const stringObject = new String('A new string.')
      

      Wir können den Operator typeof verwenden, um den Typ eines Werts zu bestimmen. Im ersten Beispiel haben wir einer Variable einfach eine Zeichenfolge zugewiesen.

      typeof stringPrimitive
      

      Output

      string

      Im zweiten Beispiel haben wir eine neue Zeichenfolge() verwendet, um ein Zeichenfolgenobjekt zu erstellen und einer Variable zuzuweisen.

      typeof stringObject
      

      Output

      object

      Meistens erstellen Sie Zeichenfolgenprimitive. JavaScript kann auf die integrierten Eigenschaften und Methoden des Zeichenfolgen“objekt-Wrappers zugreifen und diese verwenden, ohne die von Ihnen erstellte Zeichenfolgenprimitive tatsächlich in ein Objekt zu ändern.

      Während dieses Konzepts zunächst etwas anspruchsvoll ist, sollten Sie sich der Unterscheidung zwischen Primitive und Objekt bewusst sein. Im Wesentlichen stehen allen Zeichenfolgen Methoden und Eigenschaften zur Verfügung. Im Hintergrund führt JavaScript bei jedem Aufruf einer Methode oder Eigenschaft eine Konvertierung in ein Objekt und zurück in eine Primitive durch.

      Wie Zeichenfolgen indiziert sind

      Jedes der Zeichen in einer Zeichenfolge entspricht einer Indexnummer, beginnend mit 0.

      Zur Demonstration erstellen wir eine Zeichenfolge mit dem Wert How are you?.

      Howareyou?
      01234567891011

      Das erste Zeichen in der Zeichenfolge ist H, was dem Index 0 entspricht. Das letzte Zeichen ist ?, was 11 entspricht. Die Leerzeichen haben auch einen Index bei 3 und 7.

      Wenn wir auf jedes Zeichen in einer Zeichenfolge zugreifen können, haben wir verschiedene Möglichkeiten, mit Zeichenfolgen zu arbeiten und diese zu bearbeiten.

      Zugriff auf Zeichen

      Wir zeigen Ihnen, wie Sie auf Zeichen und Indizes mit der Zeichenfolge How are you? zugreifen können.

      'How are you?'
      
      

      Mit der quadratischen Klammernotation können wir auf jedes Zeichen in der Zeichenfolge zugreifen.

      'How are you?'[5]
      

      Output

      r

      Wir können auch die charAt()-Methode verwenden, um das Zeichen mit der Indexnummer als Parameter zurückzugeben.

      'How are you?'.charAt(5)
      

      Output

      r

      Alternativ können wir indexOf() verwenden, um die Indexnummer durch die erste Instanz eines Zeichens zurückzugeben.

      'How are you?'.indexOf('o')
      

      Output

      1

      Obwohl „o“ zweimal in der Zeichenfolge How are you? erscheint, erhält indexOf() die erste Instanz.

      lastIndexOf() wird verwendet, um die letzte Instanz zu finden.

      'How are you?'.lastIndexOf('o')
      

      Output

      9

      Für beide Methoden können Sie auch nach mehreren Zeichen in der Zeichenfolge suchen. Sie gibt die Indexnummer des ersten Zeichens in der Instanz zurück.

      'How are you?'.indexOf('are')
      

      Output

      4

      Die slice()-Methode hingegen gibt die Zeichen zwischen zwei Indexnummern zurück. Der erste Parameter ist die Startindexnummer und der zweite Parameter ist die Indexnummer, an der sie enden soll.

      'How are you?'.slice(8, 11)
      

      Output

      you

      Beachten Sie, dass 11 ? ist, aber ? ist nicht Teil der zurückgegebenen Ausgabe. slice() gibt zurück, was zwischen dem letzten Parameter liegt, schließt ihn jedoch nicht ein.

      Wenn ein zweiter Parameter nicht enthalten ist, gibt slice() alles vom Parameter bis zum Ende der Zeichenfolge zurück.

      'How are you?'.slice(8)
      

      Output

      you?

      Zusammenfassend helfen charAt() und slice() dabei, Zeichenfolgenwerte basierend auf Indexnummern zurückzugeben, und indexOf() und lastIndexOf() machen das Gegenteil und geben Indexnummern basierend auf den angegebenen Zeichenfolgen zurück.

      Die Länge einer Zeichenfolge finden

      Mit der Eigenschaft length können wir die Anzahl der Zeichen in einer Zeichenfolge zurückgeben.

      'How are you?'.length
      

      Output

      12

      Denken Sie daran, dass die Eigenschaft length die tatsächliche Anzahl von Zeichen zurückgibt, die mit 1 beginnen, was 12 ergibt, und nicht die endgültige Indexnummer, die bei 0 beginnt und bei 11 endet.

      Konvertieren in Groß- oder Kleinschreibung

      Die beiden integrierten Methoden toUpperCase() und toLowerCase() sind hilfreiche Möglichkeiten, um Text zu formatieren und Textvergleiche in JavaScript zu erstellen.

      toUpperCase() konvertiert alle Zeichen in Großbuchstaben.

      'How are you?'.toUpperCase()
      

      Output

      HOW ARE YOU?

      toLowerCase() konvertiert alle Zeichen in Kleinbuchstaben.

      'How are you?'.toLowerCase()
      

      Output

      how are you?

      Diese beiden Formatierungsmethoden nehmen keine zusätzlichen Parameter.

      Es lohnt sich, zu beachten, dass diese Methoden die ursprüngliche Zeichenfolge nicht ändern.

      Zeichenfolgen teilen

      JavaScript bietet eine sehr nützliche Methode, um eine Zeichenfolge durch ein Zeichen zu teilen und aus den Abschnitten eine neue Anordnung zu erstellen. Wir verwenden die split()-Methode, um die Anordnung durch ein Leerzeichen zu trennen, das durch „“ dargestellt ist.

      const originalString = 'How are you?'
      
      // Split string by whitespace character
      const splitString = originalString.split(' ')
      
      console.log(splitString)
      

      Output

      [ 'How', 'are', 'you?' ]

      Nachdem wir eine neue Anordnung in der splitString-Variablen haben, können wir auf jeden Abschnitt mit einer Indexnummer zugreifen.

      splitString[1]
      

      Output

      are

      Wenn ein leerer Parameter angegeben ist, erstellt split() eine durch Komma getrennte Anordnung mit jedem Zeichen in der Zeichenfolge.

      Durch die Trennung von Zeichenfolgen können Sie bestimmen, wie viele Wörter sich in einer Satz befinden und die Methode als Möglichkeit verwenden, um beispielsweise die Vornamen und die Nachnamen von Leuten zu bestimmen.

      Leerzeichen kürzen

      Die JavaScript-Methode trim() entfernt Leerzeichen an beiden Enden einer Zeichenfolge, jedoch nicht irgendwo dazwischen. Leerzeichen können Tabulatoren oder Leerzeichen sein.

      const tooMuchWhitespace="     How are you?     "
      
      const trimmed = tooMuchWhitespace.trim()
      
      console.log(trimmed)
      

      Output

      How are you?

      Die trim()-Methode ist eine einfache Möglichkeit, die gemeinsame Aufgabe auszuführen, um überschüssige Leerzeichen zu entfernen.

      Zeichenfolgenwerte suchen und ersetzen

      Wir können eine Zeichenfolge nach einem Wert durchsuchen und ihn mithilfe der replace() -Methode durch einen neuen Wert ersetzen. Der erste Parameter ist der zu findende Wert und der zweite Parameter ist der Wert, der ihn ersetzen kann.

      const originalString = 'How are you?'
      
      // Replace the first instance of "How" with "Where"
      const newString = originalString.replace('How', 'Where')
      
      console.log(newString)
      

      Output

      Where are you?

      Wir können nicht nur einen Wert durch einen anderen Zeichenfolgenwert ersetzen, sondern auch reguläre Ausdrücke verwenden, um replace() leistungsfähiger zu machen. Zum Beispiel wirkt sich replace() nur auf den ersten Wert aus, aber wir können das Flag g (global) verwenden, um alle Instanzen eines Werts abzufangen, und das Flag i (ohne Berücksichtigung der Groß- und Kleinschreibung), um Groß- und Kleinschreibung zu ignorieren.

      const originalString =
        "Javascript is a programming language. I'm learning javascript."
      
      // Search string for "javascript" and replace with "JavaScript"
      const newString = originalString.replace(/javascript/gi, 'JavaScript')
      
      console.log(newString)
      

      Output

      JavaScript is a programming language. I'm learning JavaScript.

      Dies ist eine sehr häufige Aufgabe, die reguläre Ausdrücke verwendet. Besuchen Sie Regexr, um weitere Beispiele für RegEx zu üben.

      Zusammenfassung

      Zeichenfolgen sind einer der am häufigsten verwendeten Datentypen, und es gibt eine Menge, was wir mit ihnen tun können.

      In diesem Tutorial haben wir den Unterschied zwischen der Zeichenfolgenprimitive und dem Zeichenfolgenobjekt kennengelernt, wie Zeichenfolgen indiziert werden und wie die integrierten Methoden und Eigenschaften von Zeichenfolgen verwendet werden, um auf Zeichen zuzugreifen, Text zu formatieren und Werte zu suchen und zu ersetzen.

      Eine allgemeinere Übersicht über Zeichenfolgen finden Sie im Lernprogramm „So arbeiten Sie mit Zeichenfolgen in JavaScript“.



      Source link

      So verwenden Sie ps, kill und schön zum Verwalten von Prozessen unter Linux


      Einführung


      Auf einem Linux-Server werden wie auf jedem anderen Computer, mit dem Sie möglicherweise vertraut sind, Anwendungen ausgeführt. Auf dem Computer werden diese als „Prozesse“ bezeichnet.

      Während Linux die Verwaltung auf niedriger Ebene hinter den Kulissen im Lebenszyklus eines Prozesses übernimmt, benötigen Sie eine Möglichkeit zur Interaktion mit dem Betriebssystem, um es von einer höheren Ebene aus zu verwalten.

      In diesem Leitfaden werden wir einige einfache Aspekte der Prozessverwaltung erörtern. Linux bietet eine reichliche Sammlung von Tools für diesen Zweck.

      Wir werden diese Ideen auf einem Ubuntu 12.04 VPS untersuchen, aber jede moderne Linux-Distribution funktioniert auf ähnliche Weise.

      So zeigen Sie laufende Prozesse unter Linux an


      top


      Der einfachste Weg, um herauszufinden, welche Prozesse auf Ihrem Server ausgeführt werden, besteht darin, den Befehl top auszuführen:

      top***
      
      top - 15:14:40 bis 46 min, 1 Benutzer, Lastdurchschnitt: 0,00, 0,01, 0,05 Aufgaben: 56 insgesamt, 1 laufend, 55 inaktiv, 0 gestoppt, 0 Zombie Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st Mem: 1019600k gesamt, 316576k gebraucht, 703024k frei, 7652k Puffer Swap: 0k insgesamt, 0k verwendet, 0k frei, 258976k zwischengespeichert   PID USER PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND               1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 init                   2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd               3 root      20   0     0    0    0 S  0.0  0.0   0:00.07 ksoftirqd/0            6 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0            7 root      RT   0     0    0    0 S  0.0  0.0   0:00.03 watchdog/0             8 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 cpuset                 9 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 khelper               10 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kdevtmpfs
      

      Der oberste Informationsblock enthält Systemstatistiken wie die Systemlast und die Gesamtzahl der Aufgaben.

      Sie können leicht erkennen, dass 1 Prozess ausgeführt wird und 55 Prozesse inaktiv sind (auch bekannt als inaktiv/ohne CPU-Ressourcen).

      Der untere Teil enthält die laufenden Prozesse und ihre Nutzungsstatistiken.

      htop


      Eine verbesserte Version von top namens htop ist in den Repositorys verfügbar. Installieren Sie sie mit diesem Befehl:

      sudo apt-get install htop
      

      Wenn wir den Befehl htop ausführen, sehen wir, dass es eine benutzerfreundlichere Anzeige gibt:

      htop***
      
        Mem[|||||||||||           49/995MB]     Durchschnittslast: 0.00 0.03 0.05   CPU[                          0.0%]     Aufgaben: 21, 3 thr; 1 laufend   Swp[                         0/0MB]     Betriebszeit: 00:58:11   PID USER PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command  1259 root       20   0 25660  1880  1368 R  0.0  0.2  0:00.06 htop     1 root       20   0 24188  2120  1300 S  0.0  0.2  0:00.56 /sbin/init   311 root       20   0 17224   636   440 S  0.0  0.1  0:00.07 upstart-udev-brid   314 root       20   0 21592  1280   760 S  0.0  0.1  0:00.06 /sbin/udevd --dae   389 messagebu  20   0 23808   688   444 S  0.0  0.1  0:00.01 dbus-daemon --sys   407 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.02 rsyslogd -c5   408 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5   409 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5   406 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.04 rsyslogd -c5   553 root       20   0 15180   400   204 S  0.0  0.0  0:00.01 upstart-socket-br
      

      Sie können hier mehr über die Verwendung von top und htop erfahren.

      Verwendung von ps zum Auflisten von Prozessen


      Sowohl top als auch htop bieten eine schöne Benutzeroberfläche, um laufende Prozesse zu sehen, die einem grafischen Aufgabenmanager ähneln.

      Diese Tools sind jedoch nicht immer flexibel genug, um alle Szenarien angemessen zu behandeln. Ein leistungsfähiger Befehl namens ps ist oft die Antwort auf diese Probleme.

      Wenn er ohne Argumente aufgerufen wird, kann die Ausgabe etwas fehlerhafter sein:

      ps***
      
        PID TTY          TIME CMD  1017 pts/0    00:00:00 bash  1262 pts/0    00:00:00 ps
      

      Diese Ausgabe zeigt alle mit dem aktuellen Benutzer und der Terminalsitzung verknüpften Prozesse an. Dies ist sinnvoll, da wir derzeit nur bash und ps mit diesem Terminal ausführen.

      Um ein vollständigeres Bild der Prozesse auf diesem System zu erhalten, können wir Folgendes ausführen:

      ps aux***
      
      USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND root         1  0.0  0.2  24188  2120 ?        Ss   14:28   0:00 /sbin/initroot         2  0.0  0.0      0     0 ?        S    14:28   0:00 [kthreadd] root         3  0.0  0.0      0     0 ?        S    14:28   0:00 [ksoftirqd/0] root         6  0.0  0.0      0     0 ?        S    14:28   0:00 [migration/0] root         7  0.0  0.0      0     0 ?        S    14:28   0:00 [watchdog/0] root         8  0.0  0.0      0     0 ?        S<   14:28   0:00 [cpuset] root         9  0.0  0.0      0     0 ?        S<   14:28   0:00 [khelper] . . .
      

      Diese Optionen weisen ps an, Prozesse, die allen Benutzern gehören (unabhängig von ihrer Terminalzuordnung), in einem benutzerfreundlichen Format anzuzeigen.

      Um eine Baumansicht zu sehen, in der hierarchische Beziehungen illustriert werden, können wir den Befehl mit diesen Optionen ausführen:

      ps axjf***
      
       PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND     0     2     0     0 ?           -1 S        0   0:00 [kthreadd]     2     3     0     0 ?           -1 S        0   0:00  _ [ksoftirqd/0]     2     6     0     0 ?           -1 S        0   0:00  _ [migration/0]     2     7     0     0 ?           -1 S        0   0:00  _ [watchdog/0]     2     8     0     0 ?           -1 S<       0   0:00  _ [cpuset]     2     9     0     0 ?           -1 S<       0   0:00  _ [khelper]     2    10     0     0 ?           -1 S        0   0:00  _ [kdevtmpfs]     2    11     0     0 ?           -1 S<       0   0:00  _ [netns] . . .
      

      Wie Sie sehen können, wird der Prozess kthreadd als übergeordnetes Element des Prozesses ksoftirqd/0 und der anderen Prozesse angezeigt.

      Eine Anmerkung zu Prozess-IDs


      In Linux- und Unix-ähnlichen Systemen wird jedem Prozess einer Prozess-ID oder PID zugewiesen. So identifiziert und verfolgt das Betriebssystem Prozesse.

      Eine schnelle Möglichkeit zum Abrufen der PID eines Prozesses ist mit dem Befehl pgrep:

      pgrep bash***
      
      1017
      

      Dadurch wird die Prozess-ID einfach abfragt und zurückgegeben.

      Der erste beim Booten erzeugte Prozess namens init erhält die PID „1“.

      pgrep init***
      
      1
      

      Dieser Prozess ist dann dafür verantwortlich, jeden anderen Prozess auf dem System zu erzeugen. Die späteren Prozesse erhalten größere PID-Nummern.

      Das übergeordnete Element eines Prozesses ist der Prozess, der für das Ablegen verantwortlich war. Übergeordnete Prozesse verfügen über eine PPID, die Sie in den Spaltenüberschriften vieler Prozessverwaltungsanwendungen sehen können, einschließlich top, htop und ps.

      Jede Kommunikation zwischen dem Benutzer und dem Betriebssystem über Prozesse umfasst die Übersetzung zwischen Prozessnamen und PIDs zu einem bestimmten Zeitpunkt während des Vorgangs. Aus diesem Grund teilen Dienstprogramme Ihnen die PID mit.

      Übergeordnete-untergeordnete Beziehungen


      Das Erstellen eines untergeordneten Prozesses erfolgt in zwei Schritten: fork(), das einen neuen Adressraum erstellt und die Ressourcen des übergeordneten Elements per Copy-on-Write kopiert, um dem untergeordneten Prozess zur Verfügung zu stehen; und exec(), das eine ausführbare Datei in den Adressraum lädt und ausführt.

      Für den Fall, dass ein untergeordneter Prozess vor seinem übergeordneten Prozess beendet wird, wird der untergeordnete Prozess zu einem Zombie, bis der übergeordnete Prozess Informationen darüber gesammelt oder dem Kernel angezeigt hat, dass er diese Informationen nicht benötigt. Die Ressourcen aus dem untergeordneten Prozess werden dann freigegeben. Wenn der übergeordnete Prozess jedoch vor dem untergeordneten Prozess beendet wird, wird der untergeordnete Prozess von init übernommen, obwohl er auch einem anderen Prozess neu zugewiesen werden kann.

      So senden Sie Prozesssignale in Linux


      Alle Prozesse in Linux reagieren auf Signale. Signale sind eine Methode auf Betriebssystemebene, mit der Programme angewiesen werden, ihr Verhalten zu beenden oder zu ändern.

      So senden Sie Prozesssignale nach PID


      Die häufigste Art, Signale an ein Programm weiterzuleiten, ist mit dem Befehl kill.

      Wie Sie möglicherweise erwarten, besteht die Standardfunktion dieses Dienstprogramms darin, zu versuchen, einen Prozess zu beenden:

      kill PID_of_target_process

      Dadurch wird das TERM-Signal an den Prozess gesendet. Das TERM-Signal weist den Prozess an, zu beenden. Dadurch kann das Programm Reinigungsvorgänge durchführen und reibungslos beenden.

      Wenn sich das Programm schlecht verhält und bei Erhalt des TERM-Signals nicht beendet wird, können wir das Signal durch Weiterleiten des KILL-Signals eskalieren:

      kill -KILL PID_of_target_process

      Dies ist ein spezielles Signal, das nicht an das Programm gesendet wird.

      Stattdessen wird es dem Betriebssystem-Kernel übergeben, der den Prozess herunterschaltet. Dies wird verwendet, um Programme zu umgehen, die die an sie gesendeten Signale ignorieren.

      Jedem Signal ist eine Nummer zugeordnet, die anstelle des Namens übergeben werden kann. Beispielsweise können Sie „-15“ anstelle von „-TERM“ und „-9“ anstelle von „-KILL“ übergeben.

      So verwenden Sie Signale für andere Zwecke


      Signale werden nicht nur zum Herunterfahren von Programmen verwendet. Sie können auch verwendet werden, um andere Aktionen auszuführen.

      Beispielsweise werden viele Daemons neu gestartet, wenn sie das HUP– oder Auflegesignal erhalten. Apache ist ein Programm, das so funktioniert.

      sudo kill -HUP pid_of_apache

      Der obige Befehl führt dazu, dass Apache seine Konfigurationsdatei neu lädt und Inhalte wiederbelebt.

      Sie können alle Signale auflisten, die mit kill gesendet werden können, indem Sie Folgendes eingeben:

      kill -l***
      
      1) SIGHUP    2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP  6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM . . .
      

      So senden Sie Prozesssignale nach Name


      Obwohl die konventionelle Art des Sendens von Signalen durch die Verwendung von PIDs ist, gibt es auch Methoden, dies mit regulären Prozessnamen zu tun.

      Der Befehl pkill funktioniert fast genau so wie kill, operiert jedoch stattdessen auf einem Prozessnamen:

      pkill -9 ping
      

      Der obige Befehl ist das Äquivalent von:

      kill -9 `pgrep ping`
      

      Wenn Sie ein Signal an jede Instanz eines bestimmten Prozesses senden möchten, können Sie den Befehl killall verwenden:

      killall firefox
      

      Der obige Befehl sendet das TERM-Signal an jede Instanz von Firefox, das auf dem Computer ausgeführt wird.

      So passen Sie Prozessprioritäten an


      Oft möchten Sie anpassen, welchen Prozessen in einer Serverumgebung Priorität eingeräumt wird.

      Einige Prozesse können als geschäftskritisch für Ihre Situation angesehen werden, während andere ausgeführt werden können, wenn Ressourcen übrig bleiben.

      Linux kontrolliert die Priorität durch einen Wert namens niceness.

      Hohe Prioritätsaufgaben werden als weniger nett angesehen, da sie auch keine Ressourcen teilen. Prozesse mit niedriger Priorität sind dagegen nett, weil sie darauf bestehen, nur minimale Ressourcen zu verbrauchen.

      Als wir am Anfang des Artikels top ausgeführt haben, gab es eine Spalte mit der Bezeichnung „NI“. Dies ist der nette Wert des Prozesses:

      top***
      
      Aufgaben: 56 insgesamt, 1 laufend, 55 inaktiv, 0 gestoppt, 0 Zombie Cpu(s):  0.0%us,  0.3%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st Mem:   1019600k insgesamt,   324496k verwendet,   695104k frei,     8512k Puffer Swap:   0k insgesamt,   0k verwendet,   0k frei,    264812k zwischengespeichert   PID-BENUTZER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            1635 root      20   0 17300 1200  920 R  0.3  0.1   0:00.01 top                    1 root      20   0 24188 2120 1300 S  0,0  0,2   0:00,56 init                   2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd               3 root      20   0     0    0    0 S  0.0  0.0   0:00.11 ksoftirqd/0
      

      Nette Werte können je nach System zwischen „-19/-20“ (höchste Priorität) und „19/20“ (niedrigste Priorität) liegen.

      Um ein Programm mit einem bestimmten netten Wert auszuführen, können wir den Befehl nice verwenden:

      nice -n 15 command_to_execute

      Dies funktioniert nur, wenn ein neues Programm gestartet wird.

      Um den netten Wert eines Programms zu ändern, das bereits ausgeführt wird, verwenden wir ein Tool namens renice:

      renice 0 PID_to_prioritize

      Hinweis: Während nice zwangsläufig mit einem Befehlsnamen funktioniert, ruft renice die Prozess-PID auf

      Zusammenfassung


      Die Prozessverwaltung ist ein Thema, das für neue Benutzer manchmal schwer zu verstehen ist, da sich die verwendeten Tools von ihren grafischen Gegenstücken unterscheiden.

      Die Ideen sind jedoch vertraut und intuitiv und werden mit ein wenig Übung zur Gewohnheit. Da Prozesse an allem beteiligt sind, was Sie mit einem Computersystem tun, ist es eine wesentliche Fähigkeit, zu lernen, wie man sie effektiv steuert.

      Von Justin Ellingwood



      Source link

      Nginx Server- und Standortblockauswahlalgorithmen verstehen


      Einführung

      Nginx ist einer der beliebtesten Webserver der Welt. Er kann hohe Lasten mit vielen gleichzeitigen Clientverbindungen erfolgreich bewältigen und kann problemlos als Webserver, Mailserver oder Reverse-Proxy-Server fungieren.

      In diesem Leitfaden werden wir einige der Details hinter den Kulissen erörtern, die bestimmen, wie Nginx Client-Abfragen verarbeitet. Das Verständnis dieser Ideen kann das Rätselraten beim Entwerfen von Server- und Standortblöcken erleichtern und die Bearbeitung von Abfragen weniger unvorhersehbar erscheinen lassen.

      Nginx-Blockkonfigurationen

      Nginx unterteilt die Konfigurationen, die unterschiedliche Inhalte bereitstellen sollen, logisch in Blöcke, die in einer hierarchischen Struktur leben. Bei jedem Abfragen einer Client-Abfrage beginnt Nginx einen Prozess zur Feststellung, welche Konfigurationsblöcke zur Bearbeitung der Abfrage verwendet werden sollen. Dieser Entscheidungsprozess ist das, was wir in diesem Leitfaden diskutieren werden.

      Die Hauptblöcke, die wir diskutieren werden, sind der Server-Block und der Standort-Block.

      Ein Serverblock ist eine Teilmenge der Nginx-Konfiguration, die einen virtuellen Server definiert, der zur Verarbeitung von Abfragen eines definierten Typs verwendet wird. Administratoren konfigurieren häufig mehrere Serverblöcke und entscheiden anhand des angeforderten Domainnamens, Ports und der IP-Adresse, welcher Block welche Verbindung verarbeiten soll.

      Ein Standortblock befindet sich in einem Serverblock und wird verwendet, um zu definieren, wie Nginx Abfragen für verschiedene Ressourcen und URIs für den übergeordneten Server verarbeiten soll. Der URI-Bereich kann nach Belieben des Administrators mithilfe dieser Blöcke unterteilt werden. Es ist ein extrem flexibles Modell.

      Wie Nginx entscheidet, welcher Serverblock eine Abfrage verarbeiten wird

      Da der Administrator mit Nginx mehrere Serverblöcke definieren kann, die als separate virtuelle Webserverinstanzen fungieren, muss festgelegt werden, welcher dieser Serverblöcke zur Erfüllung einer Abfrage verwendet wird.

      Dies geschieht durch ein definiertes System von Überprüfungen, mit denen die bestmögliche Übereinstimmung gefunden wird. Die wichtigsten Serverblock-Direktiven, mit denen sich Nginx während dieses Prozesses befasst, sind die Direktive listen und server_name.

      Analysieren der „listen“-Direktive, um mögliche Übereinstimmungen zu finden

      Zunächst überprüft Nginx die IP-Adresse und den Port der Abfrage. Dies wird mit der listen-Direktive jedes Servers verglichen, um eine Liste der Serverblöcke zu erstellen, die möglicherweise die Abfrage auflösen können.

      Die listen-Direktive definiert typischerweise, auf welche IP-Adresse und welchen Port der Serverblock reagieren wird. Standardmäßig erhält jeder Serverblock, der keine listen-Direktive enthält, die listen-Parameter 0.0.0.0:80 (oder 0.0.0.0:8080, wenn Nginx von einem normalen non-root-Benutzer ausgeführt wird). Auf diese Weise können diese Blöcke auf Abfragen an einer beliebigen Schnittstelle an Port 80 antworten, aber dieser Standardwert hat im Serverauswahlprozess nicht viel Gewicht.

      Die listen-Direktive kann auf Folgendes eingestellt werden:

      • Eine Kombination aus IP-Adresse und Port.
      • Eine einzelne IP-Adresse, die dann den Standardport 80 überwacht.
      • Ein einzelner Port, der jede Schnittstelle an diesem Port überwacht.
      • Der Pfad zu einem Unix-Socket.

      Die letzte Option hat im Allgemeinen nur Auswirkungen beim Übergeben von Abfragen zwischen verschiedenen Servern.

      Wenn Sie versuchen, zu bestimmen, an welchen Serverblock eine Abfrage gesendet wird, wird Nginx zunächst versuchen, anhand der Spezifität der listen-Direktive mit den folgenden Regeln zu entscheiden:

      • Nginx übersetzt alle „unvollständigen“ listen-Direktiven, indem fehlende Werte mit den Standardwerten ersetzt werden, sodass jeder Block durch seine IP-Adresse und den Port bewertet werden kann. Einige Beispiele für diese Übersetzungen sind:
        • Ein Block ohne listen-Direktive verwendet den Wert 0.0.0.0:80.
        • Ein Block, der auf eine IP-Adresse 111.111.111.111 ohne Port festgelegt ist, wird zu 111.111.111.111:80
        • Ein Block, der auf Port 8888 ohne IP-Adresse festgelegt ist, wird zu 0.0.0.0:8888
      • Nginx versucht dann, eine Liste der Serverblöcke zu sammeln, die der Abfrage am spezifischsten entsprechen, basierend auf der IP-Adresse und dem Port. Dies bedeutet, dass ein Block, der funktional 0.0.0.0 als IP-Adresse verwendet (um mit einer beliebigen Schnittstelle übereinzustimmen), nicht ausgewählt wird, wenn übereinstimmende Blöcke vorhanden sind, in denen eine bestimmte IP-Adresse aufgeführt ist. In jedem Fall muss der Port genau übereinstimmen.
      • Wenn nur eine spezifischste Übereinstimmung vorhanden ist, wird dieser Serverblock verwendet, um die Abfrage zu bedienen. Wenn mehrere Serverblöcke mit derselben Spezifitätsübereinstimmung vorhanden sind, beginnt Nginx mit der Auswertung der Direktive server_name jedes Serverblocks.

      Es ist wichtig, zu verstehen, dass Nginx die Direktive server_name nur dann auswertet, wenn zwischen Serverblöcken unterschieden werden muss, die der gleichen Spezifitätsstufe in der listen-Direktive entsprechen. Wenn beispielsweise example.com auf Port 80 von 192.168.1.10 gehostet wird, wird eine Abfrage für example.com in diesem Beispiel trotz der Direktive server_name im zweiten Block immer vom ersten Block bedient.

      server {
          listen 192.168.1.10;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      

      Für den Fall, dass mehr als ein Serverblock mit gleicher Spezifität übereinstimmt, besteht der nächste Schritt darin, die Direktive server_name zu überprüfen.

      Analysieren der Direktive „server_name“, um eine Übereinstimmung auszuwählen

      Um Abfragen mit gleichermaßen spezifischen listen-Direktiven weiter auszuwerten, überprüft Nginx die „Host“-Überschrift der Abfrage. Dieser Wert enthält die Domain oder IP-Adresse, die der Client tatsächlich versucht hat, zu erreichen.

      Nginx versucht, die beste Übereinstimmung für den gefundenen Wert zu finden, indem es sich die Direktive server_name in jedem der Serverblöcke ansieht, die noch Auswahlkandidaten sind. Nginx bewertet diese durch die folgende Formel:

      • Nginx versucht zunächst, einen Serverblock mit einem server_name zu finden, der dem Wert in der „Host“-Überschrift der Abfrage genau entspricht. Wenn dieser gefunden wird, wird der zugeordnete Block verwendet, um die Abfrage zu bedienen. Wenn mehrere genaue Übereinstimmungen gefunden werden, wird die erste verwendet.
      • Wenn keine genaue Übereinstimmung gefunden wird, versucht Nginx, einen Serverblock mit einem server_name zu finden, der mit einem führenden Platzhalter übereinstimmt (angezeigt durch ein * am Anfang des Namens in der Konfiguration). Wenn eine gefunden wird, wird der zugeordnete Block verwendet, um die Abfrage zu bedienen. Wenn mehrere Übereinstimmungen gefunden werden, wird die längste Übereinstimmung verwendet, um die Abfrage zu bedienen.
      • Wenn mit einem führenden Platzhalter keine Übereinstimmung gefunden wird, sucht Nginx nach einem Serverblock mit einem server_name, der mit einem nachfolgenden Platzhalter übereinstimmt (angezeigt durch einen Servernamen, der in der Konfiguration mit einem * endet). Wenn eine gefunden wird, wird dieser Block verwendet, um die Abfrage zu bedienen. Wenn mehrere Übereinstimmungen gefunden werden, wird die längste Übereinstimmung verwendet, um die Abfrage zu bedienen.
      • Wenn mit einem nachgestellten Platzhalter keine Übereinstimmung gefunden wird, wertet Nginx Serverblöcke aus, die den server_name mithilfe regulärer Ausdrücke definieren (angezeigt durch ein ~ vor dem Namen). Der erste server_name mit einem regulären Ausdruck, der der „Host“-Überschrift entspricht, wird zur Bearbeitung der Abfrage verwendet.
      • Wenn keine Übereinstimmung mit regulären Ausdrücken gefunden wird, wählt Nginx den Standardserverblock für diese IP-Adresse und diesen Port aus.

      Jede Kombination aus IP-Adresse und Port verfügt über einen Standardserverblock, der verwendet wird, wenn mit den oben genannten Methoden keine Vorgehensweise festgelegt werden kann. Bei einer Kombination aus IP-Adresse und Port ist dies entweder der erste Block in der Konfiguration oder der Block, der die Option default_server als Teil der listen-Direktive enthält (die den zuerst gefundenen Algorithmus überschreiben würde). Pro IP-Adresse/Port-Kombination kann nur eine default_server-Deklaration vorhanden sein.

      Beispiele

      Wenn ein server_name definiert ist, der genau mit dem „Host“-Überschriftswert übereinstimmt, wird dieser Serverblock ausgewählt, um die Abfrage zu verarbeiten.

      Wenn in diesem Beispiel die „Host“-Überschrift der Abfrage auf „host1.example.com“ gesetzt wäre, würde der zweite Server ausgewählt:

      server {
          listen 80;
          server_name *.example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name host1.example.com;
      
          . . .
      
      }
      

      Wenn keine genaue Übereinstimmung gefunden wird, prüft Nginx, ob ein server_name mit einem passenden Start-Platzhalter vorhanden ist. Die längste Übereinstimmung mit einem Platzhalter wird ausgewählt, um die Abfrage zu erfüllen.

      Wenn in diesem Beispiel die Abfrage einer „Host“-Überschrift „www.example.org“ hat, würde der zweite Serverblock ausgewählt:

      server {
          listen 80;
          server_name www.example.*;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name *.example.org;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name *.org;
      
          . . .
      
      }
      

      Wenn mit einem Start-Platzhalter keine Übereinstimmung gefunden wird, prüft Nginx anhand eines Platzhalters am Ende des Ausdrucks, ob eine Übereinstimmung vorliegt. An diesem Punkt wird die längste Übereinstimmung mit einem Platzhalter ausgewählt, um die Abfrage zu bedienen.

      Wenn beispielsweise die Abfrage eine „Host“-Überschrift auf „www.example.com“ festgelegt hat, wird der dritte Serverblock ausgewählt:

      server {
          listen 80;
          server_name host1.example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name www.example.*;
      
          . . .
      
      }
      

      Wenn keine Platzhalterübereinstimmungen gefunden werden können, versucht Nginx, Übereinstimmungen mit den Direktiven server_name zuzuordnen, die reguläre Ausdrücke verwenden. Der erste übereinstimmende reguläre Ausdruck wird ausgewählt, um auf die Abfrage zu antworten.

      Wenn beispielsweise die „Host“-Überschrift der Abfrage auf „www.example.com“ gesetzt ist, wird der zweite Serverblock ausgewählt, um die Abfrage zu erfüllen:

      server {
          listen 80;
          server_name example.com;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name ~^(www|host1).*.example.com$;
      
          . . .
      
      }
      
      server {
          listen 80;
          server_name ~^(subdomain|set|www|host1).*.example.com$;
      
          . . .
      
      }
      

      Wenn keiner der oben genannten Schritte die Abfrage erfüllen kann, wird die Abfrage an den Standardserver für die übereinstimmende IP-Adresse und den passenden Port weitergeleitet.

      Übereinstimmung von Standortblöcken

      Ähnlich wie bei dem Prozess, mit dem Nginx den Serverblock auswählt, der eine Abfrage verarbeitet, verfügt Nginx auch über einen etablierten Algorithmus zur Entscheidung, welcher Standortblock innerhalb des Servers zur Verarbeitung von Abfragen verwendet werden soll.

      Standortblock-Syntax

      Bevor wir uns damit befassen, wie Nginx entscheidet, welcher Standortblock zur Verarbeitung von Abfragen verwendet werden soll, gehen wir einen Teil der Syntax durch, der möglicherweise in Standortblockdefinitionen angezeigt wird. Standortblöcke befinden sich in Serverblöcken (oder anderen Standortblöcken) und werden verwendet, um zu entscheiden, wie der Abfrage-URI (der Teil der Abfrage, der nach dem Domainnamen oder der IP-Adresse/dem IP-Port kommt) verarbeitet werden soll.

      Standortblöcke haben im Allgemeinen die folgende Form:

      location optional_modifier location_match {
      
          . . .
      
      }
      

      Das oben angezeigte location_match definiert, gegen was Nginx den Abfrage-URI prüfen soll. Das Vorhandensein oder Nichtvorhandensein des Modifikators im obigen Beispiel beeinflusst die Art und Weise, wie der Nginx versucht, mit dem Standortblock übereinzustimmen. Die folgenden Modifikatoren bewirken, dass der zugehörige Standortblock wie folgt interpretiert wird:

      • (none): Wenn keine Modifikatoren vorhanden sind, wird der Speicherort als Präfix-Übereinstimmung interpretiert. Dies bedeutet, dass der angegebene Speicherort mit dem Beginn des Abfrage-URIs abgeglichen wird, um eine Übereinstimmung zu ermitteln.
      • =: Wenn ein Gleichheitszeichen verwendet wird, wird dieser Block als Übereinstimmung betrachtet, wenn der Abfrage-URI genau mit dem angegebenen Standort übereinstimmt.
      • ~: Wenn ein Tilde-Modifikator vorhanden ist, wird dieser Speicherort als Übereinstimmung zwischen regulären Ausdrücken und Groß- und Kleinschreibung interpretiert.
      • ~*: Wenn ein Tilde- und ein Sternchen-Modifikator verwendet werden, wird der Positionsblock als Übereinstimmung zwischen regulären Ausdrücken ohne Berücksichtigung der Groß- und Kleinschreibung interpretiert.
      • ^~: Wenn ein Karat- und Tilde-Modifikator vorhanden ist und dieser Block als beste Übereinstimmung mit nicht regulären Ausdrücken ausgewählt ist, findet keine Übereinstimmung mit regulären Ausdrücken statt.

      Beispiele zur Demonstration der Standortblock-Syntax

      Als Beispiel für die Präfixübereinstimmung kann der folgende Standortblock ausgewählt werden, um auf Abfrage-URIs zu antworten, die wie /site, /site/page1/index.html oder /site/index.html aussehen:

      location /site {
      
          . . .
      
      }
      

      Zur Demonstration der genauen Übereinstimmung der Abfrage-URI wird dieser Block immer verwendet, um auf eine Abfrage-URI zu antworten, die wie /page1 aussieht. Es wird nicht verwendet, um auf eine /page1/index.html-Abfrage-URI zu antworten. Beachten Sie, dass bei Auswahl dieses Blocks und Erfüllung der Abfrage über eine Indexseite eine interne Umleitung an einen anderen Speicherort erfolgt, der der eigentliche Handhaber der Abfrage ist:

      location = /page1 {
      
          . . .
      
      }
      

      Als Beispiel für einen Speicherort, der als regulärer Ausdruck mit Groß- und Kleinschreibung interpretiert werden sollte, kann dieser Block verwendet werden, um Abfragen für /tortoise.jpg zu verarbeiten, nicht jedoch für /FLOWER.PNG:

      location ~ .(jpe?g|png|gif|ico)$ {
      
          . . .
      
      }
      

      Ein Block, der eine Übereinstimmung ohne Berücksichtigung der Groß- und Kleinschreibung ähnlich wie oben ermöglichen würde, ist unten dargestellt. Hier könnten sowohl /tortoise.jpg als auch /FLOWER.PNG von diesem Block verarbeitet werden:

      location ~* .(jpe?g|png|gif|ico)$ {
      
          . . .
      
      }
      

      Schließlich würde dieser Block verhindern, dass eine Übereinstimmung mit regulären Ausdrücken auftritt, wenn festgestellt wird, dass dies die beste Übereinstimmung mit nicht regulären Ausdrücken ist. Er könnte Abfragen für /costumes/ninja.html verarbeiten:

      location ^~ /costumes {
      
          . . .
      
      }
      

      Wie Sie sehen, geben die Modifikatoren an, wie der Standortblock interpretiert werden soll. Dies sagt uns jedoch nicht, welchen Algorithmus Nginx verwendet, um zu entscheiden, an welchen Standortblock die Abfrage gesendet werden soll. Wir werden das als nächstes durchgehen.

      Wie Nginx wählt, welcher Standort zur Bearbeitung von Abfragen verwendet werden soll

      Nginx wählt den Speicherort aus, an dem eine Abfrage bearbeitet wird, ähnlich wie bei der Auswahl eines Serverblocks. Es wird ein Prozess durchlaufen, der den besten Standortblock für eine bestimmte Abfrage ermittelt. Das Verständnis dieses Prozesses ist eine entscheidende Anforderung, um Nginx zuverlässig und korrekt konfigurieren zu können.

      Unter Berücksichtigung der oben beschriebenen Arten von Standortdeklarationen bewertet Nginx die möglichen Standortkontexte, indem der Abfrage-URI mit jedem der Standorte verglichen wird. Dies geschieht mit dem folgenden Algorithmus:

      • Nginx überprüft zunächst alle Präfix-basierten Standortübereinstimmungen (alle Standorttypen, die keinen regulären Ausdruck enthalten). Es vergleicht jeden Standort mit dem vollständigen Abfrage-URI.
      • Zunächst sucht Nginx nach einer genauen Übereinstimmung Wenn ein Standortblock mit dem Modifikator = gefunden wird, der genau mit dem Abfrage-URI übereinstimmt, wird dieser Standortblock sofort ausgewählt, um die Abfrage zu bedienen.
      • Wenn keine genauen (mit dem Modifikator =) Positionsblockübereinstimmungen gefunden werden, fährt Nginx mit der Auswertung nicht exakter Präfixe fort. Es ermittelt den am längsten übereinstimmenden Präfixspeicherort für den angegebenen Abfrage-URI, den es dann wie folgt auswertet:
        • Wenn der am längsten übereinstimmende Präfixstandort den Modifikator ^ ~ hat, beendet Nginx die Suche sofort und wählt diesen Standort aus, um die Abfrage zu bearbeiten.
        • Wenn die Position mit dem längsten übereinstimmenden Präfix nicht den Modifikator ^ ~ verwendet, wird die Übereinstimmung für den Moment von Nginx gespeichert, damit der Fokus der Suche verschoben werden kann.
      • Nachdem die Position mit der längsten Übereinstimmung ermittelt und gespeichert wurde, fährt Nginx mit der Auswertung der Positionen für reguläre Ausdrücke fort (sowohl Groß- und Kleinschreibung als auch Nicht-Groß-/Kleinschreibung beachten). Wenn sich Positionen mit regulären Ausdrücken innerhalb der am längsten übereinstimmenden Präfixposition befinden, verschiebt Nginx diese an den Anfang der Liste der zu überprüfenden Regex-Positionen. Nginx versucht dann, nacheinander mit den Positionen der regulären Ausdrücke abzugleichen. Der erste reguläre Ausdruck des Standortes wird sofort ausgewählt, um die Abfrage zu bedienen.
      • Wenn keine Standorte für reguläre Ausdrücke gefunden werden, die mit dem Abfrage-URI übereinstimmen, wird der zuvor gespeicherte Präfixstandort ausgewählt, um die Abfrage zu bedienen.

      Es ist wichtig, zu verstehen, dass Nginx standardmäßig Übereinstimmungen mit regulären Ausdrücken anstelle von Präfixübereinstimmungen bereitstellt. Es werden jedoch zuerst Präfixpositionen ausgewertet, sodass die Verwaltung diese Tendenz überschreiben kann, indPositionen mit den Modifikatoren = und ^ ~ angegeben werden.

      Es ist auch wichtig, zu beachten, dass, während Präfixpositionen im Allgemeinen basierend auf der längsten, spezifischsten Übereinstimmung ausgewählt werden, die Auswertung regulärer Ausdrücke gestoppt wird, wenn die erste übereinstimmende Position gefunden wird. Dies bedeutet, dass die Positionierung innerhalb der Konfiguration enorme Auswirkungen auf die Positionen regulärer Ausdrücke hat.

      Schließlich ist es wichtig, zu verstehen, dass Übereinstimmungen mit regulären Ausdrücken innerhalb der längsten Präfixübereinstimmung „die Zeile überspringen“, wenn Nginx Regex-Positionen auswertet. Diese werden der Reihe nach ausgewertet, bevor andere Übereinstimmungen mit regulären Ausdrücken berücksichtigt werden. Maxim Dounin, ein unglaublich hilfreicher Nginx-Entwickler, erklärt in diesem Beitrag diesen Teil des Auswahlalgorithmus.

      Wann springt die Standortblockbewertung zu anderen Standorten?

      Wenn ein Standortblock ausgewählt wird, um eine Abfrage zu bedienen, wird die Abfrage im Allgemeinen von diesem Punkt an vollständig in diesem Kontext behandelt. Nur der ausgewählte Standort und die geerbten Anweisungen bestimmen, wie die Abfrage verarbeitet wird, ohne dass Geschwisterstandortblöcke eingreifen.

      Obwohl dies eine allgemeine Regel ist, mit der Sie Ihre Standortblöcke auf vorhersehbare Weise entwerfen können, ist es wichtig zu wissen, dass es manchmal Zeiten gibt, in denen eine neue Standortsuche durch bestimmte Anweisungen innerhalb des ausgewählten Standortes ausgelöst wird. Die Ausnahmen von der Regel „Nur ein Standortblock“ können Auswirkungen auf die tatsächliche Zustellung der Abfrage haben und stimmen möglicherweise nicht mit den Erwartungen überein, die Sie beim Entwerfen Ihrer Standortblöcke hatten.

      Einige Direktiven, die zu dieser Art der internen Weiterleitung führen können, sind:

      • index
      • try_files
      • rewrite
      • error_page

      Gehen wir diese kurz durch.

      Die Direktive index führt immer zu einer internen Weiterleitung, wenn sie verwendet wird, um die Abfrage zu verarbeiten. Genaue Standortübereinstimmungen werden häufig verwendet, um den Auswahlprozess zu beschleunigen, indem die Ausführung des Algorithmus sofort beendet wird. Wenn Sie jedoch eine genaue Standortübereinstimmung mit einem Verzeichnis vornehmen, besteht eine gute Chance, dass die Abfrage zur tatsächlichen Verarbeitung an einen anderen Standort umgeleitet wird.

      In diesem Beispiel wird der erste Standort mit einem Abfrage-URI von /exact abgeglichen. Um die Abfrage zu verarbeiten, initiiert die vom Block geerbte Indexanweisung eine interne Umleitung zum zweiten Block:

      index index.html;
      
      location = /exact {
      
          . . .
      
      }
      
      location / {
      
          . . .
      
      }
      

      Wenn Sie im obigen Fall wirklich die Ausführung benötigen, um im ersten Block zu bleiben, müssen Sie eine andere Methode finden, um die Abfrage an das Verzeichnis zu erfüllen. Sie können beispielsweise einen ungültigen index für diesen Block festlegen und den autoindex aktivieren:

      location = /exact {
          index nothing_will_match;
          autoindex on;
      }
      
      location  / {
      
          . . .
      
      }
      

      Dies ist eine Möglichkeit, um zu verhindern, dass ein index den Kontext wechselt, ist jedoch für die meisten Konfigurationen wahrscheinlich nicht hilfreich. Meistens kann eine genaue Übereinstimmung mit Verzeichnissen hilfreich sein, um beispielsweise die Abfrage neu zu schreiben (was auch zu einer neuen Standortsuche führt).

      Eine andere Instanz, in der der Verarbeitungsort neu bewertet werden kann, ist die Direktive try_files. Diese Direktive weist Nginx an, das Vorhandensein einer benannten Gruppe von Dateien oder Verzeichnissen zu überprüfen. Der letzte Parameter kann ein URI sein, zu dem Nginx eine interne Umleitung vornimmt.

      Erwägen Sie folgende Konfiguration:

      root /var/www/main;
      location / {
          try_files $uri $uri.html $uri/ /fallback/index.html;
      }
      
      location /fallback {
          root /var/www/another;
      }
      

      Wenn im obigen Beispiel eine Anfrage für /blahblah gestellt wird, erhält der erste Standort zunächst die Abfrage. Er wird versuchen, eine Datei namens blahblah im Verzeichnis /var/www/main zu finden. Wenn gefunden werden kann, wird anschließend nach einer Datei mit dem Namen blahblah.html gesucht. Anschließend wird versucht, festzustellen, ob sich im Verzeichnis /var/www/main ein Verzeichnis mit dem Namen blahblah/ befindet. Wenn alle diese Versuche fehlschlagen, wird zu /fallback/index.html umgeleitet. Dies löst eine weitere Standortsuche aus, die vom zweiten Standortblock abgefangen wird. Dies wird die Datei /var/www/anderen/fallback/index.html bereitstellen.

      Eine weitere Direktive, die dazu führen kann, dass ein Standortblock übergeben wird, ist die Direktive rewrite. Wenn Sie den letzten Parameter mit der Direktive rewrite zum Umschreiben oder überhaupt keinen Parameter verwenden, sucht Nginx basierend auf den Ergebnissen des Umschreibens nach einem neuen übereinstimmenden Standort.

      Wenn wir beispielsweise das letzte Beispiel so ändern, dass es ein Umschreiben enthält, können wir feststellen, dass die Abfrage manchmal direkt an den zweiten Standort übergeben wird, ohne sich auf die Direktive try_files zu verlassen:

      root /var/www/main;
      location / {
          rewrite ^/rewriteme/(.*)$ /$1 last;
          try_files $uri $uri.html $uri/ /fallback/index.html;
      }
      
      location /fallback {
          root /var/www/another;
      }
      

      Im obigen Beispiel wird eine Abfrage für /rewriteme/hello zunächst vom ersten Standortblock verarbeitet. Sie wird in /hello umgeschrieben und ein Standort gesucht. In diesem Fall stimmt sie wieder mit dem ersten Standort überein und wird wie gewohnt von den try_files verarbeitet. Wenn nichts gefunden wird, kehren Sie möglicherweise zu /fallback/index.html zurück (mithilfe der oben beschriebenen internen Umleitung try_files).

      Wenn jedoch eine Abfrage für /rewriteme/fallback/hello gestellt wird, stimmt der erste Block erneut überein. Das Umschreiben wird erneut angewendet, diesmal mit /fallback/hello. Die Abfrage wird dann aus dem zweiten Standortblock heraus zugestellt.

      Eine verwandte Situation tritt bei der Direktive return auf, wenn die Statuscodes 301 oder 302 gesendet werden. Der Unterschied in diesem Fall ist, dass es eine völlig neue Abfrage in Form einer extern sichtbaren Umleitung bildet. Dieselbe Situation kann bei der Direktive rewrite auftreten, wenn die Flags redirect oder permanent verwendet werden. Diese Standortsuche sollte jedoch nicht unerwartet sein, da extern sichtbare Weiterleitungen immer zu einer neuen Abfrage führen.

      Die Direktive error_page kann zu einer internen Umleitung führen, die der von try_files erstellten ähnelt. Diese Direktive wird verwendet, um zu definieren, was passieren soll, wenn bestimmte Statuscodes aufgetreten sind. Dies wird wahrscheinlich nie ausgeführt, wenn try_files festgelegt ist, da diese Direktive den gesamten Lebenszyklus einer Abfrage behandelt.

      Erwägen Sie dieses Beispiel:

      root /var/www/main;
      
      location / {
          error_page 404 /another/whoops.html;
      }
      
      location /another {
          root /var/www;
      }
      

      Jede Abfrage (außer denjenigen, die mit /another beginnen) wird vom ersten Block bearbeitet, der Dateien aus /var/www/main bereitstellt. Wenn jedoch keine Datei gefunden wird (Status 404), erfolgt eine interne Umleitung zu /another/whoops.html, die zu einer neuen Standortsuche führt, die schließlich im zweiten Block landet. Diese Datei wird aus /var/www/another/whoops.html. bereitgestellt.

      Wie Sie sehen können, kann das Verständnis der Umstände, unter denen Nginx eine neue Standortsuche auslöst, dazu beitragen, das Verhalten vorherzusagen, das bei Abfragen auftreten wird.

      Zusammenfassung

      Wenn Sie wissen, wie Nginx Client-Abfragen verarbeitet, können Sie Ihre Arbeit als Administrator erheblich vereinfachen. Sie können anhand jeder Client-Abfrage wissen, welchen Serverblock Nginx auswählt. Sie können auch anhand der Abfrage-URI festlegen, wie der Standortblock ausgewählt wird. Wenn Sie wissen, wie Nginx verschiedene Blöcke auswählt, können Sie die Kontexte verfolgen, die Nginx anwenden wird, um jede Abfrage zu bearbeiten.



      Source link