Kuanguka Chini kwenye Shimo la Sungura: Hadithi ya Kushindwa Kupakia upya Varnish Moja - Sehemu ya 1

ghostinushanka, baada ya kugonga vifungo kwa dakika 20 zilizopita kana kwamba maisha yake yanategemea, ananigeukia na sura ya porini machoni pake na tabasamu la ujanja - "Jamani, nadhani nimepata."

"Angalia hapa," anasema, akionyesha moja ya alama kwenye skrini, "naweka dau kofia yangu nyekundu kwamba ikiwa tutaongeza hapa nilichokutumia hivi punde," akionyesha sehemu nyingine ya nambari, "kosa halitakuwa tena. itaonyeshwa."

Nikiwa nimechanganyikiwa kidogo na nimechoka, ninarekebisha usemi wa sed ambao tumekuwa tukifanya kazi nao kwa muda, hifadhi faili na kukimbia. systemctl varnish reload. Ujumbe wa hitilafu umetoweka...

"Barua pepe nilizobadilishana na mgombea," mwenzangu aliendelea, huku tabasamu lake likizidi kuwa tabasamu la furaha, "Ghafla ilinijia kwamba hili ni shida sawa kabisa!"

Jinsi yote yalianza

Nakala hiyo inachukua uelewa wa jinsi bash, awk, sed na systemd inavyofanya kazi. Ujuzi wa varnish unapendekezwa, lakini hauhitajiki.
Mihuri ya muda katika vijisehemu imebadilishwa.
Imeandikwa na ghostinushanka.
Maandishi haya ni tafsiri ya asili iliyochapishwa kwa Kiingereza wiki mbili zilizopita; tafsiri boikoden.

Jua huangaza kupitia madirisha ya mandhari asubuhi nyingine yenye joto la vuli, kikombe cha kinywaji kipya kilichotayarishwa chenye kafeini hukaa mbali na kibodi, sauti zako unazozipenda zaidi husikika kwenye vipokea sauti vyako vinavyobanwa kichwani, na kuzima sauti ya kibodi za mitambo, na kiingilio cha kwanza. katika orodha ya tiketi zilizosalia kwenye ubao wa Kanban inang'aa kwa uchezaji na mada ya kutisha "Chunguza upakiaji upya wa varnish" sh: echo: hitilafu ya I/O katika kupanga" (Chunguza "varnishreload sh: echo: hitilafu ya I/O" kwenye jukwaa). Linapokuja suala la varnish, kuna na haiwezi kuwa na nafasi yoyote ya makosa, hata ikiwa hayasababishi shida yoyote kama ilivyo katika kesi hii.

Kwa wale ambao hawajui upakiaji upya wa varnish, hii ni hati rahisi ya ganda inayotumiwa kupakia upya usanidi varnish - pia inaitwa VCL.

Kama kichwa cha tikiti kinapendekeza, hitilafu ilitokea kwenye seva moja kwenye hatua, na kwa kuwa nilikuwa na uhakika kwamba uelekezaji wa varnish kwenye jukwaa ulikuwa ukifanya kazi ipasavyo, nilidhani kuwa hili lingekuwa kosa dogo. Kwa hivyo, ujumbe tu ambao uliishia kwenye mkondo wa kutoa ambao tayari umefungwa. Ninajichukulia tikiti, nikiwa na imani kamili kwamba nitaiweka alama kuwa tayari katika muda usiozidi dakika 30, nikijipigapiga mgongoni kwa ajili ya kuondoa ubao wa takataka nyingine na kurudi kwenye mambo muhimu zaidi.

Kugonga ukuta kwa kasi ya kilomita 200 kwa saa

Kufungua faili varnishreload, kwenye moja ya seva zinazoendesha Debian Stretch, niliona hati ya ganda chini ya mistari 200 kwa urefu.

Baada ya kupitia maandishi, sikugundua chochote ambacho kinaweza kusababisha shida wakati wa kuiendesha mara kadhaa moja kwa moja kutoka kwa terminal.

Baada ya yote, hii ni hatua, hata ikivunja, hakuna mtu atakayelalamika, vizuri ... sio sana. Ninaendesha maandishi na kuona kitakachoandikwa kwa terminal, lakini makosa hayaonekani tena.

Wanandoa zaidi hukimbia ili kuhakikisha kuwa siwezi kuzaliana tena kosa bila juhudi zozote za ziada, na ninaanza kufikiria jinsi ya kubadilisha hati hii na kuifanya bado itupe makosa.

Hati inaweza kubatilisha STDOUT (kwa kutumia > &-)? Au STDERR? Hakuna kati ya hizi zilizofanya kazi mwishoni.

Inavyoonekana systemd kwa njia fulani hurekebisha mazingira ya kuanza, lakini vipi, na kwa nini?
Ninafungua vim na kuhariri varnishreload, kuongeza set -x chini ya shebang, kwa matumaini kwamba matokeo ya utatuzi wa hati yatatoa mwanga.

