Falling Down Rabbit Hole: Istwa a nan yon echèk rechajman vèni - Pati 1

ghostinushanka, li te frape bouton yo pou 20 minit anvan yo kòm si lavi li te depann de li, li vire bò kote m 'ak yon gade semi-sovaj nan je l' ak yon souri sounwa - "Mezi, mwen panse mwen te resevwa li."

"Gade isit la," li di, lonje dwèt sou youn nan senbòl yo sou ekran an, "Mwen parye chapo wouj mwen an ke si nou ajoute isit la sa mwen sot voye ba ou," lonje dwèt sou yon lòt seksyon nan kòd, "erè a pa pral ankò. pral parèt."

Yon ti kras pè e fatige, mwen modifye ekspresyon sed nou t ap travay sou yon ti tan, sove fichye a epi kouri systemctl varnish reload. Mesaj erè a disparèt...

"Imel yo mwen echanje ak kandida a," kòlèg mwen an te kontinye, pandan y ap souri li te grandi nan yon souri otantik lajwa, "Li toudenkou parèt sou mwen ke sa a se egzakteman menm pwoblèm nan!"

Ki jan tout bagay te kòmanse

Atik la sipoze yon konpreyansyon sou fason bash, awk, sed ak systemd travay. Konesans nan vèni pi pito, men se pa obligatwa.
Timestamps nan snippets yo te chanje.
Ekri ak ghostinushanka.
Tèks sa a se yon tradiksyon orijinal ki te pibliye an Angle de semèn de sa; tradiksyon boikoden.

Solèy la klere nan fenèt panoramic yo nan yon lòt maten cho otòn, yon tas bwason ki fèk prepare ki gen anpil kafeyin repoze lwen klavye a, senfoni pi renmen ou nan son son nan kas ekoutè ou a, nwaye soti bruilement nan klavye mekanik, ak premye antre a. nan lis la nan tikè anreta sou tablo Kanban an jwe byen klere ak tit la fatal "Envestige varnishreload" sh: eko: I/O erè nan staging" (Envestige "varnishreload sh: eko: I/O erè" nan sèn). Lè li rive vèni, pa gen okenn plas pou erè, menm si yo pa lakòz okenn pwoblèm tankou nan ka sa a.

Pou moun ki pa abitye ak vèni chaje, sa a se yon senp script koki ki itilize pou rechaje konfigirasyon an vèni - yo rele tou VCL.

Kòm tit la nan tikè a sijere, erè a te fèt sou youn nan sèvè yo sou sèn nan, e depi mwen te asire w ke wout la vèni sou sèn nan te travay byen, mwen sipoze ke sa a ta dwe yon ti erè. Se konsa, jis yon mesaj ki te fini nan yon kouran pwodiksyon deja fèmen. Mwen pran tikè a pou tèt mwen, ak tout konfyans mwen pral make li pare nan mwens pase 30 minit, tape tèt mwen sou do a pou netwaye tablo a nan yon lòt fatra ankò epi retounen nan zafè ki pi enpòtan.

Kraze nan yon miray a 200 km / h

Louvri dosye a varnishreload, sou youn nan sèvè ki kouri Debian Stretch, mwen te wè yon script shell mwens pase 200 liy longè.

Èske w te pase nan script la, mwen pa t remake anyen ki ta ka lakòz pwoblèm lè w ap kouri li plizyè fwa dirèkteman nan tèminal la.

Apre yo tout, sa a se yon etap, menm si li kraze, pèsonn pa pral plenyen, byen ... pa twòp. Mwen kouri script la epi wè sa ki pral ekri nan tèminal la, men erè yo pa vizib ankò.

Yon koup plis kouri pou asire w ke mwen pa ka repwodui erè a san okenn efò adisyonèl, epi mwen kòmanse konnen ki jan yo chanje script sa a epi fè li toujou voye yon erè.

Èske script la ka depase STDOUT (itilize > &-)? Oswa STDERR? Okenn nan sa yo te travay nan fen an.

Aparamman systemd yon jan kanmenm modifye anviwònman an demaraj, men ki jan, e poukisa?
Mwen ouvri vim epi edite varnishreload, ajoute set -x dwa anba shebang la, espere ke pwodiksyon an debug nan script la pral koule kèk limyè.

