Falling Down the Rabbit Hole: D'Geschicht vun engem Lack Restart Feeler - Deel 1

Ghostinushanka, nodeems hien déi lescht 20 Minutten op d'Knäppercher geklappt huet, wéi wann säi Liewen dovunner ofhänkt, dréit mech mat engem semi-wëllen Ausdrock an den Aen an engem schlau Grinsen - "Dude, ech mengen ech verstinn."

"Kuckt hei," seet hien, weist op ee vun de Symboler um Écran, "Ech wetten op mäi roude Hutt, datt wa mir hei addéieren wat ech Iech just geschéckt hunn" - weist op eng aner Sektioun vum Code - "de Feeler ass net méi wäert erausginn."

E bësse verwonnert an midd änneren ech de sed Ausdrock un deem mir eng Zäit laang geschafft hunn, späichert d'Datei a lafen systemctl varnish reload. D'Feelermeldung ass verschwonnen ...

"Déi E-Mailen, déi ech mam Kandidat ausgetosch hunn", huet mäi Kolleg weidergespillt, wéi säi Lach an e richtegt Laachen voller Freed verwandelt, "Et huet mech op eemol opgefaang datt dëst genau dee selwechte Problem ass!"

Wéi huet et alles ugefaang

Den Artikel iwwerhëlt e Verständnis vu wéi bash, awk, sed a systemd funktionnéieren. Wëssen iwwer Lacker ass léiwer awer net erfuerderlech.
Zäitstempel an Snippets goufen geännert.
Geschriwwen mat Ghostinushanka.
Dësen Text ass eng Iwwersetzung vum Original publizéiert virun zwou Wochen op Englesch; Iwwersetzung boyikoden.

D'Sonn schéngt duerch d'Panorama-Fënstere op engem anere waarmen Hierschtmoien, eng Taass frësch gebrouwen koffeinhaltege Gedrénks steet op der Säit vun der Tastatur, eng Liiblingssymphonie vu Kläng spillt an den Kopfhörer iwwer d'Russel vu mechanesche Keyboards, an den éischten Entrée an der Lëscht vun de Réckbléck Ticketen op der Kanban Verwaltungsrot spillt spilleresch mat der schicksal Titel "Untersuchen varnishreload sh: Echo: I / O Feeler an der Inszenéierung" (Untersuchen "varnishreload sh: Echo: I / O Feeler" an der Inszenéierung). Wann et ëm Lacker geet, ginn et keng a kënne keng Feeler sinn, och wa se keng Problemer hunn, wéi an dësem Fall.

Fir déi, déi net vertraut sinn vernishreload, Dëst ass en einfache Shell-Skript fir d'Konfiguratioun nei ze lueden Lacker - och VCL genannt.

Wéi den Titel vum Ticket seet, ass de Feeler op ee vun de Serveren an der Bühn opgetrueden, a well ech war zouversiichtlech datt d'Lackrouting an der Bühn richteg funktionnéiert, hunn ech ugeholl datt dëst e klenge Feeler wier. Also, just e Message deen an e scho zougemaachen Ausgangsstroum koum. Ech huelen en Ticket fir mech, a voller Vertrauen datt ech et a manner wéi 30 Minutten fäerdeg markéiere wäert, klappe mech op d'Schëller fir de Bord vun der nächster Dreck ze läschen an zréck op méi wichteg Saachen.

Mat 200 km/h an eng Mauer gerannt

Eng Datei opmaachen varnishreload, Op engem vun de Serveren, déi Debian Stretch lafen, hunn ech e Shell-Skript manner wéi 200 Zeilen laang gesinn.

Nodeems ech de Skript duerchgefouert hunn, hunn ech näischt gemierkt wat zu Probleemer kéint féieren wann Dir et e puer Mol direkt vum Terminal leeft.

Et ass schliisslech eng Etapp, och wann se brécht, wäert kee sech beschwéieren, bon ... net ze vill. Ech lafen de Skript a kucken wat op den Terminal geschriwwe gëtt, awer d'Feeler sinn net méi ze gesinn.

E puer méi leeft fir sécher ze stellen, datt ech de Feeler net ouni e puer extra Efforten reproduzéieren kann, an ech fänken un erauszefannen wéi ech dëst Skript änneren an et nach ëmmer e Feeler werfen.

Kann de Skript STDOUT blockéieren (benotzt > &-)? Oder STDERR? Weder huet um Enn geschafft.

Selbstverständlech systeméiert ännert d'Runëmfeld op iergendeng Manéier, awer wéi a firwat?
Ech schalten vim un an änneren varnishreload, dobäizemaachen set -x direkt ënner dem Shebang, an der Hoffnung datt d'Debugging vum Output vum Skript e bësse Liicht werft.

