A várakozási ciklusunk 35 órát várt önmagára: pgrep -f és pkill -f SSH-n keresztül
Üzemeltetés
Október 31-én indítottunk egy kis ciklust SSH-n keresztül: várjunk, amíg egy másik gépen futó fordítási feladat be nem fejeződik, majd futtassunk egy utólagos feladatot. A fordítási feladat aznap este befejeződött. Amikor két nappal később újra megnéztük, a ciklus 35 órát várt, és az utólagos feladat soha nem futott le.
Mi volt a ciklus
ssh build-host 'while pgrep -f "i18n_job.py example.com" >/dev/null; do sleep 30; done; ./follow-up.sh'
A pgrep -f egy mintát vet egybe minden folyamat teljes parancssorával. Az SSH az idézett parancsot bash -c 'while pgrep -f "i18n_job.py example.com" …' alakban futtatja, és ez a parancssor tartalmazza a mintát. A pgrep a saját folyamatát kihagyja az eredmények közül, de azt a shellt nem, amelyik elindította. Tehát amíg a ciklus élt, talált egy egyezést: önmagát.
Ikertestvére: a pkill -f megöli azt a shellt, amelyben fut
Ugyanez történik a pkill -f esetén is, rosszabb következményekkel:
ssh build-host 'pkill -f "worker.py --queue a"; nohup python3 worker.py --queue a &'
A shell saját parancssora tartalmazza a mintát, ezért a pkill megöli a shellt. A munkás leáll, és soha többé nem indul el újra, az SSH pedig 255-ös kilépési kóddal zárul hibaüzenet nélkül. Idézési problémának tűnik, aminek mi is első alkalommal néztük.
Szeptember és október vége között legalább tizenegyszer estünk bele az egyikbe vagy a másikba: újraindítások, amelyek soha nem történtek meg, egy ciklus, amely három és fél órán át tartott egy ellenőrzést, egy másik, amely 50 percig tartott egy fordítási sort, és ez az eset.
Amit most csinálunk
- Zárójel a mintában:
pgrep -f "[i]18n_job.py example.com". Reguleris kifejezésként a[i]az i betűt egyezteti, így a feladat továbbra is egyezik; a shell parancssora tartalmazza a[i]karaktereket, amelyekre a kifejezés nem illeszkedik. Ez csak akkor segít, ha a sima minta sehol máshol nem jelenik meg abban a sorban: egy későbbi újraindítási parancs ugyanabban a sorban újra egyezni fog. - Keresés, leállítás és indítás külön SSH-hívásokban. Az egyik hívás kilistázza a folyamatokat
pgrep -afsegítségével, a következő megöli a kiírt PID-eket, a harmadik elindítja az új folyamatot. - PID-re várjunk, ne mintára:
tail --pid=1234 -f /dev/null, vagywhile kill -0 1234; do sleep 30; done. - Jobb, ha a systemd veszi át a feladatot. Futtassa egységként, és kérdezze le a
systemctl is-activeparanccsal, vagy indítsa el asystemd-run --waitparanccsal. Nincs rossz mintázat, amit el lehet rontani. - Minden várakozás kap határidőt (
timeout 3h), és jelzi, mikor adja fel. A határidő nélküli ciklus néma csendben bukik el.
Factory Floor, a csomag, amely a gépeinket futtatja, systemd egységeken keresztül működik: soha nem keres folyamatot a parancssora alapján. Azok a ciklusok csaptak be minket, amelyeket kézzel írtunk.