ريبيٽ هول هيٺان گرڻ: هڪ وارنش جي ٻيهر لوڊ ڪرڻ جي ناڪامي جي ڪهاڻي - حصو 1

گھوسٽينوشنڪاگذريل 20 منٽن تائين بٽڻن تي ڌڪ هڻي، ڄڻ ته هن جي زندگي ان تي منحصر هئي، هن جي اکين ۾ هڪ نيم جهنگلي نظر ۽ هڪ مسڪراهٽ سان مون ڏانهن رخ ڪيو - ”يار، مون سمجهيو ته مون کي سمجهي ورتو.

”هتي ڏسو،“ هو اسڪرين جي هڪ نشاني ڏانهن اشارو ڪندي چوي ٿو، ”مان پنهنجي ڳاڙهي ٽوپي تي شرط رکي ٿو ته جيڪڏهن اسان هتي شامل ڪريون ٿا جيڪو مون توهان کي موڪليو آهي،“ ڪوڊ جي ٻئي حصي ڏانهن اشارو ڪندي، ”غلطي هاڻي نه ٿيندي. ڏيکاريو ويندو."

ٿورڙو حيران ۽ ٿڪل، مون sed ايڪسپريس کي تبديل ڪيو جنهن تي اسان ڪجهه وقت کان ڪم ڪري رهيا آهيون، فائل کي محفوظ ڪريو ۽ هلائيندا systemctl varnish reload. غلطي جو پيغام غائب ٿي ويو آهي ...

”جيڪي اي ميلون مون اميدوار سان مٽائي ڇڏيون،“ منهنجو ساٿي اڳتي وڌندو رهيو، جيئن سندس مسڪراهٽ خوشيءَ جي حقيقي مسڪراهٽ ۾ وڌي وئي، ”اوچتو مون تي خيال آيو ته اهو ساڳيو مسئلو آهي!

اهو سڀ ڪيئن شروع ٿيو

آرٽيڪل سمجهي ٿو ته ڪيئن bash، awk، sed ۽ systemd ڪم. وارنش جي ڄاڻ کي ترجيح ڏني وئي آهي، پر گهربل ناهي.
ٽڪرن ۾ ٽائم اسٽيمپ تبديل ڪيا ويا آهن.
سان لکيل آهي گھوسٽينوشنڪا.
هي متن ٻه هفتا اڳ انگريزيءَ ۾ ڇپيل اصل جو ترجمو آهي؛ ترجمو بوڪوڊن.

سج اڀري ٿو پينورامڪ ونڊوز ذريعي هڪ ٻي گرم سرءُ جي صبح جو، تازو تيار ڪيل ڪيفين سان ڀريل مشروب جو هڪ پيالو ڪي بورڊ کان پري آهي، توهان جي هيڊفونز ۾ آوازن جي توهان جي پسنديده سمفوني، ميڪيڪل ڪيبورڊ جي سرسري آواز کي غرق ڪندي، ۽ پهرين داخلا. ڪنبن بورڊ تي بيڪ لاگ ٽڪيٽن جي لسٽ ۾ شاندار عنوان سان چمڪندو آهي “Investigate varnishreload” sh: echo: I/O error in staging” (Investigate “varnishreload sh: echo: I/O error” اسٽيجنگ ۾). جڏهن اها وارنش تي اچي ٿي، اتي موجود آهي ۽ نه ٿي سگهي ٿي غلطين لاءِ ڪا به گنجائش، جيتوڻيڪ اهي ڪنهن به مسئلي جي نتيجي ۾ نه هجن جيئن هن معاملي ۾.

انهن لاء جيڪي واقف نه آهن وارنش لوڊ, هي هڪ سادي شيل اسڪرپٽ آهي جيڪو ترتيب ڏيڻ لاءِ استعمال ڪيو ويندو آهي وارنش - VCL پڻ سڏيو ويندو آهي.