De Fichier ass fixéiert, dofir lued ech Lack nei a gesinn datt d'Ännerung alles komplett gebrach huet ... Den Auspuff ass e komplette Mess, mat Tonne C-ähnlechen Code dran. Och am Terminal scrollen ass net genuch fir ze fannen wou et ufänkt. Ech sinn komplett duercherneen. Kann Debugmodus d'Aarbecht vu Programmer beaflossen, déi an engem Skript lafen? Nee, Blödsinn. Käfer an der Schuel? Verschidde méiglech Szenarie fléien a mengem Kapp wéi Kakerlaken a verschiddene Richtungen. Eng Taass Kaffi-voll Gedrénks gëtt direkt eidel, e séiere Rees an d'Kichen fir eng Neiversuergung an ... loosst eis goen. Ech maachen de Skript op a kucken de Shebang: #!/bin/sh.

/bin/sh - Dëst ass just e Bash Symlink, sou datt de Skript am POSIX-kompatiblen Modus interpretéiert gëtt, richteg? Et war net do! D'Default Shell op Debian ass Dash, dat ass genau wat bezitt /bin/sh.

# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Jan 24  2017 /bin/sh -> dash

Fir d'Wuel vun Prozess, Ech geännert der shebang zu #!/bin/bash, geläscht set -x a probéiert nach eng Kéier. Schlussendlech, bei der spéider Neiladung vu Lack, erschéngt en tolerable Feeler am Ausgang:

Jan 01 12:00:00 hostname varnishreload[32604]: /usr/sbin/varnishreload: line 124: echo: write error: Broken pipe
Jan 01 12:00:00 hostname varnishreload[32604]: VCL 'reload_20190101_120000_32604' compiled

Linn 124, hei ass et!

114 find_vcl_file() {
115         VCL_SHOW=$(varnishadm vcl.show -v "$VCL_NAME" 2>&1) || :
116         VCL_FILE=$(
117                 echo "$VCL_SHOW" |
118                 awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}' | {
119                         # all this ceremony to handle blanks in FILE
120                         read -r DELIM VCL_SHOW INDEX SIZE FILE
121                         echo "$FILE"
122                 }
123         ) || :
124
125         if [ -z "$VCL_FILE" ]
126         then
127                 echo "$VCL_SHOW" >&2
128                 fail "failed to get the VCL file name"
129         fi
130
131         echo "$VCL_FILE"
132 }

Mä wéi et sech erausstellt, ass d'Linn 124 éischter eidel a keen Interessi. Ech konnt nëmmen unhuelen datt de Feeler geschitt ass als Deel vun enger Multiline déi op der Linn 116 ugefaang huet.
Wat schlussendlech un der Variabel geschriwwe gëtt VCL_FILE als Resultat vun der Ausféierung vun der uewe genannter Ënner-Shell?

Am Ufank schéckt et den Inhalt vun der Variabel VLC_SHOW, erstallt op der Linn 115, op den nächste Kommando duerch d'Päif. A wat geschitt dann do?

Éischtens, et benotzt varnishadm, deen Deel vum Lackinstallatiounspaket ass, fir Lack ze konfiguréieren ouni nei ze starten.

Ënnerbefehl vcl.show -v gëtt benotzt fir d'ganz VCL Konfiguratioun auszeginn ${VCL_NAME}, zu STDOUT.

Fir déi aktuell aktiv VCL Konfiguratioun wéi och e puer virdrun Versioune vu Lacker Routing Konfiguratiounen ze weisen, déi nach ëmmer an der Erënnerung sinn, kënnt Dir de Kommando benotzen varnishadm vcl.list, d'Ausgab vun deem wäert ähnlech wéi déi folgend sinn:

discarded   cold/busy       1 reload_20190101_120000_11903
discarded   cold/busy       2 reload_20190101_120000_12068
discarded   cold/busy       16 reload_20190101_120000_12259
discarded   cold/busy       16 reload_20190101_120000_12299
discarded   cold/busy       28 reload_20190101_120000_12357
active      auto/warm       32 reload_20190101_120000_12397
available   auto/warm       0 reload_20190101_120000_12587

Variabel Wäert ${VCL_NAME} an engem aneren Deel vum Skript gesat varnishreload op den Numm vum aktuell aktive VCL, wann iwwerhaapt. An dësem Fall ass et "reload_20190101_120000_12397".

Okay, variabel. ${VCL_SHOW} enthält déi komplett Konfiguratioun fir Lack, sou wäit kloer. Elo verstinn ech endlech firwat Dash Output mat set -x huet sech sou gebrach erausgestallt - et enthält den Inhalt vun der resultéierender Konfiguratioun.

