りサギの穎に萜ちる: ワニスの再起動゚ラヌの物語 - パヌト 1

ゎスティヌシャンカ、たるで自分の呜がかかっおいるかのように、前の20分間ボタンを連打した埌、圌の目に半野生の衚情ず陰険な笑みを浮かべお私に向き盎った - 「おい、わかったような気がする」。

「ここを芋おください」ず圌は画面䞊の蚘号の XNUMX ぀を指しお蚀い、「きっずあなたは赀い垜子をかぶっおいるでしょう。私がここに送った内容を远加すれば、゚ラヌは衚瀺されなくなりたす」ずコヌドの別のセクションを指さしたす。

少し圓惑しお疲れたので、しばらく䜜業しおきた sed ステヌトメントを倉曎し、ファむルを保存しお実行したす。 systemctl varnish reload。 ゚ラヌメッセヌゞが消えおしたいたした 

「候補者ずやり取りしたメヌルです」ず同僚は続け、笑い声​​が喜びに満ちた本物の笑顔に倉わりたした。「これがたさに同じ問題であるこずに突然気づきたした」

すべおはどのように始たったのか

この蚘事は、bash、awk、sed、systemd の仕組みを理解しおいるこずを前提ずしおいたす。 ワニスの知識があるこずが望たしいですが、必須ではありたせん。
スニペットのタむムスタンプが倉曎されたした。
で曞いた ゎスティヌシャンカ.
この文章は XNUMX 週間前に英語で出版された原文の翻蚳です。 翻蚳 少幎行䌝.

別の暖かい秋の朝、パノラマの窓から倪陜が茝き、淹れたおのカフェむン入りドリンクがキヌボヌドから離れ、お気に入りの音のシンフォニヌがヘッドフォンのメカニカルキヌボヌドのカサカサ音に乗っお流れ、カンバンボヌド䞊のバックログチケットリストの最初の゚ントリが、ふざけお運呜的なタむトル「Investigate varnishreload sh: echo: I/O error in staging」で茝きたす「Investigate varnishreload sh : echo: I/O error in staging」。 』の舞台。 ワニスに関しおは、今回のように問題が生じなかったずしおも、間違いはありたせんし、あっおはならないのです。

なじみのない人のために ワニスリロヌド、これは構成を再ロヌドするために䜿甚される単玔なシェル スクリプトです。 ワニス - VCLずも呌ばれたす。

チケットのタむトルが瀺すように、ステヌゞ内のサヌバヌの 30 ぀で゚ラヌが発生したした。ステヌゞ内での varnish のルヌティングが正しく機胜しおいるず確信しおいたので、これは軜埮なミスだろうず想定しおいたした。 したがっお、すでに閉じられた出力ストリヌムに入ったメッセヌゞだけです。 私は自分のためにチケットを受け取り、XNUMX 分以内に準備完了のマヌクを付け、次のゞャンクをボヌドから片付けお、より重芁な䜜業に戻るために自分の肩をたたいお自信を持っおいたす。

時速200kmで壁に衝突

ファむルを開く varnishreload、Debian Stretch を実行しおいるサヌバヌの 200 ぀で、長さが XNUMX 行未満のシェル スクリプトを芋぀けたした。

スクリプトを実行したずころ、タヌミナルから盎接耇数回実行したずきに問題を匕き起こす可胜性のあるものは䜕も芋぀かりたせんでした。

結局のずころ、これは舞台です、たずえ壊れたずしおも誰も文句を蚀いたせん、たあ...あたりにも倚くはありたせん。 スクリプトを実行しお端末に䜕が曞き出されるかを確認したすが、゚ラヌは衚瀺されなくなりたした。

さらに数回実行しお、特別な努力をしないず゚ラヌを再珟できないこずを確認し、このスクリプトを倉曎しお匕き続き゚ラヌをスロヌさせる方法を考え始めたす。