جيئن ته ٽڪيٽ جي عنوان مان معلوم ٿئي ٿو ته، اسٽيج تي موجود سرورن مان هڪ تي غلطي ٿي وئي، ۽ جيئن ته مون کي پڪ هئي ته اسٽيج تي وارنش جو رستو ٺيڪ ڪم ڪري رهيو هو، مون سمجهيو ته اها ڪا معمولي غلطي هوندي. تنهن ڪري، صرف هڪ پيغام جيڪو اڳ ۾ ئي بند ٿيل ٻاھرين وهڪرو ۾ ختم ٿي ويو. مان پنهنجي لاءِ ٽڪيٽ وٺان ٿو، مڪمل اعتماد سان ته مان 30 منٽن کان به گهٽ وقت ۾ ان کي تيار ڪري ڇڏيندس، پاڻ کي پٺيءَ تي ٿڦڻ لڳس ته بورڊ کي صاف ڪرڻ لاءِ هڪ ٻئي کان وڌيڪ اهم معاملن ڏانهن موٽيو.

200 ڪلوميٽر في ڪلاڪ جي رفتار سان ڀت سان ٽڪرائجڻ

فائل کولڻ varnishreload، ڊيبين اسٽريچ تي هلندڙ سرورن مان هڪ تي، مون ڏٺو ته شيل اسڪرپٽ 200 لائينن کان گهٽ ڊگهو آهي.

اسڪرپٽ جي ذريعي وڃڻ کان پوء، مون ڪجھ به نوٽيس نه ڪيو جنهن جي نتيجي ۾ مسئلا پيدا ٿي سگهي ٿي جڏهن ان کي سڌو سنئون ٽرمينل کان ڪيترائي ڀيرا هلائڻ.

آخرڪار، هي هڪ اسٽيج آهي، جيتوڻيڪ اهو ڀڄي ويندو، ڪو به شڪايت نه ڪندو، خير ... تمام گهڻو نه. مان اسڪرپٽ هلائيندو آهيان ۽ ڏسندو آهيان ته ٽرمينل ڏانهن ڇا لکيو ويندو، پر غلطيون هاڻي نظر نه اينديون آهن.

هڪ ٻه وڌيڪ ڊوڙون ٿا انهي ڳالهه کي يقيني بڻائڻ لاءِ ته مان ڪنهن به اضافي ڪوشش کان سواءِ غلطي کي ٻيهر نه ٿو بڻائي سگهان، ۽ مان اهو معلوم ڪرڻ شروع ڪري رهيو آهيان ته هن اسڪرپٽ کي ڪيئن تبديل ڪجي ۽ ان کي اڃا به غلطي اڇلائي.

ڇا اسڪرپٽ STDOUT (استعمال ڪندي > &-)؟ يا STDERR؟ انهن مان ڪو به آخر ۾ ڪم نه ڪيو.

بظاهر سسٽم ڪنهن به طريقي سان شروعاتي ماحول کي تبديل ڪري ٿو، پر ڪيئن، ۽ ڇو؟
مون ويم کوليو ۽ ايڊٽ ڪيو varnishreload، شامل ڪرڻ set -x صحيح شيبنگ جي هيٺان، اميد آهي ته اسڪرپٽ جي ڊيبگ آئوٽ ڪجهه روشني وجهي ويندي.

فائل صحيح ٿي چڪي آهي، تنهنڪري مون وارنش کي ٻيهر لوڊ ڪيو ۽ ڏسو ته تبديلي مڪمل طور تي هر شيء کي ٽوڙي ڇڏيو آهي ... نڪرڻ هڪ مڪمل گندگي آهي، جنهن ۾ ڪيترائي سي-جهڙو ڪوڊ آهن. جيتوڻيڪ ٽرمينل ۾ طومار ڪرڻ ڪافي نه آهي ڳولڻ لاء جتي اهو شروع ٿئي ٿو. مان مڪمل طور تي پريشان آهيان. ڇا ڊيبگنگ موڊ اسڪرپٽ ۾ شروع ڪيل پروگرامن جي آپريشن کي متاثر ڪري سگھي ٿو؟ نه، اهو بيوقوف آهي. شيل ۾ بگ؟ ڪيتريون ئي ممڪن منظرنامو منهنجي مٿي ذريعي مختلف طرفن ۾ ڪاڪروچ وانگر ڊوڙي رهيا آهن. ڪيفين ٿيل مشروب جو پيالو فوري طور تي خالي ڪيو ويو، اسٽاڪ کي ڀرڻ لاءِ باورچی خانه ڏانهن تڪڙو سفر ۽ ... اسان وڃون ٿا. مون اسڪرپٽ کوليو ۽ شيبنگ تي ويجھو نظر وجهو: #!/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 ترتيب اڪثر ڪري ڪيترن ئي فائلن مان گڏ ڪري سگهجي ٿو. سي-انداز تبصرا استعمال ڪيا ويا آهن سڃاڻپ ڪرڻ لاءِ جتي ڪن ڪنفيگريشن فائلن کي ٻين ۾ شامل ڪيو ويو آهي، ۽ اهو ئي آهي ته هيٺ ڏنل لائن جي ڪوڊ سنيپٽ سڀني بابت آهي.
تبصرن لاءِ نحو شامل ڪيل فائلن کي بيان ڪرڻ لاءِ ھيٺ ڏنل شڪل ۾ آھي:

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

