د خرگوش سوري ښکته کول: د یو وارنش ریبوټ غلطی کیسه - لومړۍ برخه

غوستینوشانکا، د تیرو 20 دقیقو لپاره د بټونو له وهلو وروسته لکه څنګه چې د هغه ژوند په دې پورې تړلی و ، په خپلو سترګو کې نیم وحشي څرګندونه او په خندا خندا سره ماته مخ شو - "یار ، زه فکر کوم زه پوهیږم."

هغه د کوډ بلې برخې ته په اشارې سره وايي: "دلته وګوره ،" هغه په ​​سکرین کې یو سمبول ته په اشارې سره وویل ، "زه تاسو ته زما سور خولۍ شرط درکوم ، که موږ هغه څه اضافه کړو چې ما تاسو ته دلته لیږلي"

یو څه حیران او ستړی شوی، زه د سیډ بیان بدل کړم چې موږ یې د یو څه مودې لپاره کار کوو، فایل خوندي کړئ او چل کړئ systemctl varnish reload. د خطا پیغام ورک شوی دی ...

"هغه ایمیلونه چې ما د کاندید سره تبادله کړل،" زما همکار ادامه ورکړه، لکه څنګه چې د هغه موسکا په ریښتینې موسکا بدله شوه له خوښۍ څخه ډکه، "دا ناڅاپه زما په ذهن کې راڅرګند شو چې دا هم ورته ستونزه ده!"

دا ټول څنګه پیل شول

مقاله د دې پوهه په غاړه لري چې څنګه bash، awk، sed او systemd کار کوي. د وارنش پوهه غوره ده مګر اړتیا نلري.
په لنډیو کې د مهال ویش بدل شوي.
سره لیکل شوی غوستینوشانکا.
دا متن د هغه اصلي ژباړه ده چې دوه اونۍ وړاندې په انګلیسي ژبه خپره شوې وه. ژباړه boyikoden.

لمر د مني په یو بل ګرم سهار کې د پینورامیک کړکیو له لارې ځلیږي، د تازه جوش شوي کافین شوي څښاک یوه پیاله د کیبورډ څخه لیرې پاتې کیږي، د غږونو یوه غوره سمفوني په هیډفونونو کې د میخانیکي کیبورډونو په سر غږیږي، او د کانبان په بورډ کې د بیکلاګ ټیکټ لیست کې لومړی ننوتل: زه په بشپړ ډول د لوبې کولو سرلیک سره: O په مرحله کې تېروتنه" (په مرحله کې د "varnishreload sh: echo: I/O تېروتنه" پلټنه وکړئ). کله چې د وارنش خبره راځي، هیڅ ډول غلطی شتون نلري او نشي کیدی، حتی که دوی د کومې ستونزې پایله ونلري، لکه څنګه چې پدې قضیه کې.

د هغو کسانو لپاره چې نه پیژندل کیږي varnishreload، دا یو ساده شیل سکریپټ دی چې د تشکیلاتو بیا پورته کولو لپاره کارول کیږي وارنش - د VCL په نوم هم یادیږي.

لکه څنګه چې د ټیکټ سرلیک وړاندیز کوي ، تېروتنه په مرحله کې په یو سرور کې رامینځته شوې ، او څنګه چې زه ډاډه وم چې په مرحله کې د وارنش روټینګ په سمه توګه کار کوي ، ما ګومان وکړ چې دا به یوه کوچنۍ تېروتنه وي. نو ، یوازې یو پیغام چې دمخه تړل شوي محصول جریان ته رسیدلی. زه د خپل ځان لپاره ټیکټ اخلم، په پوره باور سره چې زه به یې په 30 دقیقو کې د چمتو کیدو نښه کړم، د راتلونکي جنک د تختې پاکولو لپاره خپل اوږه په اوږه واچوم او نورو مهمو شیانو ته بیرته راشم.

په 200 کیلومتره فی ساعت کې دیوال سره ټکر

د فایل خلاصول varnishreload، په یو سرور کې چې دبیان سټریچ چلوي ، ما د شیل سکریپټ له 200 لینونو څخه لږ اوږد ولید.

د سکریپټ له لارې پرمخ وړل، ما داسې څه ونه لیدل چې ستونزې رامینځته کړي کله چې دا په مستقیم ډول له ټرمینل څخه څو ځله چلوي.