スクリプトは STDOUT をブロックできたすか (䜿甚 > &- それずも暙準゚ラヌ? 結局どちらも機胜したせんでした。

systemd が䜕らかの方法で実行環境を倉曎するのは明らかですが、どのように、そしおなぜなのでしょうか?
vimを起動しお線集したす varnishreload、远加 set -x スクリプトの出力をデバッグするこずで䜕らかの光が圓たるこずを期埅しお、シバンのすぐ䞋にありたす。

ファむルは修正されたので、ワニスをリロヌドするず、倉曎によっおすべおが完党に壊れおいるこずがわかりたす...排気は完党に混乱しおおり、C のようなコヌドが倧量に含たれおいたす。 タヌミナル内をスクロヌルしおも、どこから始たるのかを芋぀けるのに十分ではありたせん。 私は完党に混乱しおいたす。 デバッグ モヌドは、スクリプトで実行されるプログラムの動䜜に圱響を䞎える可胜性がありたすか? いや、でたらめだ。 シェルのバグ? 考えられるいく぀かのシナリオが、ゎキブリのように頭の䞭でさたざたな方向に飛び亀っおいたす。 カフェむンたっぷりの飲み物はすぐに空になり、すぐにキッチンに行っおカフェむンを補絊しお さあ、出発です。 スクリプトを開いおシバンを詳しく芋おみたしょう。 #!/bin/sh.

/bin/sh - これは単なる bash シンボリックリンクなので、スクリプトは POSIX 互換モヌドで解釈されたすね。 そこにはなかったのです Debian のデフォルトのシェルはダッシュです。これはたさにそれです。 蚀及する /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_SHOW115 行目で䜜成された、パむプを介しお次のコマンドに送信されたす。 そしおそこで䜕が起こるのでしょうか

たず、䜿甚するのは、 varnishadmvarnish むンストヌル パッケヌゞの䞀郚であり、再起動せずに varnish を構成したす。

サブコマンド vcl.show -v で指定された VCL 蚭定党䜓を出力するために䜿甚されたす。 ${VCL_NAME}、STDOUTに。

珟圚アクティブな VCL 蚭定ず、メモリ内にただ残っおいるいく぀かの以前のバヌゞョンの varnish のルヌティング蚭定を衚瀺するには、次のコマンドを䜿甚できたす。 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 行目から始たる倧量のコマンドでは䜕が起こるのでしょうか?
それに盎面しおみたしょう。
コマンドは XNUMX ぀の郚分で構成されたす。

  1. 単玔な echo、倉数の倀を衚瀺したす ${VCL_SHOW}
    echo "$VCL_SHOW"
  2. awk、行 (レコヌド) を怜玢したす。テキストを分割した埌の最初のフィヌルドは「//」、XNUMX 番目のフィヌルドは「VCL.SHOW」になりたす。
    awk は、これらのパタヌンに䞀臎する最初の行を曞き出しお、すぐに凊理を停止したす。

    awk '$1 == "//" && $2 == "VCL.SHOW" {print; exit}'
  3. スペヌスで区切られた XNUMX ぀の倉数にフィヌルド倀を栌玍するコヌドのブロック。 XNUMX 番目の倉数 FILE は行の残りを受け取りたす。 最埌に、最埌の゚コヌは倉数の内容を曞き蟌みたす。 ${FILE}.
    { read -r DELIM VCL_SHOW INDEX SIZE FILE; echo "$FILE" }
  4. ステップ 1  3 はすべおサブシェルで囲たれおいるため、倀の出力は $FILE 倉数に曞き蟌たれたす VCL_FILE.

119 行目のコメントが瀺すように、これは、VCL が名前に空癜文字を含むファむルを参照する堎合を確実に凊理するずいう唯䞀の目的を果たしたす。

元の凊理ロゞックをコメントアりトしたした。 ${VCL_FILE} コマンドの順序を倉曎しようずしたしたが、䜕も起こりたせんでした。 私にずっおはすべお問題なく動䜜したしたが、サヌビスを開始する堎合にぱラヌが発生したした。

スクリプトを手動で実行するず゚ラヌが単玔に再珟できないようですが、掚定 30 分がすでに XNUMX 回終了しおおり、さらに優先床の高いタスクが衚瀺され、残りのケヌスが脇に远いやられおいたす。 週の残りの時間はさたざたなタスクでいっぱいでしたが、SED に関する講挔ず候補者ずの面接で少し薄められただけでした。 ゚ラヌの問題 varnishreload 時間の砂の䞭に取り返しの぀かないほど倱われた。

あなたのいわゆるセフ...実際...ゎミ

翌週はかなり空いおいた日があったので、再床このチケットを利甚するこずにしたした。 私の脳内では、バックグラりンドのプロセスがずっずこの問題の解決策を探しおいたので、今回は間違いなく䜕が問題なのかを理解できるだろうず期埅しおいたした。

前回はコヌドを倉曎しただけではダメだったので、116行目から曞き盎すこずにしたした。 いずれにせよ、既存のコヌドは愚かでした。 そしお、䜿甚する必芁はたったくありたせん read.

もう䞀床゚ラヌを芋おみたしょう:
sh: echo: broken pipe - このコマンドでは、゚コヌは XNUMX か所にありたすが、最初のほうが犯人 (少なくずも共犯者) である可胜性が高いず思われたす。 Awk も自信を呌び起こしたせん。 そしお、それが本圓にそうな堎合に備えお、 awk | {read; echo} この蚭蚈がこれらすべおの問題を匕き起こすのであれば、なぜ亀換しないのでしょうか? この XNUMX 行のコマンドは、awk のすべおの機胜を䜿甚するわけではありたせん。 read 付属品で。

先週から報道がありたしたので、 sed新しく習埗したスキルを詊しお簡玠化したいず思った echo | awk | { read; echo} より分かりやすく echo | sed。 これは間違いなくバグを発芋するための最良のアプロヌチではありたせんが、少なくずも自分の sed-fu を詊しお、問題に぀いお䜕か新しいこずを孊がうず考えたした。 その過皋で、私は同僚である sed トヌク ラむタヌに、より効率的な sed スクリプトを考え出すのを手䌝っおくれるよう頌みたした。

内容を萜ずしおしたいたした varnishadm vcl.show -v "$VCL_NAME" これにより、サヌビスを再起動する手間をかけずに sed スクリプトの䜜成に集䞭できたす。

sed が入力を凊理する正確な方法の簡単な説明は、次の堎所にありたす。 圌のGNUマニュアル。 sed ゜ヌスのシンボル n 行区切り文字ずしお明瀺的に指定されたす。

同僚のアドバむスを受けお、数回のパスを経お、元の 116 行目党䜓ず同じ結果が埗られる sed スクリプトを䜜成したした。

以䞋は入力デヌタを含むサンプル ファむルです。

> 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 たた私たちの顔に向かっお笑った。 タヌミナルの暗い空間で、りィンクするカヌ゜ルが新しいコマンドの入力を埅っおいたした...

出所 habr.com

コメントを远加したす