Et ass wichteg ze verstoen datt eng komplett VCL Konfiguratioun dacks aus verschiddene Dateien zesummegeklappt ka ginn. C-Stil Kommentarer gi benotzt fir ze definéieren wou eng Konfiguratiounsdatei an engem aneren abegraff ass, an dat ass genau wat déi ganz Linn vum Code Snippet hei drënner ass.
D'Syntax fir Kommentarer déi abegraff Dateien beschreiwen huet de folgende Format:

// VCL.SHOW <NUM> <NUM> <FILENAME>

D'Zuelen an dësem Kontext sinn net wichteg, mir sinn interesséiert fir den Dateinumm.

Also wat geschitt am Sumpf vun Kommandoen, déi op der Linn 116 ufänkt?
Loosse mer et erausfannen.
De Kommando besteet aus véier Deeler:

  1. Einfach echo, déi de Wäert vun der Variabel weist ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk, déi no enger Zeil (Rekord) sicht, wou dat éischt Feld, no der Spaltung vum Text, "//" ass, an dat zweet "VCL.SHOW".
    Awk schreift déi éischt Zeil aus, déi dës Mustere entsprécht an da stoppen d'Veraarbechtung direkt.

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. E Block vu Code deen d'Feldwäerter a fënnef Variablen späichert, getrennt vu Plazen. Déi fënnef Variabel FILE kritt de Rescht vun der Linn. Schlussendlech schreift de leschten Echo den Inhalt vun der Variabel eraus ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. Well all Schrëtt 1 bis 3 an enger Ënner-Shell zougemaach sinn, ass d'Ausgab vum Wäert $FILE wäert zu enger Variabel geschriwwe ginn VCL_FILE.

Wéi de Kommentar op der Linn 119 seet, déngt dëst den eenzegen Zweck fir zouverlässeg Fäll ze handhaben, wou de VCL op Dateie mat Whitespace Charaktere an hiren Nimm bezitt.

Ech hunn d'Original Veraarbechtung Logik kommentéiert fir ${VCL_FILE} a probéiert d'Sequenz vun de Kommandoen z'änneren, awer et huet zu näischt gefouert. Alles huet propper fir mech geschafft, an am Fall vum Start vum Service huet et e Feeler ginn.

Et schéngt, datt de Feeler einfach net reproduzéierbar ass wann Dir de Skript manuell leeft, während déi geschätzte 30 Minutten scho sechs Mol eriwwer sinn an zousätzlech eng méi héich Prioritéit Aufgab opgetaucht ass, déi de Rescht vun de Fäll op der Säit dréckt. De Rescht vun der Woch war mat villen Aufgaben gefëllt a gouf nëmme liicht verdënntem mat engem Gespréich iwwer Sed an engem Interview mam Kandidat. Feeler Problem an varnishreload irretrievably verluer am Sands vun Zäit.

Deng sougenannte Sed-Fu... eigentlech... Dreck

Déi nächst Woch hat een zimlech fräien Dag, also hunn ech décidéiert dësen Ticket erëm opzehuelen. Ech hunn gehofft, datt a mengem Gehir e puer Hannergrondprozesser all dës Zäit no enger Léisung fir dëse Problem gesicht hunn, an dës Kéier wäert ech definitiv verstoen wat falsch ass.

Well d'lescht Kéier just de Code änneren net gehollef huet, hunn ech just decidéiert et vun der 116. Zeil ëmzeschreiwen. Op alle Fall war de existente Code domm. An et ass absolut net néideg ze benotzen read.