په هرصورت، دا یو پړاو دی، حتی که دا مات شي، هیڅوک به شکایت وکړي، ښه ... ډیر نه. زه سکریپټ پرمخ وړم او وګورم چې ټرمینل ته به څه لیکل کیږي، مګر تېروتنې نور نه لیدل کیږي.

یو څو نور منډې وهي ترڅو ډاډ ترلاسه کړم چې زه نشم کولی غلطی له یو څه اضافي هڅو پرته بیا تولید کړم ، او زه په دې پوهیدل پیل کوم چې څنګه دا سکریپټ بدل کړم او دا لاهم یوه تېروتنه وغورځوم.

ایا سکریپټ کولی شي STDOUT بلاک کړي (په کارولو سره > &-)؟ یا STDERR؟ نه په پای کې کار وکړ.

په ښکاره ډول سیسټم په یو ډول د چلولو چاپیریال بدلوي، مګر څنګه، او ولې؟
زه ویم چالان کړم او ترمیم کړم varnishreload، اضافه کول set -x د شیبنګ لاندې سم ، امید دی چې د سکریپټ محصول ډیبګ کول به یو څه رڼا واچوي.

فایل فکس شوی ، نو زه وارنش بیا لوډ کړم او ګورم چې بدلون په بشپړ ډول هرڅه مات کړي ... اخراج یو بشپړ ګډوډ دی ، په دې کې د ټنونو C - په څیر کوډ سره. حتی په ترمینل کې سکرول کول کافي ندي چې ومومئ چیرې چې دا پیل کیږي. زه په بشپړه توګه مغشوش یم. ایا د ډیبګ حالت په سکریپټ کې د چلولو برنامو کار اغیزه کولی شي؟ نه، بدمرغه. په خولۍ کې بګ؟ ډیری احتمالي سناریوګانې زما په سر کې الوتنې کوي لکه کاکروچ په بیلابیلو لارو کې. د کافین ډک څښاک یوه پیاله په سمدستي کې خالي کوي ، پخلنځي ته د بیا رسولو لپاره ګړندي سفر او… راځئ چې لاړ شو. ما سکریپټ خلاص کړ او شیبنګ ته نږدې کتنه کوم: #!/bin/sh.

/bin/sh - دا یوازې د باش سیملنک دی، نو سکریپټ د POSIX-مطابق حالت کې تشریح شوی، سمه ده؟ دا هلته نه وه! په ډیبیان کې ډیفالټ شیل ډش دی ، کوم چې واقعیا څه دي حواله کوي /bin/sh.

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

د محاکمې لپاره، ما شیبنګ ته بدل کړ #!/bin/bash, ړنګ شوی set -x او بیا هڅه وکړه. په نهایت کې ، د وارنش په ورپسې بار کولو کې ، په محصول کې د زغم وړ تېروتنه ښکاره شوه:

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

124 کرښه، دلته ده!

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 }

مګر لکه څنګه چې دا معلومه شوه، 124 کرښه خالي ده او هیڅ دلچسپي نلري. زه یوازې فرض کولی شم چې تېروتنه د ملټي لاین برخې په توګه رامینځته شوې چې په 116 کرښه کې پیل کیږي.
په پای کې متغیر ته څه لیکل کیږي VCL_FILE د پورته فرعي شیل اجرا کولو په پایله کې؟

په پیل کې، دا د متغیر مینځپانګې لیږي VLC_SHOW، په 115 لاین کې رامینځته شوی ، د پایپ له لارې راتلونکي کمانډ ته. او بیا هلته څه کیږي؟

لومړی، دا کاروي varnishadm, کوم چې د وارنش نصبولو کڅوړه برخه ده، د بیا پیل کولو پرته د وارنش تنظیم کولو لپاره.

فرعي کمانډ vcl.show -v د VCL ټول ترتیب تولیدولو لپاره کارول کیږي چې په کې مشخص شوي ${VCL_NAME}، STDOUT ته.

د اوسني فعال VCL تشکیلاتو ښودلو لپاره او همدارنګه د وارنش د روټینګ ترتیبونو ډیری پخوانی نسخې چې لاهم په حافظه کې دي ، تاسو کولی شئ کمانډ وکاروئ varnishadm vcl.list، چې پایله به یې لاندې سره ورته وي:

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

