Pagkahulog sa Buntag sa Kuneho: Ang Istorya sa Usa ka Varnish Reload Failure - Bahin 1

ghostinushanka, nga nagpalayo sa mga butones sa miaging 20 ka minuto nga ingon og ang iyang kinabuhi nagdepende niini, milingi kanako uban sa usa ka semi-wild nga pagtan-aw sa iyang mga mata ug usa ka maliputon nga ngisi - "Dude, sa akong hunahuna nakuha ko kini."

“Tan-awa dinhi,” siya miingon, nga nagtudlo sa usa sa mga simbolo sa screen, “Akong gipusta ang akong pula nga kalo nga kon atong idugang dinhi ang akong gipadala kanimo,” nagtudlo sa laing seksyon sa code, “ang sayop dili na ipakita.”

Medyo nalibog ug gikapoy, giusab nako ang sed nga ekspresyon nga among gitrabaho sa makadiyot, i-save ang file ug dagan systemctl varnish reload. Ang mensahe sa sayop nawala...

“Ang mga email nga akong gibaylo sa kandidato,” mipadayon ang akong kauban, samtang ang iyang ngisi mitubo ngadto sa usa ka tinuod nga pahiyom sa kalipay, “Kalit lang nga misantop sa akong hunahuna nga mao ra kini ang problema!”

Giunsa kini tanan

Ang artikulo adunay pagsabut kung giunsa ang bash, awk, sed ug systemd nagtrabaho. Ang kahibalo sa barnis gipalabi, apan dili gikinahanglan.
Ang mga timestamp sa mga snippet giusab.
Gisulat sa ghostinushanka.
Kini nga teksto usa ka hubad sa orihinal nga gipatik sa English duha ka semana ang milabay; paghubad boikoden.

Ang adlaw midan-ag sa panoramic nga mga bintana sa lain na usab nga mainit nga buntag sa tingdagdag, usa ka tasa sa bag-ong giandam nga ilimnon nga puno sa caffeine gikan sa keyboard, ang imong paborito nga symphony sa mga tunog nga tunog sa imong mga headphone, naglumos sa kasikas sa mekanikal nga mga keyboard, ug ang una nga pagsulod. sa listahan sa mga backlog ticket sa Kanban board playfully nagdan-ag uban sa makamatay nga titulo "Imbistigasyon varnishreload" sh: echo: I/O error sa staging" (Imbistiga "varnishreload sh: echo: I/O error" sa dula). Kung bahin sa barnis, adunay ug dili mahimo nga bisan unsang lugar alang sa mga sayup, bisan kung dili kini moresulta sa bisan unsang mga problema sama sa kini nga kaso.

Para sa mga dili pamilyar varnishreload, kini usa ka yano nga shell script nga gigamit sa pag-reload sa configuration barnis - gitawag usab nga VCL.

Sama sa gisugyot sa titulo sa tiket, ang sayup nahitabo sa usa sa mga server sa entablado, ug tungod kay sigurado ako nga ang pag-ruta sa barnis sa entablado nagtrabaho sa husto, akong gihunahuna nga kini usa ka gamay nga sayup. Busa, usa lang ka mensahe nga natapos sa usa ka sirado na nga output stream. Gikuha nako ang tiket alang sa akong kaugalingon, sa bug-os nga pagsalig nga markahan ko kini nga andam sa wala’y 30 minuto, pikpik ang akong likod sa paglimpyo sa board sa lain na usab nga basura ug mobalik sa labi ka hinungdanon nga mga butang.

Pagbangga sa bungbong sa 200 km/h

Pag-abli sa file varnishreload, sa usa sa mga server nga nagpadagan sa Debian Stretch, nakakita ko og shell script nga wala pay 200 ka linya ang gitas-on.

Sa pag-agi sa script, wala ako nakamatikod sa bisan unsang butang nga mahimong moresulta sa mga problema kung magdagan kini daghang beses direkta gikan sa terminal.

Tuod man, kini usa ka yugto, bisan kung kini maguba, wala’y moreklamo, aw.. dili kaayo. Gipadagan nako ang script ug tan-awon kung unsa ang isulat sa terminal, apan ang mga sayup dili na makita.

Ang usa ka magtiayon nga dugang nga nagdagan aron masiguro nga dili nako makopya ang sayup nga wala’y dugang nga paningkamot, ug nagsugod ako sa paghunahuna kung giunsa pag-usab kini nga script ug himuon kini nga sayup.

Mahimo bang i-override sa script ang STDOUT (gamit > &-)? O STDERR? Walay usa niini nga nagtrabaho sa katapusan.

Dayag nga gibag-o sa systemd ang palibot sa pagsugod, apan giunsa, ug ngano?
Giablihan nako ang vim ug gi-edit varnishreload, midugang set -x sa ilawom mismo sa shebang, nanghinaut nga ang pag-debug nga output sa script maghatag gamay nga kahayag.