Faili imesahihishwa, kwa hiyo ninapakia tena varnish na kuona kwamba mabadiliko yalivunja kabisa kila kitu ... Kutolea nje ni fujo kamili, ambayo kuna tani za msimbo wa C. Hata kusongesha kwenye terminal haitoshi kupata inaanzia wapi. Nimechanganyikiwa kabisa. Je, hali ya utatuzi inaweza kuathiri utendakazi wa programu zilizozinduliwa katika hati? Hapana, ni upuuzi. Mdudu kwenye ganda? Matukio kadhaa yanayowezekana yanapita kichwani mwangu kama mende katika mwelekeo tofauti. Kikombe cha kinywaji kilicho na kafeini huondolewa papo hapo, safari ya haraka ya jikoni ili kujaza hisa na ... tunaenda. Ninafungua maandishi na kuangalia kwa karibu shebang: #!/bin/sh.

/bin/sh - huu ni ulinganifu tu wa bash, kwa hivyo hati inatafsiriwa katika hali inayolingana ya POSIX, sivyo? Sivyo! Kamba chaguo-msingi kwenye Debian ni dashi, na ndivyo inavyoonekana. inahusu /bin/sh.

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

Kama mtihani, nilibadilisha shebang kuwa #!/bin/bash, imefutwa set -x na kujaribu tena. Mwishowe, baada ya kuwasha tena varnish, hitilafu inayoweza kuvumiliwa ilionekana kwenye matokeo:

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

Mstari wa 124, hii hapa!

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 }

Lakini kama inavyogeuka, mstari wa 124 hauna kitu na hauna riba. Ningeweza tu kudhani kuwa hitilafu ilitokea kama sehemu ya kamba ya multiline kuanzia kwenye mstari wa 116.
Ni nini hatimaye imeandikwa kwa kutofautiana? VCL_FILE kama matokeo ya kutekeleza ganda ndogo hapo juu?

Mwanzoni, hutuma yaliyomo ya kutofautisha VLC_SHOW, iliyoundwa kwenye mstari wa 115, kufuata amri kupitia bomba. Na kisha nini kinatokea huko?

Kwanza, hutumiwa hapo varnishadm, ambayo ni sehemu ya mfuko wa ufungaji wa varnish, kwa ajili ya kuanzisha varnish bila kuanzisha upya.

Timu ndogo vcl.show -v inayotumika kutoa usanidi mzima wa VCL ulioainishwa ndani ${VCL_NAME}, kwa STDOUT.

Ili kuonyesha usanidi wa sasa wa VCL, pamoja na matoleo kadhaa ya awali ya usanidi wa uelekezaji wa varnish ambayo bado iko kwenye kumbukumbu, unaweza kutumia amri. varnishadm vcl.list, matokeo ambayo yatakuwa sawa na yaliyo hapa chini:

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

Thamani inayobadilika ${VCL_NAME} imewekwa katika sehemu nyingine ya hati varnishreload kwa jina la VCL inayotumika kwa sasa, ikiwa ipo. Katika kesi hii itakuwa "reload_20190101_120000_12397".

Kubwa, kutofautiana ${VCL_SHOW} ina usanidi kamili wa varnish, wazi kwa sasa. Sasa hatimaye ninaelewa kwa nini matokeo ya dashi ni set -x iligeuka kuwa imevunjwa sana - ilijumuisha yaliyomo kwenye usanidi unaosababisha.

Ni muhimu kuelewa kwamba usanidi kamili wa VCL mara nyingi unaweza kuunganishwa kutoka kwa faili kadhaa. Maoni ya mtindo wa C hutumiwa kutambua mahali faili fulani za usanidi zimejumuishwa katika zingine, na hiyo ndiyo maana ya mstari ufuatao wa kijisehemu cha msimbo.
Sintaksia ya maoni yanayoelezea faili zilizojumuishwa iko katika muundo ufuatao:

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

Nambari sio muhimu katika muktadha huu, tunavutiwa na jina la faili.

Ni nini hatimaye hufanyika katika bwawa la amri kuanzia mstari wa 116?
Hebu tuone.
Timu ina sehemu nne:

  1. Rahisi echo, ambayo huchapisha thamani ya kutofautisha ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk, ambayo hutafuta mstari (rekodi) ambapo sehemu ya kwanza, baada ya kuvunja maandishi, ni "//", na ya pili ni "VCL.SHOW".
    Awk itaandika mstari wa kwanza unaolingana na mifumo hii na kisha itaacha kuchakata mara moja.

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. Kizuizi cha msimbo ambacho huhifadhi thamani za uga katika vijiwezo vitano, vinavyotenganishwa na nafasi. Tofauti ya tano ya FILE inapokea safu iliyobaki. Mwishowe, mwangwi wa mwisho huandika yaliyomo kwenye kutofautisha ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. Kwa kuwa hatua zote 1 hadi 3 zimefungwa kwa ganda ndogo, ikitoa thamani $FILE itaandikwa kwa kutofautiana VCL_FILE.