متغیر ارزښت ${VCL_NAME} د سکریپټ په بله برخه کې ترتیب کړئ varnishreload د اوسني فعال VCL نوم ته، که کوم وي. پدې حالت کې دا به "reload_20190101_120000_12397" وي.

ښه، متغیر. ${VCL_SHOW} د وارنش لپاره بشپړ ترتیب لري، تر دې دمه روښانه. اوس زه په پای کې پوهیږم چې ولې د ډیش محصول سره set -x دومره مات شو - پدې کې د پایله شوي ترتیب مینځپانګې شاملې وې.

دا مهمه ده چې پوه شئ چې د VCL بشپړ ترتیب اکثرا د ډیری فایلونو څخه یوځای کیدلی شي. د C سټایل نظرونه د دې تعریف کولو لپاره کارول کیږي چیرې چې یو ترتیب فایل په بل کې شامل شوی ، او دا په حقیقت کې هغه څه دي چې د کوډ سنیپټ لاندې لاین په اړه دي.
د تبصرو لپاره ترکیب چې شامل شوي فایلونه تشریح کوي لاندې بڼه لري:

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

پدې شرایطو کې شمیرې مهم ندي ، موږ د فایل نوم سره علاقه لرو.

نو د کمانډونو په دلدل کې څه پیښیږي چې په 116 لاین پیل کیږي؟
راځئ چې دا معلومه کړو.
قومانده له څلورو برخو څخه جوړه ده:

  1. ساده echo، کوم چې د متغیر ارزښت ښیې ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk، کوم چې د یوې کرښې (ریکارډ) په لټه کې دي ، چیرې چې د متن له ویشلو وروسته لومړی ساحه به "//" وي ، او دویمه برخه به "VCL. SHOW" وي.
    اوک به لومړۍ کرښه ولیکئ چې د دې نمونو سره سمون لري او بیا سمدلاسه پروسس کول ودروي.

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. د کوډ یو بلاک چې د ساحې ارزښتونه په پنځو متغیرونو کې ذخیره کوي، د ځایونو لخوا جلا شوي. پنځم متغیر فایل د لاین پاتې برخه ترلاسه کوي. په نهایت کې ، وروستی گونج د متغیر مینځپانګې لیکي ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. څرنګه چې ټول مرحلې له 1 څخه تر 3 پورې په فرعي شیل کې تړل شوي، د ارزښت محصول $FILE یو متغیر ته لیکل کیږي VCL_FILE.

لکه څنګه چې په 119 کرښه کې تبصره وړاندیز کوي، دا د قضیو په معتبر ډول اداره کولو یوازینۍ موخه لري چیرې چې VCL به د دوی په نومونو کې د سپینې ځای حروفونو سره فایلونو ته مراجعه وکړي.

ما د اصلي پروسس کولو منطق په اړه تبصره کړې ${VCL_FILE} او هڅه یې وکړه چې د حکمونو ترتیب بدل کړي، مګر دا د هیڅ شی لامل نه شو. هرڅه زما لپاره په پاکه توګه کار وکړ، او د خدمت پیل کولو په صورت کې، دا یوه تېروتنه وکړه.

داسې بریښي چې خطا په ساده ډول د بیا تولید وړ نه ده کله چې سکریپټ په لاسي ډول چلول کیږي ، پداسې حال کې چې اټکل شوي 30 دقیقې دمخه شپږ ځله پای ته رسیدلي او سربیره پردې ، د لوړ لومړیتوب دنده راڅرګنده شوې ، پاتې قضیې بلې خوا ته اړوي. د اونۍ پاتې برخه د مختلفو کارونو څخه ډکه وه او یوازې د سیډ په اړه د خبرو اترو او د کاندید سره د مرکې سره یو څه کم شوی و. په کې د تېروتنې ستونزه varnishreload د وخت په شګو کې بې له لاسه ورکول.

ستاسو تش په نامه سیډ فو ... په حقیقت کې ... کثافات