Gitul-id ang file, mao nga gi-reload nako ang barnis ug nakita nga ang pagbag-o hingpit nga nakaguba sa tanan ... Ang tambutso usa ka kompleto nga kagubot, diin adunay mga tonelada nga C-like code. Bisan ang pag-scroll sa terminal dili igo aron makit-an kung diin kini magsugod. Naglibog gyud ko. Makaapektar ba ang debugging mode sa operasyon sa mga programa nga gilusad sa usa ka script? Dili, kini walay pulos. Bug sa kabhang? Daghang posible nga mga senaryo ang nagdagan sa akong ulo sama sa mga uk-ok sa lainlaing direksyon. Ang kopa sa caffeinated nga ilimnon diha-diha dayon nahaw-as, usa ka dali nga pagbiyahe ngadto sa kusina aron mapuno ang stock ug ... Giablihan nako ang script ug gitan-aw pag-ayo ang shebang: #!/bin/sh.

/bin/sh - kini usa lamang ka symlink sa bash, mao nga ang script gihubad sa POSIX-compatible mode, di ba? Dili kaayo! Ang default shell sa Debian kay dash, ug mao gyud kana ang hitsura niini. nagpasabut /bin/sh.

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

Isip pagsulay, giilisan nako ang shebang sa #!/bin/bash, gitangtang set -x ug misulay pag-usab. Sa katapusan, sa sunod nga pag-reboot sa barnis, usa ka maagwanta nga sayup ang nagpakita sa output:

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

Linya 124, ania na!

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 }

Apan ingon sa nahibal-an, ang linya 124 medyo walay sulod ug walay interes. Mahimo ra nako nga hunahunaon nga ang sayup nahitabo ingon bahin sa usa ka multiline string nga nagsugod sa linya 116.
Unsa ang katapusan nga gisulat sa variable? VCL_FILE isip resulta sa pagpatuman sa sub-shell sa ibabaw?

Sa sinugdanan, kini nagpadala sa mga sulod sa variable VLC_SHOW, gihimo sa linya 115, nga nagsunod sa mando pinaagi sa tubo. Ug unya unsay mahitabo didto?

Una, kini gigamit didto varnishadm, nga bahin sa pakete sa pag-instalar sa barnis, alang sa pag-set up sa barnis nga wala mag-restart.

Sub-team vcl.show -v gigamit sa pag-output sa tibuok nga configuration sa VCL nga gipiho sa ${VCL_NAME}, sa STDOUT.

Aron ipakita ang kasamtangan nga aktibo nga configuration sa VCL, ingon man usab ang pipila ka mga naunang bersyon sa varnish routing configurations nga anaa pa sa memorya, mahimo nimong gamiton ang command varnishadm vcl.list, ang output niini mahimong susama sa usa sa ubos:

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

Variable nga bili ${VCL_NAME} gi-install sa laing bahin sa script varnishreload sa ngalan sa kasamtangan nga aktibo nga VCL, kung adunay usa. Niini nga kaso kini mahimong "reload_20190101_120000_12397".

Nindot, variable ${VCL_SHOW} naglangkob sa kompleto nga configuration alang sa barnis, tin-aw alang sa karon. Karon nahibal-an na nako kung ngano nga ang output sa dash set -x nahimo nga nabuak kaayo - kini naglakip sa mga sulod sa resulta nga configuration.

Mahinungdanon nga masabtan nga ang usa ka kompleto nga pag-configure sa VCL mahimong kanunay nga gihiusa gikan sa daghang mga file. Ang mga komento sa estilo sa C gigamit aron mahibal-an kung diin gilakip ang pipila nga mga file sa pag-configure sa uban, ug kana ang gipasabut sa mosunod nga linya sa snippet sa code.
Ang syntax alang sa mga komentaryo nga naghulagway sa gilakip nga mga file anaa sa mosunod nga pormat:

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

Ang mga numero dili hinungdanon sa kini nga konteksto, interesado kami sa ngalan sa file.

Unsa ang katapusan nga mahitabo sa swamp sa mga sugo sugod sa linya 116?
Atong isipon kini.
Ang team naglangkob sa upat ka bahin:

  1. Yano echo, nga nag-imprinta sa bili sa variable ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk, nga mangita og linya (record) diin ang unang field, human maputol ang text, mao ang “//”, ug ang ikaduha mao ang “VCL.SHOW”.
    Isulat sa Awk ang una nga linya nga katumbas sa kini nga mga sumbanan ug dayon hunongon ang pagproseso dayon.

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. Usa ka bloke sa code nga nagtipig sa mga kantidad sa uma sa lima ka mga variable, nga gibulag sa mga luna. Ang ikalima nga FILE variable makadawat sa nahabilin nga linya. Sa katapusan, ang katapusan nga echo nagsulat sa mga sulod sa variable ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. Tungod kay ang tanan nga mga lakang 1 hangtod 3 gilakip sa usa ka subshell, nga nagpagawas sa kantidad $FILE isulat sa usa ka variable VCL_FILE.

Sama sa gisugyot sa komento sa linya 119, nagsilbi kini nga katuyoan sa kasaligan nga pagdumala sa mga kaso diin ang VCL mag-refer sa mga file nga adunay mga espasyo sa ilang mga ngalan.