ان حوالي سان انگ اھم نه آھن، اسان کي فائل جي نالي ۾ دلچسپي آھي.

لائن 116 تي شروع ٿيندڙ حڪمن جي دلدل ۾ آخرڪار ڇا ٿيندو؟
اچو ته ان جو اندازو لڳايو.
ٽيم چار حصن تي مشتمل آهي:

  1. سادو echo، جيڪو متغير جي قيمت کي پرنٽ ڪري ٿو ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk، جيڪو هڪ لڪير (رڪارڊ) ڳولي ٿو جتي پهريون فيلڊ، متن کي ٽوڙڻ کان پوء، "//" آهي، ۽ ٻيو "VCL.SHOW" آهي.
    Awk انهن نمونن سان ملندڙ پهرين لائن لکندو ۽ پوءِ فوري طور تي پروسيسنگ کي روڪيندو.

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. ڪوڊ جو هڪ بلاڪ جيڪو فيلڊ جي قيمتن کي پنجن متغيرن ۾ ذخيرو ڪري ٿو، جڳهن سان الڳ ٿيل. پنجون فائل متغير باقي لڪير وصول ڪري ٿو. آخرڪار، آخري گونج متغير جي مواد کي لکي ٿو ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. جيئن ته سڀئي مرحلا 1 کان 3 سب شيل ۾ بند ٿيل آهن، قيمت کي ٻاھر ڪڍڻ $FILE variable ڏانهن لکيو ويندو VCL_FILE.

جيئن ته لڪير 119 تي تبصرو مشورو ڏئي ٿو، اهو واحد مقصد ڪم ڪري ٿو معتبر طور تي ڪيسن کي سنڀالڻ جتي VCL فائلن کي انهن جي نالن ۾ اسپيس سان حوالي ڪندو.

مون تبصرو ڪيو آهي اصل پروسيسنگ منطق لاءِ ${VCL_FILE} ۽ حڪم جي ترتيب کي تبديل ڪرڻ جي ڪوشش ڪئي، پر اهو ڪجهه به نه ٿيو. مون لاءِ هر شي ٺيڪ ڪم ڪيو، پر جڏهن مون خدمت شروع ڪئي ته اها غلطي ٿي.

اهو لڳي ٿو ته غلطي صرف ٻيهر پيدا ڪرڻ جي قابل ناهي جڏهن اسڪرپٽ دستي طور تي هلندي، جڏهن ته 30 منٽ اڳ ۾ ئي ڇهه ڀيرا ختم ٿي چڪا آهن ۽ ان کان علاوه، هڪ اعلي ترجيحي ڪم ظاهر ٿيو آهي، ٻين معاملن کي هڪ طرف ڌڪي ڇڏيو. باقي هفتي مختلف ڪمن سان ڀريو پيو هو ۽ صرف sed تي هڪ رپورٽ ۽ اميدوار سان هڪ انٽرويو ذريعي ٿورڙو گهٽجي ويو. ۾ غلطي سان مسئلو varnishreload وقت جي رڻ ۾ گم ٿي ويو.

توهان جو نام نهاد sed-fu... اصل ۾... گندو آهي