Kuckt de Feeler nach eng Kéier:
sh: echo: broken pipe - an dësem Kommando ass Echo op zwou Plazen, awer ech de Verdacht datt deen éischten de méi wahrscheinleche Täter ass (gutt, oder op d'mannst e Kompliz). Awk inspiréiert och kee Vertrauen. An am Fall wou et wierklech ass awk | {read; echo} den Design féiert zu all dëse Problemer, firwat net ersetzen? Dëst eent-Linn Kommando benotzt net all d'Features vun awk, an och dës extra read am Anhang.

Zënter der leschter Woch gouf et e Bericht iwwer sedEch wollt meng nei erfuerene Fäegkeeten probéieren a vereinfachen echo | awk | { read; echo} an eng méi verständlech echo | sed. Och wann dëst definitiv net déi bescht Approche ass fir de Käfer ze fangen, hunn ech geduecht datt ech op d'mannst mäi Sed-Fu probéieren a vläicht eppes Neies iwwer de Problem léieren. Ënnerwee hunn ech mäi Kolleg, de Sed Talk Schrëftsteller, gefrot mir ze hëllefen mat engem méi effiziente Sed Skript ze kommen.

Ech hunn den Inhalt erofgelooss varnishadm vcl.show -v "$VCL_NAME" op eng Datei sou datt ech mech op d'Schreiwe vum Sed Skript konzentréieren kann ouni de Stress vum Service nei ze starten.

Eng kuerz Beschreiwung vu genau wéi sed den Input handhabt ka fonnt ginn säi GNU Handbuch. An der sed Quellen, d'Symbol n explizit als Zeilentrener uginn.

A verschiddene Passagen, a mam Rot vu mengem Kolleg, hu mir e Sed-Skript geschriwwen, deen datselwecht Resultat huet wéi déi ganz originell Linn 116.

Drënner ass eng Probedatei mat Inputdaten:

> cat vcl-example.vcl
Text
// VCL.SHOW 0 1578 file with 3 spaces.vcl
More text
// VCL.SHOW 0 1578 file.vcl
Even more text
// VCL.SHOW 0 1578 file with TWOspaces.vcl
Final text

Et ass vläicht net evident aus der uewe genannter Beschreiwung, awer mir sinn nëmmen am éischte Kommentar interesséiert // VCL.SHOW, an et kënnen e puer vun hinnen an den Inputdaten sinn. Dofir schléisst den Original awk nom éischte Match of.

# шаг первый, вывести только строки с комментариями
# используя возможности sed, определяется символ-разделитель с помощью конструкции '#' вместо обычно используемого '/', за счёт этого не придётся экранировать косые в искомом комментарии
# определяется регулярное выражение “// VCL.SHOW”, для поиска строк с определенным шаблоном
# флаг -n позаботится о том, чтобы sed не выводил все входные данные, как он это делает по умолчанию (см. ссылку выше)
# -E позволяет использовать расширенные регулярные выражения
> cat vcl-processor-1.sed
#// VCL.SHOW#p
> sed -En -f vcl-processor-1.sed vcl-example.vcl
// VCL.SHOW 0 1578 file with 3 spaces.vcl
// VCL.SHOW 0 1578 file.vcl
// VCL.SHOW 0 1578 file with TWOspaces.vcl

# шаг второй, вывести только имя файла
# используя команду “substitute”, с группами внутри регулярных выражений, отображается только нужная группa
# и это делается только для совпадений, ранее описанного поиска
> cat vcl-processor-2.sed
#// VCL.SHOW# {
    s#.* [0-9]+ [0-9]+ (.*)$#1#
    p
}
> sed -En -f vcl-processor-2.sed vcl-example.vcl
file with 3 spaces.vcl
file.vcl
file with TWOspaces.vcl

# шаг третий, получить только первый из результатов
# как и в случае с awk, добавляется немедленное завершения после печати первого найденного совпадения
> cat vcl-processor-3.sed
#// VCL.SHOW# {
    s#.* [0-9]+ [0-9]+ (.*)$#1#
    p
    q
}
> sed -En -f vcl-processor-3.sed vcl-example.vcl
file with 3 spaces.vcl

# шаг четвертый, схлопнуть всё в однострочник, используя двоеточия для разделения команд
> sed -En -e '#// VCL.SHOW#{s#.* [0-9]+ [0-9]+ (.*)$#1#p;q;}' vcl-example.vcl
file with 3 spaces.vcl

Also den Inhalt vum Varnishreload Skript géif esou ausgesinn:

VCL_FILE="$(echo "$VCL_SHOW" | sed -En '#// VCL.SHOW#{s#.*[0-9]+ [0-9]+ (.*)$#1#p;q;};')"

Déi uewe genannte Logik kann wéi follegt zesummegefaasst ginn:
Wann String reegelméissegen Ausdrock entsprécht // VCL.SHOW, da giereg den Text op, dee béid Zuelen an där Linn enthält, a späichert alles wat no dëser Operatioun iwwreg ass. Gitt de gespäicherten Wäert eraus an Enn de Programm.

Einfach, ass et net?

Mir ware frou mam Sed Skript an der Tatsaach datt et all den ursprénglechen Code ersetzt. All meng Tester hunn déi gewënschte Resultater ginn, also hunn ech den "varnishreload" um Server geännert an erëm gelaf systemctl reload varnish. Dreckeg Feeler echo: write error: Broken pipe eis erëm an d’Gesiicht gelaacht. E Winking Cursor waart op en neit Kommando fir am däischteren Void vum Terminal aginn ze ginn ...

Source: will.com

Setzt e Commentaire