Fichye a korije, Se konsa, mwen rechaje vèni ak wè ke chanjman an konplètman kraze tout bagay... Echapman an se yon dezòd konplè, nan ki gen tòn kòd ki tankou C. Menm defile nan tèminal la pa ase pou jwenn kote li kòmanse. Mwen konplètman konfonn. Èske mòd debogaj ka afekte operasyon pwogram ki lanse nan yon script? Non, se yon istwa san sans. Pinèz nan kokiy la? Plizyè senaryo posib ap kouri nan tèt mwen tankou ravèt nan diferan direksyon. Gode ​​bwason ki gen kafeyin la imedyatman vide, yon vwayaj rapid nan kwizin nan ranplir stock la ak ... ale nou ale. Mwen louvri script la epi pran yon gade pi pre nan shebang la: #!/bin/sh.

/bin/sh - sa a se jis yon lyen senbolik bash, kidonk script la entèprete nan mòd POSIX-konpatib, dwa? Se pa konsa! Koki default sou Debian se priz, e se egzakteman sa li sanble. refere /bin/sh.

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

Kòm yon tès, mwen chanje shebang la #!/bin/bash, efase set -x epi eseye ankò. Finalman, sou rdemare ki vin apre nan vèni, yon erè tolerab parèt nan pwodiksyon an:

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

Liy 124, men li!

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 }

Men, kòm li vire soti, liy 124 se byen vid epi li pa gen okenn enterè. Mwen te kapab sèlman asime ke erè a te fèt kòm yon pati nan yon fisèl multiliy kòmanse sou liy 116.
Ki sa ki finalman ekri nan varyab la? VCL_FILE kòm yon rezilta nan egzekite sub-koki ki anwo a?

Nan kòmansman an, li voye sa ki nan varyab la VLC_SHOW, ki te kreye sou liy 115, swiv kòmandman an nan tiyo a. Lè sa a, sa k ap pase la?

Premyèman, li se itilize la varnishadm, ki se yon pati nan pake enstalasyon vèni a, pou mete kanpe vèni san rekòmanse.

Sou-ekip vcl.show -v itilize pou pwodiksyon tout konfigirasyon VCL espesifye nan ${VCL_NAME}, pou STDOUT.

Pou montre aktyèl konfigirasyon VCL aktif la, ansanm ak plizyè vèsyon anvan konfigirasyon routage vèni ki toujou nan memwa, ou ka itilize kòmandman an. varnishadm vcl.list, pwodiksyon an ki pral sanble ak youn ki anba a:

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

Valè varyab ${VCL_NAME} enstale nan yon lòt pati nan script la varnishreload nan non VCL aktif kounye a, si gen youn. Nan ka sa a li pral "reload_20190101_120000_12397".

Gwo, varyab ${VCL_SHOW} gen konfigirasyon konplè pou vèni, klè pou kounye a. Koulye a, mwen finalman konprann poukisa pwodiksyon an priz se set -x te tounen soti yo dwe tèlman kase - li enkli sa ki nan konfigirasyon an ki kapab lakòz.

Li enpòtan pou w konprann ke yon konfigirasyon VCL konplè ka souvan pave ansanm nan plizyè dosye. Kòmantè C-style yo itilize pou idantifye kote sèten fichye konfigirasyon yo te enkli nan lòt moun, e se sa ki liy sa a nan fragment kòd se tout sou.
Sentaks pou kòmantè ki dekri dosye enkli yo se nan fòma sa a:

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

Nimewo yo pa enpòtan nan kontèks sa a, nou enterese nan non dosye a.

Ki sa ki finalman rive nan marekaj la nan kòmandman kòmanse sou liy 116?
Ann kalkile li.
Ekip la konsiste de kat pati:

  1. Senp echo, ki enprime valè varyab la ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk, ki chèche yon liy (dosye) kote premye jaden an, apre yo fin kraze tèks la, se "//", ak dezyèm lan se "VCL.SHOW".
    Awk pral ekri premye liy ki koresponn ak modèl sa yo epi li pral sispann travay imedyatman.

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. Yon blòk kòd ki estoke valè jaden an senk varyab, separe pa espas. Senkyèm varyab FILE resevwa rès liy lan. Finalman, dènye eko ekri sa ki nan varyab la ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. Depi tout etap 1 a 3 yo fèmen nan yon subshell, pwodiksyon valè a $FILE pral ekri nan yon varyab VCL_FILE.

Jan kòmantè a sou liy 119 sijere, sa a sèvi sèlman objektif la nan jere seryezman ka kote VCL pral referans dosye ak espas nan non yo.

