Нашиот циклус за чекање чекаше 35 часа за самиот себе: pgrep -f и pkill -f преку SSH
Операции
На 31 октомври започнавме мал циклус преку SSH: чекај додека преведувачка задача на друга машина не заврши, па потоа пушти следна задача. Преведувачката задача заврши таа вечер. Кога повторно погледнавме два дена подоцна, циклусот чекаше 35 часа, а следната задача никогаш не била пуштена.
Што беше циклусот
ssh build-host 'while pgrep -f "i18n_job.py example.com" >/dev/null; do sleep 30; done; ./follow-up.sh'
pgrep -f споредува шаблон со целата командна линија на секоја процес. SSH ја извршува наведнатата команда како bash -c 'while pgrep -f "i18n_job.py example.com" …', а таа командна линија го содржи шаблонот. pgrep го исклучува сопствениот процес од резултатите, но не и школка (shell) што го стартувала. Значи, сè додека циклусот беше жив, наоѓаше совпаѓање: самиот себе.
Неговиот близнак: pkill -f ја убива школка (shell) во која се извршува
Истото се случува и со pkill -f, но со полоши последици:
ssh build-host 'pkill -f "worker.py --queue a"; nohup python3 worker.py --queue a &'
Командната линија на самата школка (shell) го содржи шаблонот, па затоа pkill ја убива школка (shell). Работникот (worker) е запрен и никогаш повеќе не е стартуван, а SSH излегува со код 255 без порака за грешка. Изглега како проблем со наводниците, што и ние првобитно мислевме дека е.
Од септември до крајот на октомври упаднавме во едната или другата ситуација најмалку десетина пати: рестартирања што никогаш не се случија, циклус што држеше проверка три и пол часа, друг што држеше преведувачка редица 50 минути, и овој.
Што правиме сега
- Заграда во шаблонот:
pgrep -f "[i]18n_job.py example.com". Како регуларен израз,[i]ја совпаѓа буквата i, па задачата сè уште се совпаѓа; командната линија на школка (shell) ги содржи знаците[i], што изразот не ги совпаѓа. Ова помага само ако обичниот шаблон не се појавува никаде друго на таа линија: команда за рестартирање подоцна на истата линија повторно се совпаѓа. - Најдете, запрете и стартувајте во посебни SSH повици. Еден повик ги наведува процесите со
pgrep -af, следниот ги убива испишаните PID-ови, а третот го стартува новиот процес. - Чекајте на PID, а не на шаблон:
tail --pid=1234 -f /dev/null, илиwhile kill -0 1234; do sleep 30; done. - Уште подобро, оставете systemd да го преземе задолжението. Пуснете го како unit и прашајте со
systemctl is-active, или стартувајте го соsystemd-run --wait. Нема шаблон кој може погрешно да се имплементира. - Секој чекање добива краен рок (
timeout 3h) и вели кога ќе одустани. Петља без краен рок неуспешно завршува без известување.
Factory Floor, комплетот што ги движи нашите машини, работи преку systemd units: тој никогаш не бара процес по неговата командна линија. Петлите што нè измамија беа оние што ги напишавме рачно.