የጥንቸል ጉድጓድ መውደቅ፡ የአንድ ቫርኒሽ ዳግም መጫን ውድቀት ታሪክ - ክፍል 1

ghostinushankaህይወቱ በዚህ ላይ የተመሰረተ ይመስል ላለፉት 20 ደቂቃዎች ቁልፎቹን እየዶለተ ሲሄድ ፣ ከፊል የዱር እይታ አይኑ ውስጥ እና በፈገግታ ፈገግታ ወደ እኔ ዞሯል - “ወዳጄ ፣ ያገኘሁት ይመስለኛል።

“እዚህ ተመልከት” አለ፣ በስክሪኑ ላይ ካሉት ምልክቶች አንዱን እየጠቆመ፣ “ቀይ ኮፍያዬን አሁን የላክሁህን እዚህ ላይ ብንጨምርልህ፣” ሲል ወደ ሌላ የኮድ ክፍል እየጠቆመ፣ “ስህተቱ ከእንግዲህ አይኖርም። ይታያል።"

ትንሽ ግራ ተጋባሁ እና ደክሞኝ ለተወሰነ ጊዜ ስንሰራበት የነበረውን ሴድ አገላለፅ አስተካክዬ ፋይሉን አስቀምጬ ሩጥ systemctl varnish reload. የስህተት መልዕክቱ ጠፍቷል...

“ከእጩው ጋር የተለዋወጥኳቸው ኢሜይሎች” ባልደረባዬ ቀጠለ፣ ፈገግታው ወደ እውነተኛ የደስታ ፈገግታ ሲያድግ፣ “ይህ በትክክል ተመሳሳይ ችግር እንደሆነ በድንገት ገባኝ።

ሁሉም እንዴት ተጀመረ

ጽሁፉ ባሽ፣ አዉክ፣ ሴድ እና ስርዓት እንዴት እንደሚሰሩ ግንዛቤን ይወስዳል። የቫርኒሽን እውቀት ይመረጣል, ግን አያስፈልግም.
የጊዜ ማህተሞች በቅንጭቦች ውስጥ ተለውጠዋል።
ጋር ተፃፈ ghostinushanka.
ይህ ጽሑፍ ከሁለት ሳምንታት በፊት በእንግሊዝኛ የታተመ ዋናው ትርጉም ነው; ትርጉም boikoden.