په راتلونکې اونۍ کې یوه وړیا ورځ وه، نو ما پریکړه وکړه چې دا ټکټ بیا واخلم. ما هیله درلوده چې زما په مغزو کې، دا ټول وخت یو څه پس منظر پروسې د دې ستونزې د حل په لټه کې وي، او دا ځل به زه حتما پوه شم چې څه غلط دي.

له هغه وخته چې تیر ځل یوازې د کوډ بدلولو مرسته ونه کړه، ما یوازې پریکړه وکړه چې دا د 116 کرښې څخه پیل کړي. په هر حالت کې، موجوده کوډ احمق و. او د کارولو لپاره بالکل اړتیا نشته read.

تېروتنې ته بیا کتنه:
sh: echo: broken pipe - په دې کمانډ کې، گونج په دوو ځایونو کې دی، مګر زه شک لرم چې لومړی یې احتمالي مجرم دی (ښه، یا لږترلږه یو ملګری). اوک هم اعتماد نه هڅوي. او په هغه صورت کې چې دا واقعا وي awk | {read; echo} ډیزاین د دې ټولو ستونزو لامل کیږي، ولې یې ځای نه نیسي؟ دا یو لاین کمانډ د awk ټولې ځانګړتیاوې نه کاروي، او حتی دا اضافي read په ضمیمه کې

د تیرې اونۍ راهیسې په دې اړه یو راپور شتون لري sedما غوښتل چې زما نوي ترلاسه شوي مهارتونه هڅه وکړم او ساده کړم echo | awk | { read; echo} په ډیر پوهیدو کې echo | sed. پداسې حال کې چې دا یقینا د بګ نیولو لپاره غوره لاره نه ده ، ما فکر کاوه چې زه به لږترلږه زما سیډ فو هڅه وکړم او ممکن د ستونزې په اړه یو څه نوي زده کړم. د لارې په اوږدو کې، ما له خپل همکار، د سیډ خبرې لیکونکي څخه وغوښتل چې زما سره مرسته وکړي چې د ډیر اغیزمن سیډ سکریپټ سره راشي.

ما مینځپانګه واخیسته varnishadm vcl.show -v "$VCL_NAME" یوې فایل ته نو زه کولی شم د sed سکریپټ لیکلو باندې تمرکز وکړم پرته لدې چې د خدماتو بیا پیل کولو ستونزې پرته.

په دقیق ډول یو لنډ توضیحات چې څنګه sed input اداره کوي موندل کیدی شي د هغه د GNU لارښود. په سیډ سرچینو کې، سمبول n په ښکاره ډول د کرښې جلا کونکي په توګه مشخص شوی.

په څو پاسونو کې، او زما د همکار په مشوره، موږ یو سیډ سکریپټ ولیکه چې د ټولې اصلي کرښې 116 په څیر ورته پایله یې ورکړه.

لاندې د ان پټ ډیټا سره د نمونې فایل دی:

> 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

دا ممکن د پورته توضیحاتو څخه څرګند نه وي ، مګر موږ یوازې په لومړي نظر کې علاقه لرو // VCL.SHOW، او کیدای شي د دوی ډیری یې د ان پټ ډاټا کې وي. له همدې امله اصلي awk د لومړۍ لوبې وروسته پای ته رسیږي.

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

نو د varnishreload سکریپټ مینځپانګې به داسې ښکاري:

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

پورتني منطق په لاندې ډول لنډولای شو:
که تار د منظم بیان سره سمون ولري // VCL.SHOW، بیا په لالچ سره هغه متن وخورئ چې پدې لیکه کې دواړه شمیرې پکې شاملې دي ، او هرڅه چې د دې عملیاتو وروسته پاتې کیږي خوندي کړئ. زیرمه شوی ارزښت صادر کړئ او برنامه پای ته ورسوئ.

ساده، دا نه ده؟

موږ د سیډ سکریپټ او حقیقت سره خوشحاله یو چې دا ټول اصلي کوډ بدلوي. زما ټولو ازموینو مطلوبې پایلې ورکړې، نو ما په سرور کې "varnishreload" بدل کړ او بیا ورغلم systemctl reload varnish. ناپاکه اشتباه echo: write error: Broken pipe زموږ په مخ بیا وخندل. یو ویښ کرسر د ټرمینل تیاره خلا کې د نوي کمانډ ننوتلو ته په تمه و ...

سرچینه: www.habr.com

Add a comment