Gikomentaryo nako ang orihinal nga lohika sa pagproseso alang sa ${VCL_FILE} ug misulay sa pag-usab sa han-ay sa sugo, apan wala kini mosangpot sa bisan unsa. Ang tanan nagtrabaho pag-ayo alang kanako, apan sa diha nga ako nagsugod sa serbisyo naghatag kini usa ka sayup.

Ingon og ang sayup dili na mabag-o kung mano-mano ang pagpadagan sa script, samtang ang giingon nga 30 minuto na-expire na sa unom ka beses ug, dugang pa, usa ka mas taas nga prayoridad nga buluhaton ang nagpakita, nga gisalikway ang ubang mga butang. Ang nahabilin sa semana napuno sa lain-laing mga buluhaton ug gamay ra nga natunaw sa usa ka taho sa sed ug usa ka interbyu sa usa ka kandidato. Problema sa error sa varnishreload dili na mabawi nga nawala sa mga balas sa panahon.

Ang imong gitawag nga sed-fu... sa tinuod... basura

Pagkasunod semana aduna koy usa ka medyo libre nga adlaw, mao nga nakahukom ko nga atubangon kini nga tiket pag-usab. Nanghinaut ko nga sa akong utok, ang pipila ka proseso sa background nangita alang sa usa ka solusyon sa kini nga problema sa tanan niini nga panahon, ug niining higayona siguradong masabtan nako kung unsa ang nahitabo.

Tungod kay ang pagbag-o lang sa code wala makatabang sa miaging higayon, nakahukom na lang ko nga isulat kini pag-usab sugod sa linya 116. Sa bisan unsa nga kaso, ang kasamtangan nga code kay hungog. Ug dili na kinahanglan nga gamiton kini read.

Pagtan-aw sa sayup pag-usab:
sh: echo: broken pipe — echo makita sa duha ka mga dapit niini nga sugo, apan ako nagduda nga ang una mao ang mas lagmit nga hinungdan (o sa labing menos usa ka kakunsabo). Awk dili man makadasig ug kumpiyansa. Ug kung mao gyud awk | {read; echo} ang disenyo nagdala sa tanan niini nga mga problema, nganong dili kini pulihan? Kini nga usa ka linya nga mando wala mogamit sa tanan nga mga bahin sa awk, ug bisan kini nga dugang read dugang pa.

Sukad sa miaging semana adunay report sa sed, Gusto nakong sulayan ang akong bag-ong naangkon nga mga kahanas ug pasimplehon echo | awk | { read; echo} ngadto sa mas masabtan echo | sed. Bisan kung kini siguradong dili ang labing kaayo nga pamaagi sa pag-ila sa bug, naghunahuna ko nga labing menos sulayan nako ang akong sed-fu ug tingali makakat-on og bag-o bahin sa problema. Sa dalan, akong gihangyo ang akong kauban, ang tagsulat sa sed talk, sa pagtabang kanako sa paghimo sa usa ka mas episyente nga sed script.

Gihulog nako ang sulod varnishadm vcl.show -v "$VCL_NAME" sa usa ka file, aron ako maka-focus sa pagsulat sa sed script nga walay bisan unsa nga kahasol sa pag-reboot sa serbisyo.

Usa ka mubo nga paghulagway sa eksakto kung giunsa ang sed nga mga proseso sa input makit-an sa iyang GNU nga manwal. Sa sed tinubdan ang simbolo n tin-aw nga gipiho isip usa ka separator sa linya.

Sa daghang mga pass ug sa mga rekomendasyon sa akong kauban, nagsulat kami usa ka sed script nga naghatag parehas nga sangputanan sa tibuuk nga orihinal nga linya 116.

Sa ubos usa ka sample file nga adunay input data:

> 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

Mahimong dili kini dayag gikan sa paghulagway sa ibabaw, apan kami interesado lamang sa unang komento // VCL.SHOW, ug mahimong adunay daghan niini sa input data. Mao kini ang hinungdan nga ang orihinal nga awk matapos human sa unang duwa.

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

Mao nga, ang sulud sa script sa varnishreload ingon niini:

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

Ang labaw nga lohika mahimong ipahayag sa mubo ingon sa mosunod:
Kung ang hilo motakdo sa usa ka regular nga ekspresyon // VCL.SHOW, unya hakog nga lamyon ang teksto nga naglakip sa duha ka numero niini nga linya, ug tipigi ang tanan nga nahibilin human niini nga operasyon. Ipagawas ang gitipigan nga bili ug tapuson ang programa.

Simple, dili ba?

Nalipay kami sa sed script ug sa kamatuoran nga gipulihan niini ang tanan nga orihinal nga code. Ang tanan nakong mga pagsulay naghatag sa gitinguha nga mga resulta, mao nga akong giusab ang "varnishreload" sa server ug gipadagan kini pag-usab systemctl reload varnish. Daotan nga sayop echo: write error: Broken pipe nangatawa pag-usab sa among mga nawong. Ang nagpangidlap nga cursor naghulat alang sa usa ka bag-ong sugo nga ipasulod sa ngitngit nga kahaw-ang sa terminal...

Source: www.habr.com

Idugang sa usa ka comment