በሌላ ሞቃታማ የመከር ማለዳ ፀሐይ በፓኖራሚክ መስኮቶች በኩል ታበራለች፣ አንድ ኩባያ አዲስ የተዘጋጀ ካፌይን የበለፀገ መጠጥ ከቁልፍ ሰሌዳው ይርቃል፣ የሚወዱት የሲምፎኒ ድምጽ በጆሮ ማዳመጫዎ ውስጥ ይሰማል፣ የሜካኒካል ኪይቦርዶችን ዝገት ሰምጦ እና የመጀመሪያው መግቢያ በካንባን ሰሌዳ ላይ ባለው የኋላ ሎግ ቲኬቶች ዝርዝር ውስጥ “ቫርኒሽሬሎድን መርምር” sh: echo: I/O error in staging” (በማዘጋጀት ላይ “varnishreload sh: echo: I/O error” የሚለውን መርምር በሚለው እጣ ፈንታ ርዕስ በጨዋታ ያበራል። ወደ ቫርኒሽ ሲመጣ, ምንም እንኳን በዚህ ጉዳይ ላይ ምንም አይነት ችግር ባያመጣም, ለስህተት ምንም ቦታ ሊኖር አይችልም.

ለማያውቁት varnish reload, ይህ አወቃቀሩን እንደገና ለመጫን የሚያገለግል ቀላል የሼል ስክሪፕት ነው። ቫርኒሽ - ቪሲኤል ተብሎም ይጠራል.

የቲኬቱ ርዕስ እንደሚያመለክተው ስህተቱ በመድረኩ ላይ ከሚገኙት አገልጋዮች በአንዱ ላይ ተከስቷል, እና በመድረክ ላይ ያለው የቫርኒሽ መስመር በትክክል እንደሚሰራ እርግጠኛ ስለሆንኩ ይህ ትንሽ ስህተት ነው ብዬ አስቤ ነበር. ስለዚህ፣ አስቀድሞ በተዘጋ የውጤት ዥረት ውስጥ ያለቀ መልእክት። ትኬቱን ለራሴ ወስጃለሁ፣ ከ30 ደቂቃ ባነሰ ጊዜ ውስጥ ዝግጁ እንደምሆን ሙሉ በሙሉ በመተማመን፣ ሰሌዳውን ከሌላ ቆሻሻ በማጽዳት እራሴን በመንካት ወደ ተጨማሪ አስፈላጊ ጉዳዮች እመለሳለሁ።

በሰዓት 200 ኪ.ሜ ላይ ግድግዳ ላይ መውደቅ

ፋይሉን በመክፈት ላይ varnishreloadDebian Stretchን ከሚያስኬዱ አገልጋዮች በአንዱ ላይ ከ200 መስመር ያነሰ ርዝመት ያለው የሼል ስክሪፕት አየሁ።

በስክሪፕቱ ውስጥ ካለፍኩ በኋላ፣ በቀጥታ ከተርሚናል ብዙ ጊዜ ሲሰራው ችግር ሊያስከትል የሚችል ነገር አላስተዋልኩም።

ከሁሉም በላይ, ይህ መድረክ ነው, ቢሰበርም, ማንም አያማርርም, ደህና ... በጣም ብዙ አይደለም. እኔ ስክሪፕቱን አሂድ እና ወደ ተርሚናል ምን እንደሚጻፍ ተመልከት, ነገር ግን ስህተቶቹ ከአሁን በኋላ አይታዩም.

ያለ ምንም ተጨማሪ ጥረት ስህተቱን እንደገና ማባዛት እንደማልችል ለማረጋገጥ ተጨማሪ ባልና ሚስት ይሮጣሉ፣ እና ይህን ስክሪፕት እንዴት እንደምቀይር እና አሁንም ስህተት እንዲጥል ማድረግ እጀምራለሁ።

ስክሪፕቱ STDOUTን መሻር ይችላል (በመጠቀም > &-)? ወይስ STDERR? ከእነዚህ ውስጥ አንዳቸውም በመጨረሻ አልሰሩም.

በስርአት የተፈጠረ ይመስላል የጅምር አካባቢውን ያስተካክላል፣ ግን እንዴት እና ለምን?
ቪም ከፍቼ አርትዕ አደርጋለሁ varnishreload, በማከል set -x የስክሪፕቱ የስህተት ውፅዓት የተወሰነ ብርሃን እንደሚፈነጥቅ ተስፋ በማድረግ ልክ በሼባንግ ስር።

ፋይሉ ተስተካክሏል፣ ስለዚህ ቫርኒሽን እንደገና ጫንኩ እና ለውጡ ሁሉንም ነገር እንደፈረሰ አይቻለሁ… የጭስ ማውጫው ሙሉ በሙሉ የተመሰቃቀለ ነው ፣ በውስጡም ብዙ ቶን ሲ-የሚመስል ኮድ አለ። የት እንደሚጀመር ለማወቅ በተርሚናል ውስጥ ማሸብለል እንኳን በቂ አይደለም። ሙሉ በሙሉ ግራ ተጋባሁ። የማረም ሁነታ በስክሪፕት ውስጥ የተጀመሩ ፕሮግራሞችን አሠራር ሊጎዳ ይችላል? አይደለም ከንቱ ነው። በሼል ውስጥ ያለ ስህተት? ብዙ ሊሆኑ የሚችሉ ሁኔታዎች በተለያዩ አቅጣጫዎች እንደ በረሮ በራሴ ውስጥ እየሮጡ ነው። ካፌይን ያለው መጠጥ ጽዋ ወዲያውኑ ባዶ ይሆናል፣ ወደ ኩሽና በፍጥነት ጉዞውን ለመሙላት እና ... እንሄዳለን። ስክሪፕቱን ከፍቼ ሸባንግን ጠለቅ ብዬ እመለከተዋለሁ፡- #!/bin/sh.

/bin/sh - ይህ የ bash ሲምሊንክ ብቻ ነው፣ ስለዚህ ስክሪፕቱ በ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_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 ካለ አሁን ገባሪ ቪሲኤል ስም። በዚህ አጋጣሚ "ዳግም መጫን_20190101_120000_12397" ይሆናል።

ታላቅ ፣ ተለዋዋጭ ${VCL_SHOW} ለቫርኒሽ የተሟላ ውቅር ይዟል, ለአሁኑ ግልጽ. አሁን በመጨረሻ የዳሽ ውፅዓት ለምን እንደሆነ ተረድቻለሁ set -x በጣም የተሰበረ ሆኖ ተገኝቷል - የተገኘውን የውቅር ይዘት ያካትታል.

የተሟላ የቪሲኤል ውቅር ከበርካታ ፋይሎች አንድ ላይ ሊጣመር እንደሚችል መረዳት በጣም አስፈላጊ ነው። የC-style አስተያየቶች የተወሰኑ የውቅረት ፋይሎች በሌሎች ውስጥ የተካተቱበትን ቦታ ለመለየት ጥቅም ላይ ይውላሉ፣ እና የሚከተለው የኮድ ቅንጣቢ መስመር ስለዚያ ነው።
የተካተቱ ፋይሎችን የሚገልጹ የአስተያየቶች አገባብ በሚከተለው ቅርጸት ነው።

// 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 ተለዋዋጭ የቀረውን መስመር ይቀበላል. በመጨረሻም, የመጨረሻው ማሚቶ የተለዋዋጭውን ይዘት ይጽፋል ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. ከ 1 እስከ 3 ያሉት ሁሉም ደረጃዎች በንዑስ ሼል ውስጥ ተዘግተዋል, እሴቱን በማውጣት $FILE ወደ ተለዋዋጭ ይጻፋል VCL_FILE.

በመስመር 119 ላይ ያለው አስተያየት እንደሚያመለክተው፣ ይህ ቪሲኤል በስማቸው ያሉ ክፍተቶችን የሚጠቅስባቸውን ጉዳዮች በአስተማማኝ ሁኔታ የማስተናገድ ብቸኛ ዓላማን ያገለግላል።

ዋናውን የማስኬጃ አመክንዮ አስተያየት ሰጥቻለሁ ${VCL_FILE} እና የትዕዛዙን ቅደም ተከተል ለመለወጥ ሞክሯል, ነገር ግን ወደ ምንም ነገር አልመራም. ሁሉም ነገር ጥሩ ሆኖልኛል, ነገር ግን አገልግሎቱን ስጀምር ስህተት ፈጠረ.

ስክሪፕቱን በእጅ በሚሰራበት ጊዜ ስህተቱ በቀላሉ የማይባዛ ይመስላል ፣ የታሰበው 30 ደቂቃ ቀድሞውኑ ስድስት ጊዜ ያለፈበት እና ፣ በተጨማሪም ፣ ከፍ ያለ ቅድሚያ የሚሰጠው ተግባር ታይቷል ፣ ሌሎች ጉዳዮችን ወደ ጎን እየገፋ። የቀረው ሳምንት በተለያዩ ተግባራት የተሞላ ሲሆን በሴድ ዘገባ እና ከእጩ ጋር በተደረገ ቃለ ምልልስ በትንሹ ተሟጧል። ውስጥ ስህተት ጋር ችግር varnishreload በጊዜ አሸዋ ውስጥ ሊመለስ በማይቻል ሁኔታ ጠፋ።

ሴድ-ፉ የምትባለው... እንደውም... ቆሻሻ ነው።

በሚቀጥለው ሳምንት አንድ ትክክለኛ ነፃ ቀን ነበረኝ፣ ስለዚህ ይህን ቲኬት እንደገና ለመቅረፍ ወሰንኩ። በአእምሮዬ ውስጥ አንዳንድ የጀርባ ሂደት በዚህ ጊዜ ሁሉ ለዚህ ችግር መፍትሄ እየፈለገ እንደሆነ ተስፋ አድርጌ ነበር፣ እና በዚህ ጊዜ ምን እየተካሄደ እንዳለ በእርግጠኝነት እረዳለሁ።

በቀላሉ ኮዱን መቀየር ለመጨረሻ ጊዜ ስላላዋጣኝ ከመስመር 116 ጀምሮ እንደገና ልጽፈው ወሰንኩ። ያም ሆነ ይህ, ያለው ኮድ ሞኝ ነበር. እና እሱን መጠቀም በፍጹም አያስፈልግም read.

ስህተቱን እንደገና ስንመለከት፡-
sh: echo: broken pipe — አስተጋባ በዚህ ትእዛዝ ውስጥ በሁለት ቦታዎች ላይ ይታያል፣ ግን የመጀመሪያው የበለጠ ጥፋተኛ (ወይም ቢያንስ ተባባሪ) ሊሆን እንደሚችል እገምታለሁ። አውክ በራስ መተማመንን አያነሳሳም። እና በእውነቱ ከሆነ awk | {read; echo} ዲዛይኑ ወደ እነዚህ ሁሉ ችግሮች ይመራል, ለምን አይተካውም? ይህ ባለ አንድ መስመር ትዕዛዝ ሁሉንም የአውክ ባህሪያትን እና ሌላው ቀርቶ ተጨማሪውን አይጠቀምም። read በተጨማሪ.

ካለፈው ሳምንት ጀምሮ ሪፖርት ተደርጓል sed, አዲስ ያገኘሁትን ችሎታዬን ለመሞከር እና ለማቃለል ፈልጌ ነበር echo | awk | { read; echo} ይበልጥ ለመረዳት ወደሚችል echo | sed. ይህ በእርግጠኝነት ስህተትን ለመለየት የተሻለው መንገድ ባይሆንም፣ ቢያንስ የእኔን ሴድ-ፉ እንደምሞክር እና ምናልባት ስለ ችግሩ አዲስ ነገር ልማር ብዬ አስቤ ነበር። እግረ መንገዴን፣ የስራ ባልደረባዬን የሴድ ንግግር ደራሲ፣ የበለጠ ቀልጣፋ የሴድ ስክሪፕት ይዤ እንድመጣ እንዲረዳኝ ጠየቅኩት።

ይዘቱን ጣልኩት varnishadm vcl.show -v "$VCL_NAME" ወደ ፋይል፣ ስለዚህ የሴድ ስክሪፕቱን ያለአንዳች ውጣ ውረድ የአገልግሎት ዳግም ማስነሳት ላይ ማተኮር እችላለሁ።

በትክክል እንዴት ሴድ ሂደቶች ግብዓት እንደሚገኝ አጭር መግለጫ የእሱ የጂኤንዩ መመሪያ. በሴድ ምንጮች ውስጥ ምልክቱ 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, እና በግቤት ውሂቡ ውስጥ ብዙዎቹ ሊኖሩ ይችላሉ. ለዚህም ነው ከመጀመሪያው ግጥሚያ በኋላ ዋናው አዋክ ያበቃል.

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

ስለዚህ ፣ የቫርኒሽ ጫን ስክሪፕት ይዘቱ እንደዚህ ያለ ነገር ይመስላል።

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 እንደገና በፊታችን ሳቅን። ጠመዝማዛ ጠቋሚው በተርሚናሉ ጨለማ ባዶነት ውስጥ አዲስ ትዕዛዝ እስኪገባ እየጠበቀ ነበር...

ምንጭ: hab.com

አስተያየት ያክሉ