“Edrychwch yma,” meddai, gan bwyntio at un o'r symbolau ar y sgrin, “Fe wnes i fetio fy het goch, os ydyn ni'n ychwanegu yma yr hyn rydw i newydd ei anfon atoch chi,” gan bwyntio at adran arall o'r cod, “ni fydd y gwall bellach. yn cael ei arddangos."
Ychydig yn ddryslyd ac wedi blino, rwy'n addasu'r mynegiant sed rydyn ni wedi bod yn gweithio arno ers tro, cadw'r ffeil a rhedeg systemctl varnish reload
. Mae'r neges gwall wedi diflannu...
“Y negeseuon e-bost y gwnes i eu cyfnewid â’r ymgeisydd,” parhaodd fy nghydweithiwr, wrth i’w wên dyfu’n wên o lawenydd gwirioneddol, “Gwawriodd arnaf yn sydyn mai’r un broblem yn union yw hon!”
Sut y dechreuodd y cyfan
Mae'r erthygl yn rhagdybio dealltwriaeth o sut mae bash, awk, sed a systemd yn gweithio. Mae gwybodaeth am farnais yn well, ond nid yw'n ofynnol.
Mae stampiau amser mewn pytiau wedi'u newid.
Ysgrifennwyd gyda
Mae'r testun hwn yn gyfieithiad o'r gwreiddiol a gyhoeddwyd yn Saesneg bythefnos yn ôl; cyfieithiad
Mae'r haul yn tywynnu trwy'r ffenestri panoramig ar fore hydref cynnes arall, paned o ddiod llawn caffein wedi'i baratoi'n ffres yn gorffwys i ffwrdd o'r bysellfwrdd, mae'ch hoff symffoni o symffoni yn swnio yn eich clustffonau, yn boddi siffrwd allweddellau mecanyddol, a'r cofnod cyntaf yn y rhestr o docynnau ôl-groniad ar fwrdd Kanban yn disgleirio’n chwareus gyda’r teitl tyngedfennol “Ymchwilio i varnishreload” sh: adlais: gwall I/O wrth lwyfannu” (Archwiliwch “varnishreload sh: adlais: gwall I/O” yn y llwyfannu). O ran farnais, mae ac ni all fod unrhyw le i wallau, hyd yn oed os nad ydynt yn arwain at unrhyw broblemau fel yn yr achos hwn.
Ar gyfer y rhai nad ydynt yn gyfarwydd â
Fel y mae teitl y tocyn yn ei awgrymu, digwyddodd y gwall ar un o'r gweinyddwyr ar y llwyfan, a chan fy mod yn siŵr bod y llwybriad farnais ar y llwyfan yn gweithio'n iawn, cymerais mai camgymeriad bach fyddai hwn. Felly, dim ond neges a ddaeth i ben mewn ffrwd allbwn sydd eisoes wedi'i chau. Cymeraf y tocyn i mi fy hun, yn gwbl hyderus y byddaf yn ei farcio'n barod mewn llai na 30 munud, yn rhoi fy hun ar y cefn i glirio'r bwrdd o sbwriel arall eto ac yn dychwelyd at faterion pwysicach.
Chwalu i mewn i wal ar 200 km/h
Wrth agor y ffeil varnishreload
, ar un o'r gweinyddwyr sy'n rhedeg Debian Stretch, gwelais sgript cragen yn llai na 200 llinell o hyd.
Ar ôl mynd trwy'r sgript, ni sylwais ar unrhyw beth a allai arwain at broblemau wrth ei redeg sawl gwaith yn uniongyrchol o'r derfynell.
Wedi'r cyfan, mae hwn yn gam, hyd yn oed os yw'n torri, ni fydd neb yn cwyno, wel ... dim gormod. Rwy'n rhedeg y sgript ac yn gweld beth fydd yn cael ei ysgrifennu i'r derfynell, ond nid yw'r gwallau bellach yn weladwy.
Mae cwpl arall yn rhedeg i sicrhau na allaf atgynhyrchu'r gwall heb unrhyw ymdrech ychwanegol, ac rwy'n dechrau darganfod sut i newid y sgript hon a'i gwneud yn dal i daflu gwall.
A all y sgript ddiystyru STDOUT (gan ddefnyddio > &-
)? Neu STDERR? Ni weithiodd yr un o'r rhain yn y diwedd.
Mae'n debyg bod systemd rhywsut yn addasu'r amgylchedd cychwyn, ond sut, a pham?
Rwy'n agor vim ac yn golygu varnishreload
, gan ychwanegu set -x
reit o dan y shebang, gan obeithio y bydd allbwn dadfygio'r sgript yn taflu rhywfaint o oleuni.
Mae'r ffeil wedi'i chywiro, felly rwy'n ail-lwytho farnais a gweld bod y newid wedi torri popeth yn llwyr... Mae'r gwacáu yn llanast llwyr, lle mae tunnell o god tebyg i C. Nid yw hyd yn oed sgrolio yn y derfynell yn ddigon i ddod o hyd i ble mae'n dechrau. Dwi wedi drysu'n llwyr. A all modd dadfygio effeithio ar weithrediad rhaglenni a lansiwyd mewn sgript? Na, mae'n nonsens. Byg yn y plisgyn? Mae sawl senario posib yn rasio trwy fy mhen fel chwilod duon i gyfeiriadau gwahanol. Mae cwpan y ddiod â chaffein yn cael ei wagio ar unwaith, taith gyflym i'r gegin i ailgyflenwi'r stoc a... bant â ni. Rwy'n agor y sgript ac yn edrych yn agosach ar y shebang: #!/bin/sh
.
/bin/sh
- dim ond symlink i bash yw hwn, felly dehonglir y sgript yn y modd sy'n gydnaws â POSIX, iawn? Nid felly! Y gragen rhagosodedig ar Debian yw dash, a dyna'n union sut olwg sydd arno. /bin/sh
.
# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Jan 24 2017 /bin/sh -> dash
Fel prawf, newidiais y shebang i #!/bin/bash
, dileu set -x
a cheisio eto. Yn olaf, ar ôl ailgychwyn farnais wedi hynny, ymddangosodd gwall goddefadwy yn yr allbwn:
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
Llinell 124, dyma fe!
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 }
Ond fel mae'n digwydd, mae llinell 124 yn eithaf gwag ac o ddim diddordeb. Ni allwn ond tybio bod y gwall wedi digwydd fel rhan o linyn aml-linell yn dechrau ar linell 116.
Beth sydd wedi'i ysgrifennu i'r newidyn yn y pen draw? VCL_FILE
o ganlyniad i weithredu'r is-gragen uchod?
Ar y dechrau, mae'n anfon cynnwys y newidyn VLC_SHOW
, a grëwyd ar linell 115, yn dilyn y gorchymyn trwy'r bibell. Ac yna beth sy'n digwydd yno?
Yn gyntaf, fe'i defnyddir yno varnishadm
, sy'n rhan o'r pecyn gosod farnais, ar gyfer gosod farnais heb ailgychwyn.
Is-dîm vcl.show -v
a ddefnyddir i allbynnu'r ffurfweddiad VCL cyfan a nodir yn ${VCL_NAME}
, i STDOUT.
I arddangos y ffurfweddiad VCL gweithredol cyfredol, yn ogystal â sawl fersiwn blaenorol o ffurfweddiadau llwybro farnais sy'n dal yn y cof, gallwch ddefnyddio'r gorchymyn varnishadm vcl.list
, y bydd ei allbwn yn debyg i'r un isod:
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
Gwerth amrywiol ${VCL_NAME}
wedi'i osod mewn rhan arall o'r sgript varnishreload
i enw'r VCL sy'n weithredol ar hyn o bryd, os oes un. Yn yr achos hwn bydd yn “ail-lwytho_20190101_120000_12397”.
Gwych, amrywiol ${VCL_SHOW}
yn cynnwys cyfluniad cyflawn ar gyfer farnais, yn glir am y tro. Nawr rwy'n deall o'r diwedd pam mae'r allbwn dash set -x
troi allan i fod mor doredig - roedd yn cynnwys cynnwys y cyfluniad canlyniadol.
Mae'n bwysig deall y gellir cyfuno ffurfweddiad VCL cyflawn yn aml o sawl ffeil. Defnyddir sylwadau arddull C i nodi lle mae rhai ffeiliau cyfluniad wedi'u cynnwys mewn eraill, a dyna hanfod y llinell cod ganlynol.
Mae'r gystrawen ar gyfer sylwadau sy'n disgrifio'r ffeiliau sydd wedi'u cynnwys yn y fformat a ganlyn:
// VCL.SHOW <NUM> <NUM> <FILENAME>
Nid yw'r niferoedd yn bwysig yn y cyd-destun hwn, mae gennym ddiddordeb yn enw'r ffeil.
Beth sy'n digwydd yn y pen draw yn y gors o orchmynion sy'n dechrau ar linell 116?
Gadewch i ni chyfrif i maes.
Mae’r tîm yn cynnwys pedair rhan:
- Syml
echo
, sy'n argraffu gwerth y newidyn${VCL_SHOW}
echo "$VCL_SHOW"
awk
, sy’n edrych am linell (record) lle mae’r maes cyntaf, ar ôl torri’r testun, yn “//”, a’r ail yn “VCL.SHOW”.
Bydd Awk yn ysgrifennu'r llinell gyntaf sy'n cyfateb i'r patrymau hyn ac yna'n rhoi'r gorau i brosesu ar unwaith.awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
- Bloc o god sy'n storio gwerthoedd maes yn bum newidyn, wedi'u gwahanu gan fylchau. Mae'r pumed newidyn FFEIL yn derbyn gweddill y llinell. Yn olaf, mae'r adlais olaf yn ysgrifennu cynnwys y newidyn
${FILE}
.{ read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
- Gan fod pob cam 1 i 3 wedi'i amgáu mewn is-blisgyn, gan allbynnu'r gwerth
$FILE
yn cael ei ysgrifennu i newidynVCL_FILE
.
Fel y mae'r sylw ar linell 119 yn ei awgrymu, dyma'r unig ddiben o drin achosion yn ddibynadwy lle bydd VCL yn cyfeirio at ffeiliau gyda bylchau yn eu henwau.
Rwyf wedi nodi'r rhesymeg brosesu wreiddiol ar gyfer ${VCL_FILE}
a cheisiodd newid y dilyniant gorchymyn, ond nid oedd yn arwain at unrhyw beth. Gweithiodd popeth yn iawn i mi, ond pan ddechreuais y gwasanaeth roedd yn rhoi gwall.
Mae'n ymddangos nad yw'r gwall yn atgynhyrchadwy wrth redeg y sgript â llaw, tra bod y 30 munud tybiedig eisoes wedi dod i ben chwe gwaith ac, yn ogystal, mae tasg â blaenoriaeth uwch wedi ymddangos, gan wthio materion eraill o'r neilltu. Roedd gweddill yr wythnos yn llawn amrywiaeth o dasgau a dim ond ychydig yn llai gwanedig oedd adroddiad ar sed a chyfweliad ag ymgeisydd. Problem gyda gwall yn varnishreload
a gollwyd yn anadferadwy yn nhywod amser.
Eich hyn a elwir yn sed-fu... mewn gwirionedd... sbwriel
Yr wythnos nesaf fe ges i un diwrnod gweddol rydd, felly penderfynais daclo'r tocyn yma eto. Roeddwn yn gobeithio yn fy ymennydd, bod rhywfaint o broses gefndir wedi bod yn chwilio am ateb i'r broblem hon drwy'r amser hwn, a'r tro hwn byddwn yn bendant yn deall beth oedd yn digwydd.
Gan nad oedd newid y cod yn helpu y tro diwethaf, penderfynais ei ailysgrifennu gan ddechrau o linell 116. Beth bynnag, roedd y cod presennol yn dwp. Ac nid oes angen ei ddefnyddio o gwbl read
.
Edrych ar y gwall eto:
sh: echo: broken pipe
— mae adlais yn ymddangos mewn dau le yn y gorchymyn hwn, ond yr wyf yn amau mai'r cyntaf yw'r troseddwr mwyaf tebygol (neu o leiaf yn gyd-droseddwr). Nid yw awk yn ennyn hyder chwaith. A rhag ofn ei fod mewn gwirionedd awk | {read; echo}
mae'r dyluniad yn arwain at yr holl broblemau hyn, beth am ei ddisodli? Nid yw'r gorchymyn un-llinell hwn yn defnyddio holl nodweddion awk, a hyd yn oed yr un ychwanegol hwn read
yn ychwanegol.
Ers yr wythnos diwethaf cafwyd adroddiad ar sed
, Roeddwn i eisiau rhoi cynnig ar fy sgiliau newydd a symleiddio echo | awk | { read; echo}
i mewn i fwy dealladwy echo | sed
. Er nad dyma'r ffordd orau o adnabod y byg yn bendant, meddyliais y byddwn o leiaf yn rhoi cynnig ar fy sed-fu ac efallai yn dysgu rhywbeth newydd am y broblem. Ar hyd y ffordd, gofynnais i fy nghydweithiwr, awdur y sgwrs sed, fy helpu i lunio sgript sed fwy effeithlon.
Gollyngais y cynnwys varnishadm vcl.show -v "$VCL_NAME"
i ffeil, felly gallwn ganolbwyntio ar ysgrifennu'r sgript sed heb unrhyw drafferth o reboots gwasanaeth.
Disgrifiad byr o sut yn union y gellir dod o hyd i fewnbwn prosesau sed n
a nodir yn benodol fel gwahanydd llinell.
Mewn sawl pas a chydag argymhellion fy nghyd-Aelod, fe wnaethom ysgrifennu sgript sed a roddodd yr un canlyniad â’r llinell wreiddiol gyfan 116.
Isod mae ffeil sampl gyda data mewnbwn:
> 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
Efallai nad yw hyn yn amlwg o'r disgrifiad uchod, ond dim ond y sylw cyntaf sydd gennym ni // VCL.SHOW
, ac efallai y bydd nifer ohonynt yn y data mewnbwn. Dyma pam mae'r llecyn gwreiddiol yn dod i ben ar ôl y gêm gyntaf.
# шаг первый, вывести только строки с комментариями
# используя возможности 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
Felly, bydd cynnwys y sgript varnishreload yn edrych rhywbeth fel hyn:
VCL_FILE="$(echo "$VCL_SHOW" | sed -En '#// VCL.SHOW#{s#.*[0-9]+ [0-9]+ (.*)$#1#p;q;};')"
Gellir mynegi'r rhesymeg uchod yn fyr fel a ganlyn:
Os yw'r llinyn yn cyfateb i fynegiad rheolaidd // VCL.SHOW
, yna yfwch yn farus y testyn sydd yn cynnwys y ddau rif yn y llinell hon, ac arbedwch bob peth sydd yn weddill ar ol y gweithrediad hwn. Allyrru'r gwerth sydd wedi'i storio a gorffen y rhaglen.
Syml, ynte?
Roeddem yn hapus gyda'r sgript sed a'r ffaith ei fod wedi disodli'r holl god gwreiddiol. Rhoddodd fy holl brofion y canlyniadau dymunol, felly newidiais y "varnishreload" ar y gweinydd a'i redeg eto systemctl reload varnish
. Camgymeriad drwg echo: write error: Broken pipe
chwerthin yn ein hwynebau eto. Roedd y cyrchwr wincio yn aros i orchymyn newydd gael ei nodi yng ngwacter tywyll y derfynell...
Ffynhonnell: hab.com