Kama maoni kwenye mstari wa 119 yanavyopendekeza, hii inatumika kwa madhumuni pekee ya kushughulikia kesi kwa uaminifu ambapo VCL itarejelea faili zilizo na nafasi katika majina yao.

Nimetoa maoni juu ya mantiki asilia ya usindikaji ${VCL_FILE} na kujaribu kubadilisha mlolongo wa amri, lakini haikuongoza kwa chochote. Kila kitu kilinifanyia kazi vizuri, lakini nilipoanza huduma ilitoa makosa.

Inaonekana kwamba kosa haliwezi kuzalishwa tena wakati wa kuendesha hati kwa mikono, wakati dakika 30 zinazofikiriwa tayari zimeisha mara sita na, kwa kuongeza, kazi ya kipaumbele cha juu imeonekana, kusukuma mambo mengine kando. Wiki iliyobaki ilijazwa na kazi mbalimbali na ilipunguzwa kidogo tu na ripoti ya sed na mahojiano na mgombea. Tatizo la hitilafu katika varnishreload ilipotea kabisa katika mchanga wa wakati.

Kinachoitwa sed-fu... ni... takataka

Wiki iliyofuata nilikuwa na siku moja bila malipo, kwa hivyo niliamua kushughulikia tikiti hii tena. Nilitumaini kwamba katika ubongo wangu, mchakato fulani wa usuli ulikuwa ukitafuta suluhisho la tatizo hili wakati huu wote, na wakati huu bila shaka ningeelewa kinachoendelea.

Kwa kuwa kubadilisha nambari tu haikusaidia mara ya mwisho, niliamua tu kuiandika upya kuanzia mstari wa 116. Kwa hali yoyote, kanuni iliyopo ilikuwa ya kijinga. Na hakuna haja kabisa ya kuitumia read.

Kuangalia kosa tena:
sh: echo: broken pipe - echo inaonekana katika sehemu mbili katika amri hii, lakini ninashuku kuwa ya kwanza ndiye mkosaji anayewezekana (au angalau mshirika). Awk haihimizi imani pia. Na ikiwa ni kweli awk | {read; echo} kubuni husababisha matatizo haya yote, kwa nini usiibadilishe? Amri hii ya mstari mmoja haitumii vipengele vyote vya awk, na hata hii ya ziada read zaidi ya hayo.

Tangu wiki iliyopita kulikuwa na ripoti ya sed, nilitaka kujaribu ujuzi wangu mpya na kurahisisha echo | awk | { read; echo} katika kueleweka zaidi echo | sed. Ingawa hii sio njia bora ya kutambua mdudu, nilidhani ningejaribu sed-fu yangu na labda nijifunze kitu kipya juu ya shida. Njiani, nilimuuliza mwenzangu, mwandishi wa sed talk, anisaidie kupata hati bora zaidi ya sed.

Niliacha yaliyomo varnishadm vcl.show -v "$VCL_NAME" kwa faili, kwa hivyo ningeweza kuzingatia kuandika hati ya sed bila shida yoyote ya kuanza tena huduma.

Maelezo mafupi ya jinsi sed michakato ya kuingiza inaweza kupatikana ndani mwongozo wake wa GNU. Katika vyanzo vya sed ishara n imebainishwa kwa uwazi kama kitenganishi cha mstari.

Katika kupita kadhaa na kwa mapendekezo ya mwenzangu, tuliandika hati ya sed ambayo ilitoa matokeo sawa na mstari mzima wa 116.

Ifuatayo ni sampuli ya faili iliyo na data ya kuingiza:

> 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

Hii inaweza kuwa dhahiri kutoka kwa maelezo hapo juu, lakini tunavutiwa tu na maoni ya kwanza // VCL.SHOW, na kunaweza kuwa na kadhaa kati yao kwenye data ya ingizo. Hii ndio sababu awk ya asili inaisha baada ya mechi ya kwanza.

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

Kwa hivyo, yaliyomo kwenye hati ya upakiaji wa varnish itaonekana kitu kama hiki:

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

Mantiki hapo juu inaweza kuelezewa kwa ufupi kama ifuatavyo:
Ikiwa mfuatano unalingana na usemi wa kawaida // VCL.SHOW, kisha kwa pupa umeza maandishi ambayo yanajumuisha nambari zote mbili kwenye mstari huu, na uhifadhi kila kitu kinachosalia baada ya operesheni hii. Toa thamani iliyohifadhiwa na umalize programu.

Rahisi, sivyo?

Tulifurahishwa na hati ya sed na ukweli kwamba ilibadilisha nambari zote za asili. Vipimo vyangu vyote vilitoa matokeo yaliyohitajika, kwa hivyo nilibadilisha "varnishreload" kwenye seva na kuiendesha tena. systemctl reload varnish. Makosa mabaya echo: write error: Broken pipe alicheka katika nyuso zetu tena. Mshale unaokonyeza macho ulikuwa ukingoja amri mpya iingizwe katika utupu wa giza wa terminal...

Chanzo: mapenzi.com

Kuongeza maoni