Mwen te fè kòmantè sou lojik pwosesis orijinal la pou ${VCL_FILE} epi yo te eseye chanje sekans lòd la, men li pa t 'mennen nan anyen. Tout bagay te travay byen pou mwen, men lè mwen te kòmanse sèvis la li te bay yon erè.

Li sanble ke erè a se tou senpleman pa repwodiktif lè w ap kouri script la manyèlman, pandan y ap sipoze 30 minit yo te deja ekspire sis fwa epi, anplis, yon travay ki pi wo priyorite te parèt, pouse lòt zafè sou kote. Rès semèn nan te ranpli ak yon varyete travay epi li te sèlman yon ti kras dilye pa yon rapò sou sed ak yon entèvyou ak yon kandida. Pwoblèm ak erè nan varnishreload te irevokabl pèdi nan sab yo nan tan.

Sa yo rele ou sed-fu... se aktyèlman... fatra

Semèn kap vini an mwen te gen yon jou san patipri gratis, kidonk mwen te deside atake tikè sa a ankò. Mwen te espere ke nan sèvo mwen an, kèk pwosesis background te ap chèche pou yon solisyon a pwoblèm sa a pandan tout tan sa a, ak fwa sa a mwen ta definitivman konprann sa k ap pase.

Depi tou senpleman chanje kòd la pa ede dènye fwa, mwen jis deside reekri li kòmanse nan liy 116. Nan nenpòt ka, kòd ki deja egziste a te estipid. Epi pa gen absoliman pa bezwen sèvi ak li read.

Gade erè a ankò:
sh: echo: broken pipe — eko parèt nan de kote nan lòd sa a, men mwen sispèk ke premye a se koupab ki gen plis chans (oswa omwen yon konplis). Awk pa enspire konfyans tou. Ak nan ka li vrèman se awk | {read; echo} konsepsyon an mennen nan tout pwoblèm sa yo, poukisa pa ranplase li? Kòmand yon sèl-liy sa a pa sèvi ak tout karakteristik yo nan awk, e menm yon sèl siplemantè sa a read an plis.

Depi semèn pase a te gen yon rapò sou sed, Mwen te vle eseye konpetans mwen fèk akeri epi senplifye echo | awk | { read; echo} nan yon pi konprann echo | sed. Pandan ke sa a se definitivman pa apwòch ki pi bon yo idantifye ensèk la, mwen te panse mwen ta omwen eseye sed-fu mwen an e petèt aprann yon bagay nouvo sou pwoblèm nan. Sou wout la, mwen te mande kòlèg mwen an, otè diskou sed la, pou ede m vini ak yon script sed ki pi efikas.

Mwen lage kontni an varnishadm vcl.show -v "$VCL_NAME" nan yon fichye, konsa mwen te kapab konsantre sou ekri script sed san okenn konplikasyon nan rdemare sèvis.

Ou ka jwenn yon deskripsyon kout sou egzakteman ki jan sed pwosesis opinyon ka jwenn nan manyèl GNU li a. Nan sous yo sed senbòl la n espesifye klèman kòm yon separasyon liy.

Nan plizyè pas ak rekòmandasyon kòlèg mwen an, nou te ekri yon script sed ki te bay menm rezilta ak tout liy orijinal 116 la.

Anba a se yon echantiyon fichye ak done antre:

> 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

Sa a ka pa evidan nan deskripsyon ki anwo a, men nou sèlman enterese nan premye kòmantè a // VCL.SHOW, epi ka gen plizyè nan yo nan done yo antre. Se poutèt sa awk orijinal la fini apre premye match la.

# шаг первый, вывести только строки с комментариями
# используя возможности 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

Se konsa, sa ki nan script varnishreload la pral gade yon bagay tankou sa a:

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

Lojik ki anwo a ka eksprime yon ti tan jan sa a:
Si fisèl la matche ak yon ekspresyon regilye // VCL.SHOW, Lè sa a, devore visye tèks ki gen ladan tou de nimewo nan liy sa a, epi sove tout sa ki rete apre operasyon sa a. Emèt valè ki estoke a epi fini pwogram nan.

Senp, pa vre?

Nou te kontan ak script sed ak lefèt ke li ranplase tout kòd orijinal la. Tout tès mwen yo te bay rezilta yo vle, se konsa mwen chanje "varnishreload" sou sèvè a epi kouri li ankò. systemctl reload varnish. Move erè echo: write error: Broken pipe ri nan figi nou ankò. Kursè a ap tann pou yon nouvo lòd yo dwe antre nan vid la fè nwa nan tèminal la ...

Sous: www.habr.com

Add nouvo kòmantè