ايندڙ هفتي مون وٽ هڪ بلڪل مفت ڏينهن هو، تنهنڪري مون هن ٽڪيٽ کي ٻيهر ڏيڻ جو فيصلو ڪيو. مون کي اميد هئي ته منهنجي دماغ ۾ هن سڄي عرصي ۾ ڪو پس منظر وارو عمل ان مسئلي جو حل ڳولي رهيو هو ۽ هن ڀيري مان ضرور سمجهندو ته ڇا ٿي رهيو آهي.

جيئن ته صرف ڪوڊ تبديل ڪرڻ آخري ڀيرو مدد نه ڪئي، مون صرف ان کي ٻيهر لکڻ جو فيصلو ڪيو 116 لائن کان شروع ڪندي. ڪنهن به صورت ۾، موجوده ڪوڊ بيوقوف هو. ۽ ان کي استعمال ڪرڻ جي بلڪل ڪا ضرورت ناهي read.

غلطي کي ٻيهر ڏسو:
sh: echo: broken pipe - گونج هن حڪم ۾ ٻن هنڌن تي ظاهر ٿئي ٿو، پر مون کي شڪ آهي ته پهريون وڌيڪ ممڪن آهي مجرم (يا گهٽ ۾ گهٽ هڪ ساٿي). Awk پڻ اعتماد کي متاثر نٿو ڪري. ۽ صورت ۾ اهو واقعي آهي awk | {read; echo} ڊزائن انهن سڀني مسئلن جي ڪري ٿي، ڇو نه ان کي تبديل ڪيو وڃي؟ هي ون لائين ڪمانڊ awk جي سڀني خصوصيتن کي استعمال نٿو ڪري، ۽ اڃا به هي اضافي read ان کان علاوه.

گذريل هفتي کان وٺي هڪ رپورٽ هئي sed، مان پنهنجي نئين حاصل ڪيل صلاحيتن کي ڪوشش ڪرڻ ۽ آسان ڪرڻ چاهيان ٿو echo | awk | { read; echo} وڌيڪ سمجھڻ ۾ echo | sed. جڏهن ته اهو يقيني طور تي بگ کي سڃاڻڻ جو بهترين طريقو ناهي، مون سوچيو ته مان گهٽ ۾ گهٽ پنهنجي سيڊ فو جي ڪوشش ڪندس ۽ ٿي سگهي ٿو ته مسئلي بابت ڪجهه نئون سکي وٺان. رستي ۾، مون پنهنجي ساٿي، سيڊ ٽاڪ جي ليکڪ کان پڇيو، مون کي وڌيڪ موثر سيڊ اسڪرپٽ سان گڏ اچڻ ۾ مدد ڪرڻ لاء.

مون مواد ڪڍي ڇڏيو varnishadm vcl.show -v "$VCL_NAME" هڪ فائل ڏانهن، تنهنڪري آئون خدمت ريبوٽس جي بغير ڪنهن پريشاني جي sed اسڪرپٽ لکڻ تي ڌيان ڏئي سگهان ٿو.

هڪ مختصر وضاحت بلڪل ڪيئن sed پروسيس ان پٽ ۾ ملي سگهي ٿو سندس GNU دستياب. sd ذريعن ۾ علامت 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، پوء لالچ سان متن کي کائي ڇڏيو جنهن ۾ هن لڪير ۾ ٻئي نمبر شامل آهن، ۽ هر شيء کي بچايو جيڪو هن آپريشن کان پوء رهي ٿو. محفوظ ڪيل قيمت کي ختم ڪريو ۽ پروگرام کي ختم ڪريو.

سادو، آهي نه؟

اسان sed اسڪرپٽ سان خوش هئاسين ۽ حقيقت اها آهي ته اهو سڀ اصل ڪوڊ تبديل ڪيو. منهنجا سڀئي ٽيسٽ گهربل نتيجا ڏنائين، تنهنڪري مون سرور تي "varnishreload" کي تبديل ڪيو ۽ ان کي ٻيهر هلائي ڇڏيو systemctl reload varnish. خراب غلطي echo: write error: Broken pipe اسان جي منهن تي وري کلڻ لڳو. ٽهڪ ڏيندڙ ڪرسر ٽرمينل جي اونداهيءَ ۾ هڪ نئين حڪم جي داخل ٿيڻ جو انتظار ڪري رهيو هو...

جو ذريعو: www.habr.com

تبصرو شامل ڪريو