Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHPer's Guide to Daemon Crafting Taming and Sum...
Search
uzulla
March 22, 2025
Programming
2
1.6k
PHPer's Guide to Daemon Crafting Taming and Summoning
at: PHPerKaigi 2025
date: 2025/03/22
speaker: uzulla
uzulla
March 22, 2025
Tweet
Share
More Decks by uzulla
See All by uzulla
バイブスあるコーディングで ~PHP~ 便利ツールをつくるプラクティス
uzulla
1
340
似たもの同士のPerlとPHP
uzulla
1
240
More Context, Better Code. 既存コードやOAS等をコンテキストとしてLLMに与える事で、よりよいコード生成を行う話
uzulla
1
170
あなたのアプリ、ログはでてますか?あるいはログをだしてますか? (Funabashi.dev用 軽量版)
uzulla
3
270
セッションのトークセッション / Traps for PHP session features in growing web apps
uzulla
2
180
Crafting a Own PHP - ウキウキ手作りミニマリストPHP
uzulla
5
2.5k
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - How to use exceptions other than throwing
uzulla
5
1.2k
PHPerが ISUCONでやるべき事
uzulla
1
1.4k
開発生産性は上がらない - N Ways to Reduce Development Productivity
uzulla
1
310
Other Decks in Programming
See All in Programming
開発チーム・開発組織の設計改善スキルの向上
masuda220
PRO
13
7.3k
一人でAIプロダクトを作るための工夫 〜技術選定・開発プロセス編〜 / I want AI to work harder
rkaga
13
2.8k
Vibe coding コードレビュー
kinopeee
0
460
ワープロって実は計算機で
pepepper
2
1.4k
DynamoDBは怖くない!〜テーブル設計の勘所とテスト戦略〜
hyamazaki
1
210
コンテキストエンジニアリング Cursor編
kinopeee
1
700
LLMOpsのパフォーマンスを支える技術と現場で実践した改善
po3rin
8
980
A Gopher's Guide to Vibe Coding
danicat
0
170
GitHub Copilotの全体像と活用のヒント AI駆動開発の最初の一歩
74th
8
3.2k
レガシープロジェクトで最大限AIの恩恵を受けられるようClaude Codeを利用する
tk1351
2
1k
Honoアップデート 2025年夏
yusukebe
1
840
Introduction to Git & GitHub
latte72
0
120
Featured
See All Featured
Embracing the Ebb and Flow
colly
87
4.8k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
6k
Designing for humans not robots
tammielis
253
25k
Agile that works and the tools we love
rasmusluckow
329
21k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
Optimising Largest Contentful Paint
csswizardry
37
3.4k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
How STYLIGHT went responsive
nonsquared
100
5.7k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
53k
Transcript
PHPer's Guide to Daemon Crafting, Taming and Summoning
Re:લઆ
ݩؾͰ͔͢ʂ
ݩؾ͋ΕͳΜͰͰ͖Δʂ
͕ʂ PHPͱ͍͑ ApacheNginx͕͍ͳ͍ͱ͏͔͝ͳ͍ ಠΓཱͪͰ͖ͳ͍ݴޠ (ॾઆ͋Δ)
ࢲʮॻ͚ΔΖ(աڈͷτʔΫࢀর)ʯ ʁʮPHPͰhttpdΛॻ͘ is ͦ͠͏ʯ ࢲʮී௨ʹΕΑ͍(աڈͷτʔΫࢀর)ʯ ʁʮͦ͏͍͏ͱ͜ΖͰ͢Αʁʁʁʁʯ
! GoogleʮPHPͰσʔϞϯʁΒͳ͍ʂʯ ! CopolotʮαϙʔτͳΜͰ…ʯ ! ChatGPTʮ͍ͷແཧͰ͢ʯ
…ͦΜͳઈͷ͕࣌ଓ͖·ͨ͠ ʢԶҎ֎ͦ͏Ͱͳ͍͔ʁʁʁʁʣ
͔͠͠ʂ2025ʂʂʂʂ ͍ͭʹٹੈओ͕ݱΕͨʂʂ
Devin/Claude code:ɹɹ ʮ͑ɺ͓લPHPͰσʔϞϯॻ͚ͳ͍ͷʁ ॻ͍ͯΔΑʯ
͍ͭʹʮͳʹ͔Θ͔ΒΜ࣌ʯ͕ऴΘͬͨ… ʢ͍ɺਓؒͳʹ͔Θ͔͓ͬͯΒΜ͕ɺಈ࡞͢Δαϯϓϧ͕ݟΕΔʂʣ
Ͱɺͩɻ
ࠓճࢲAIʹίʔυΛॻ͔͍ͤͯ·͕͢ Θ͟ͱͰ͢
ෛ͚੯͠ΈͰͳ͘ʂʂʂ ࢲ͕ࣗθϩ͔ΒίʔυΛॻ͚ͳ͍Θ͚Ͱͳ͍ʂʂ(ͬͯ͠ΔͩΖʂ) ෛ͚੯͠ΈͰͳ͘ʂʂʂ Θ͟ͱͰ͢ʂʂʂʂʂʂ
օ͞Μ͕खʹೖΕΒΕΔͱ͍͏ࣄ͕ॏཁͳͷͰ͢ʂ
ʁʮPHPͰσʔϞϯʁ͍Έ͋Δͷʁʯ ࢲʮϩϚϯ͕͋Γ·͢ʂʂʂʂʂʂʯ
ҰൠతͳΠϝʔδ
ApacheNginxඞཁ͕ͳ͍ PHP γϯάϧϓϩηε୯ମͰಈ͘ϓϩάϥϜ ڵຯ͕͋Γ·ͤΜ͔ʂʁ(Զ͚͔ͩʁ)
ࠓճλΠτϧੌͭ͘·Βͳͦ͏͡Όͳ͍Ͱ͔͢ʂʂʂ Ͱ͍ͭʹγάφϧॲཧsystemdͷཱ͕ͭΜͰ͢ʂʂʂ
ʮѱ͍ͳɺσʔϞϯ࡞PHPʹແཧͳΜͩʯ ͏͍ΘͤͶ͑ͧʂʂʂ
CMS࡞ݴޠͱ͔͍ΘΕ͍ͯͨ PHPͷ͠Ϳͱ͞Λ ͋ΒͨΊͯΈͤͯΓ·͢Αʂʂʂ
ؓٳ
ʮԶ͕PHPerKaigiͩʂ(???)ʯ ‣ ͱɺݴ͑Δఔʹ(ʁ) ॳճ͔Βຖొஃ(લࡇؚΉ) ‣ ओʹPHPܥόοΫΤϯυΤϯδχΞ ‣ ʮઓʹಥવ͛ࠐ·ΕΔ༭ฌΛͯ͠ ͍·͢ʯ ‣
࠷ۙͷΈ ʮҰମԶ… ɹͲ͏ࣗݾհΛ͢Ε…ʁʯ
ݱࡏͷݱ(2025-03ݱࡏ) ‣ ༗ݶձࣾΦʔϓϯεϑΟΞ (CTO) ‣ גࣜձࣾΦτόϯΫ (όοΫΤϯυΤϯδχΞ) ‣ גࣜձࣾPR TIMES
(PHPεϖγϟϦετɺઌഐ) ‣ גࣜձࣾϦϯέʔδ (༯ਫ਼) ‣ ଞ֤ࣾ…(ΞʔΩςΫτίϯαϧPHPerຐআ͚ͳͲ)
ͦͷଞ൪એ ‣ Youtubeͷ uzulla chͰɺBaanSeenͳͲͷYoutubeͯ͠·͢ νϟϯωϧొͯ͠ʂग़ԋͯ͠ʂ ‣ ʮXdebugΛ։࢝͢Δ܅ʯͱ͍͏Chrome֦ுΛͭ͘Γ·ͨ͠ ੋඇ͔ͭͬͯ! ‣
BlueSkyʹɺͷPackagistࢹBotΛ෮׆ͤ͞·ͨ͠ʂ throwable.bsky.social (ݩͷxͷcall_user_func͔ΒϦϯΫͯ͋͠Γ·͢)
DISCLAIMER ‣ ͜ͷτʔΫɺ御社ͷαʔϏεʹPHPͷσʔϞϯΛಋೖ͢Δ ͜ͱΛお勧めしませんɻ ‣ (ݸਓαʔϏεͳΒɺԠԉ͠·͢ʂΏ͘Ώ͘ޚࣾʹ…ʁ) ‣ ࢲ͕ʮࣗPHPͰσʔϞϯΛॻ͘ΜͩʂʯͱݴΘΕͨΒɺ· ͣʮ΄͔ͷݴޠɺͬͯΈͨʁʯͱฉ͖·͢ɻ ‣
Δͱͯ͠ɺνʔϜͰेͳٞΛ͓͜ͳ͍·͠ΐ͏ɻ
ຊ σʔϞϯ࿉ ࣂ͍ͳΒ͠ ঌש ͷɺPHPer͚ΨΠυ
σʔϞϯͱʁ ‣ όοΫάϥϯυͰಈ࡞͢ΔৗறϓϩάϥϜ ‣ ࣗಈతʹىಈ͠ɺಛఆͷαʔϏελεΫΛܧଓతʹ࣮ߦ͠· ͢ ‣ Ϣʔβʔ͕ϩάΞτͯ͠ऴྃͤͣɺγεςϜγϟοτμϯ ·Ͱಈ࡞͠ଓ͚·͢ɻ ‣
ϢʔβʔͷΠϯλϥΫγϣϯͳ͠ʹಈ࡞͚ͭͮ͠Δ ‣ ྫ:Apache, Nginx, MySQL, PostgreSQL, crond, sshd
;ͭ͏ͷPHPͱσʔϞϯͷҧ͍ Start ϒϥβ Request Apache PHP script Start(reset) Process PHP
Response to ϒϥβ PHP script Finish(reset) ‣ ϦΫΤετ͕དྷͯϨεϙϯεΛฦ͢ɺຖճϦηοτ͞ΕΔ ‣ Θ͔Γ͍͢ʂ
όονͱσʔϞϯͷҧ͍ ‣ όονσʔϞϯʹʮࣅ͍ͯ·͢ʯ ‣ όονCronͳͲͰఆظతʹىಈͯ͠ऴྃ͢Δ ‣ Ұͷ࣮ߦͰ݁͢Δॲཧɺͱʹ͔͘ʮऴΘΓ͕͋Δʯ ‣ όονຖճऴྃ͢ΔͷͰσʔλετΞʹอଘͯ࣍͠ͷόον ʹඋ͑ΔͨΓ͢Δ
Cron։࢝ PHP script Start(reset) Process PHP Cronऴྃ PHP script Finish(reset)
Cron Cron
Batch(Cron)ͷݶքͱར ‣ ࠷খ࣮ߦִؒCronͳΒ1(௨ৗ) ‣ ಉ࣮࣌ߦͷ੍ޚ͕໘ɾ͍͠(ϩοΫ੍ޚ) ‣ CronʮʯదͰಈ͘
σʔϞϯ - Կ͔Λॲཧ͢ΔͷͰ͋Δ͕ɺϦΫΤετͱ͔Ϩεϙϯεඞ ਢͰͳ͍ɻ - NඵʹҰूܭͯ͠DBʹॻ͖ࠐΉͱ͔ - ঢ়ଶΛௐ͚͕ͭͮͯ͋ΕΞϥʔτΛSlackʹ͓͘Δͱ͔ - େྔͷσʔλΛʮԆॲཧͨ͠Γɾޮతʹɾॱ൪ʹʯॲཧ͢Δ
ͱ͔ - ͋ͱɺ(ඞཁ͕ͳ͚Ε)ऴྃ͠ͳ͍
MainLoop PHP script Start(reset) Systemd() Job ऴྃʁ Main Loop Entry
ॲཧA ॲཧN γάφϧ τϥοϓ NO ऴྃ ॲཧ YES killͳͲ γάφϧ ܧଓ ϑϥά ֬ೝ PHP script Finish( reset)
‣ Cronىಈִ͕ؒ͋Δ͕ɺσʔϞϯىಈִ͕ؒͳ͘ৗʹ࣮ߦ ‣ ىಈ͚ͭͮ͠ΔͷͰɺ࠶ଓɺΩϟογϡΛຖճಡΈࠐΉඞ ཁ͕ͳ͍ ‣ ʮఀࢭִؒʯ͕ͳ͍ͷͰɺଈ࠲ʹԠՄೳ ‣ ܧଓ͢ΔͷͰɺWebSocketͳͲͷଓΛҡ࣋Մೳ
σʔϞϯͷܽ ‣ ҆ఆͯ͠ಈ࡞͢ΔͷΛ࡞Δͷ͕͍͠ ͨͱ͑ϝϞϦϦʔΫɺDB࠶ଓॲཧͳͲ ‣ (όονී௨ͷWebϓϩάϥϜͱʹͨϊϦ) ‣ ҟৗऴྃͨ͠ͱ͖ʹ࠶ىಈͤͨ͞Γ͕໘ ‣ ଟ͘ͷ߹ɺόονREST
APIͰΑ͍Μ͚ ‣ ʑ…
ͳͥPHPͰσʔϞϯΛʁ(ݴ͍༁) ‣ PHPWebΞϓϦʴόονͱ͍͏Πϝʔδ͕ڧ͍ ‣ PHPͷࣝΛ׆͔͠ɺ༷ʑͳόοΫάϥϯυॲཧΛॻ͘ࣄ͕ Ͱ͖Ε… ‣ ΧοίΠΠ(ओ؍) ‣ ͜ͷลΓͷָ͓͠ΈޙͰ…
ૉͳσʔϞϯΛ࡞Δ 1. CLIεΫϦϓτͱͯ͠ىಈ 2. ϝΠϯϧʔϓͰܧଓ࣮ߦ 3. γάφϧϋϯυϦϯάͷ࣮
#"/usr/bin/env php <?php declare(strict_types=1); $running = true; pcntl_signal(SIGTERM, function ()
use (&$running) { // γάφϧϋϯυϥͷઃఆ echo "SIGTERMΛ͏͚ͱΓ·ͨ͠ɺऴྃ͠·͢" . PHP_EOL; $running = false; }); echo "σʔϞϯىಈ (PID: ".getmypid().")" . PHP_EOL; while ($running) { // ϝΠϯϧʔϓ pcntl_signal_dispatch(); // γάφϧΛड৴ͨ͠ॲཧ echo "." . PHP_EOL; sleep(5); /% CPUΛ༗͠ͳ͍Α͏ʹεϦʔϓ } echo "σʔϞϯऴྃ" . PHP_EOL;
$running = true; while ($running) { // ϝΠϯϧʔϓ pcntl_signal_dispatch(); //
γάφϧΛड৴ͨ͠ॲཧ echo "." . PHP_EOL; sleep(5); /" CPUΛ༗͠ͳ͍Α͏ʹεϦʔϓ } ‣ ແݶϧʔϓ(ϝΠϯϧʔϓ)͕͋Δ ‣ ʮා͍ʂʂʂʯ
$running = true; pcntl_signal(SIGTERM, function () use (&$running) { //
γάφϧϋϯυϥͷઃఆ echo "SIGTERMΛ͏͚ͱΓ·ͨ͠ɺऴྃ͠·͢" . PHP_EOL; $running = false; }); while ($running) { // ϝΠϯϧʔϓ pcntl_signal_dispatch(); // γάφϧΛड৴ͨ͠ॲཧ }
pcntl_signal(SIGTERM, function () use (&$running) { echo "SIGTERMΛ͏͚ͱΓ·ͨ͠ɺऴྃ͠·͢" . PHP_EOL;
$running = false; }); pcntl_signal(SIGHUP, function () use (&$running) { echo "SIGHUPΛ͏͚ͱΓ·ͨ͠ɺऴྃ͠·͢" . PHP_EOL; $running = false; }); pcntl_signal(SIGINT, function () use (&$running) { echo "SIGINTΛ͏͚ͱΓ·ͨ͠ɺऴྃ͠·͢" . PHP_EOL; $running = false; }); ‣ ड͚औΔγάφϧݸผઃఆ͕Ͱ͖·͢ ‣ γάφϧͷॲཧʮड͚औ͓͍ͬͯͯʯpcntl_signal_dispatch()Λݺͼग़ͯ͠ɺอཹதͷγάφϧΛॲ ཧ͠·͢ɻ͜ΕॏཁͳεςοϓͰɺ͜Ε͕ͳ͍ͱγάφϧϋϯυϥͰҙͷॲཧΛઃఆͰ͖·ͤΜɻ
γάφϧͷૹΓํ ‣ killίϚϯυͰૹ৴Ͱ͖·͢ɺPIDͷࢦఆ͕ඞཁͰ͢ ‣ PIDpsίϚϯυͰ֬ೝͰ͖·͢ $ kill {PID} $ kill
-HUP 1234 $ kill -TERM 1234 $ kill -USR1 1234 $ kill -KILL 1234 # ͜ΕOS͕ड͚औΓ·͢
ओཁͳγάφϧ ‣ SIGTERM (15): ਖ਼ৗऴྃཁٻ ‣ SIGINT (2): ΩʔϘʔυׂΓࠐΈʢCtrl+Cʣ ‣
SIGHUP (1): அɺ(Α͋͘Δͷ͕ઃఆ࠶ಡΈࠐΈ) ‣ SIGUSR1 (10), SIGUSR2 (12): Ϣʔβʔఆٛ ‣ SIGKILL (9): ڧ੍ऴྃʢัଊෆՄʣ
খ ‣ γάφϧͷҙຯʮࡉ͔͖͘·͍ͬͯ·ͤΜʯ ‣ Apache͕γάφϧͨΓͶ͍͑ͬͯͬͯɺWINCHΛѱ༻ͯ͠Δ͜ͱ Ұ෦Ͱ༗໊Ͱ͢Ͷ ‣ (WINCHΟϯυαΠζมߋͷγάφϧͰ͢) ‣ ࠷ѱɺεΫϩʔϧόʔ͕ͰΔ͚ͩͰɺApache͕ऴྃ͢ΔΜͰ͢ΑͶ…
‣ (ݹདྷɺCLIͰApacheΛىಈ͢Δਓ͕ؒ͏·ΕΔͱࢥͬͯͳ͔ͬͨ ΜͩΖ͏…)
None
খ:దͳऴྃॲཧ ‣ άϨʔεϑϧγϟοτμϯ ‣ ৽نॲཧΛఀࢭ͢Δ ‣ ਐߦதͷॲཧͷྃ͠ ‣ Ϧιʔεͷదͳղ์͠ ‣
ঢ়ଶͷอଘ͢Δ ‣ ऴྃεςʔλεͷ௨
pcntl_signal(SIGTERM, function () { echo "ऴྃॲཧΛ࣮ߦத..""; /$ ਐߦதͷδϣϒΛอଘ saveCurrentState(); /$
DBίωΫγϣϯΛΫϩʔζ DB:&getConn-(close(); echo "ਖ਼ৗʹऴྃ͠·ͨ͠ɻ"; exit 0; /$ TODO ·ͱʹ࣮ͤΑ }); ‣ ଞʹɺSIGTERMͳΒ register_shutdown_function Λ׆༻͢Δख͋Δ
σʔϞϯͷঌשํ๏ $ php daemon.php ‣ CLI ϓϩάϥϜͷΑ͏ʹͯ͠ঌש(ىಈ)͕Ͱ͖·͢ɻ ‣ λʔϛφϧΛด͡Δͱऴྃͯ͠͠·͏͜ͱͰ͢ ‣
։ൃʹศར͕ͩɺσʔϞϯΛࣂ͏ͱͯ͠ඍົ
ྫ: nohupΛ͏ํ๏ $ nohup php daemon.php & ‣ nohup: ϋϯάΞοϓγάφϧʢSIGHUPʣΛແࢹ͠·͢
‣ &: όοΫάϥϯυͰ࣮ߦ
ྫ: screen(tmux)ͳͲΛ͏ํ๏ # screenىಈ $ screen # σʔϞϯͳͲىಈ (screenͷதͰͷγΣϧ)$ php
daemon.php # Ctrl+A, DͰɺγΣϧΛΓͯ͠(σλον)ɺϓϩάϥϜΛऴྃͤͣʹϩάΞτͰ͖Δ # ޙͰ·ͨϩάΠϯͯ͠ɺ࠶։(Ξλον)Ͱ͖Δ $ screen -r ‣ ίωΫγϣϯ͕͖Εͯshell͕ऴྃͤͣɺ࠶ଓ͕Մೳ ‣ ։ൃ࣌ʹศར (࣮࣌ؒߦ͢ΔόονͰ͔ͭ͏ΑͶ) ‣ αʔόʔىಈ࣌ʹࣗಈىಈ͢ΔΑ͏ͳͷͰͳ͍
ίϯςφڥ FROM php:8.3-cli RUN docker-php-ext-install pcntl COPY -#from=composer /usr/bin/composer /usr/bin/composer
COPY . /keira WORKDIR /keira RUN composer install CMD /keira/bin/keira.php ‣ ͋ͱ docker run -it keira Ͱىಈ; ‣ ҙ: -it Φϓγϣϯ͕ͩɺ͠ͳ͍ͱγΣϧ͕ͳ͘ɺHUP͕Ͱ͖ͳ͍ͷͰऴ ྃผ్Δ͜ͱ
ຊ໋: systemdʹΑΔঌש ‣ SystemdLinuxͷαʔϏεཧσʔϞϯ [Unit] Description=PHP Sample Daemon After=network.target [Service]
Type=simple User=ww"-data ExecStart=/path/to/daemon.php Restart=on-failure RestartSec=5s Envfile=/etc/environment [Install] WantedBy=multi-user.target
systemctlʹΑΔૢ࡞ # αʔϏεͷొ $ systemctl enable php-daemon.service # αʔϏεͷ։࢝ $
systemctl start php-daemon.service # ঢ়ଶ֬ೝ $ systemctl status php-daemon.service # ఀࢭ $ systemctl stop php-daemon.service
Journalctl͍ͭͯ ‣ ϩάϑΝΠϧͷཧ͕ෆཁʂʢϩʔςʔγϣϯɺύʔϛογϣϯઃఆͳ Ͳʣ ‣ ߏԽσʔλͱͯ͠อଘ͞Εɺݕࡧ͕༰қ ‣ λΠϜελϯϓɺϗετ໊ɺϓϩηεIDͳͲͷϝλσʔλ͕ࣗಈతʹ ༩ ‣
γεςϜશମͷϩάͱ౷߹͞Εɺͷ૬ؔؔΛѲ͍͢͠ ‣ ϩάϨϕϧʹΑΔϑΟϧλϦϯά͕؆୯ ‣ ϩάग़ྗɺjournalctlίϚϯυͰ֬ೝͰ͖·͢ɻ
journalctlྫ # αʔϏεͷϩάΛදࣔ $ journalctl -u php-daemon.service # ࠷৽ͷϩάΛϑΥϩʔ $
journalctl -u php-daemon.service -f # ࠓͷϩάͷΈදࣔ $ journalctl -u php-daemon.service -#since today $ journalctl -u php-daemon.service -#since "2023-03-20 21:30:08" -#until "2023-03-20 22:30:08" # ΤϥʔϨϕϧͷϩάͷΈදࣔ $ journalctl -u php-daemon.service -p err # JSONܗࣜͰग़ྗ $ journalctl -u php-daemon.service -#output=json
ࢹͱ݈શੑ֬อ ‣ ϩάJournalctlͰࢹͰ͖Δ ‣ ʁʮͱ͍͑ɺҟৗऴྃͨ͠ΒͲ͏͢ΔͷʁPHP৴༻ͳ͍ ͠…ʯ ‣ ϔϧενΣοΫΛఆظతʹ࣮ߦͯ͠…ͱ͔͋Γ·͕͢ ‣ ͳΜͱɺҟৗऴྃͳΒSystemd͕࠶ىಈΛͬͯ͘Ε·
͢ʂʂʂ ศརʂʂʂʂ
༨ஊɿsystemdʹΑΔεέδϡʔϧ࣮ߦ ‣ ͱ͍͑ɺσʔϞϯϓϩάϥϜͳΜͯ࡞Γͨ͘ͳ͍ਓͷͨΊͷ systemdཱ͓ͪใ ‣ SystemdσʔϞϯͷىಈऴྃΛ͢Δ͚ͩͱ͓͍͖ɺεέ δϡʔϧ࣮ߦͰ͖ΔʹCronͷΘΓʹ͑Δ ‣ Cronͱ͕ͪͬͯϑΝΠϧΛઃஔͯ͠ཧ͢ΔͷͰɺIaCͱ૬ੑ͕ ྑ͍Ͱ͢
‣ Ұ࣌ఀࢭͱ͔ႈʹͰ͖·͢
systemdλΠϚʔϢχοτ # /etc/systemd/system/php-daemon.timer [Unit] Description=Run PHP daemon daily [Timer] OnCalendar=*-*-*
03:00:00 # ຖޕલ3࣌ʹ࣮ߦ AccuracySec=1s # ਫ਼Λ1ඵʹઃఆ [Install] WantedBy=timers.target
1Ҏʹυϯυϯ࣮ߦ͍ͨ͠߹ɺ͜ͷΑ͏ͳ͜ͱͰ͖·͢ [Unit] Description=My Job Service After=network.target [Service] Type=oneshot ExecStart=/path/to/your/script.sh [Unit]
Description=Run My Job every 10 seconds [Timer] OnUnitActiveSec=10s #લճͷ࣮ߦ͔Β10ඵޙʹ࠶࣮ߦ AccuracySec=1s [Install] WantedBy=timers.target
·ͱΊ ‣ Craft ‣ PHPͰσʔϞϯϓϩάϥϜ͕࡞Մೳ ‣ Taim ‣ γάφϧॲཧ͕ॏཁ ‣
summon ‣ systemdͳͲͷπʔϧΛ׆༻͠·͠ΐ͏
࣭λΠϜͦͷ1 ࣭͕͋͝ΕͲ͏ͧʂ
͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ PHPͰσʔϞϯΛʮࣂ͍ͳΒ͠ʯɺ࣮༻తʹӡ༻͠·͠ΐ͏ʂ (͔͖ͣ͞Μ https://x.com/i999rri τʔΫϨϏϡʔ͋Γ͕ͱ͏ʂ)
ͬͯɺ͜ΕͰऴΘΔΘ͚ͳ͍Ζ͕͍ʂʂʂ ͏ͣΒͪΌΜτʔΫΛΊΜͰʔʂʂʂ
͔͜͜Βָ͓͠ΈλΠϜ ‣ ʮPHPͰͭ͘ΒΕͨσʔϞϯͬͯͭΛΈͤͯ͋͛·͢Α…ʂʯ ‣ ʮ͑͑ͬPHPͰʂʁʯʮ͍ʂʂʯ ‣ ʮDemon(ѱຐ)Ͱͳ͘ʂʁʯʮ͍ʁʁʯ
Keira
None
‣ KeiraɺPHPͱamphpͰߏங͞ΕͨWebϞχλϦϯάΞϓϦ Ͱ͢ɻෳΛಉ࣌ࢹ͠ɺ͕ൃੜͨ͠ࡍʹϦΞϧλΠϜͰ௨ ͠·͢ɻ ‣ ϦΞϧλΠϜ௨ɿোൃੜ࣌ʹଈ࠲ʹSlack௨(※) ‣ WebSocketରԠɿϦΞϧλΠϜߋ৽ΛWebSocketͰఏڙ ‣ RESTful
APIɿγϯϓϧͳAPIͰࢹσʔλʹΞΫηε ‣ γάφϧ੍ޚɿUNIXγάφϧͰΞϓϦΛૢ࡞ ‣ ֤छΧελϚΠζࢹઃఆ
None
ࢲʮͲ͏Ͱ͢ʁʯ ʁʮJS Chart͓͔͘͠Ͷʁʯ ࢲʮຊ࣭Ͱͳ͍ʯ
ʢσʔϞϯͳΒͰͷʣӡ༻ʹ͑ΔϙΠϯτ ‣ Ұ࣌ఀࢭ͕ USR1,2 γάφϧͰͰ͖Δ ‣ ઃఆϑΝΠϧͷϦϩʔυΛHUPͰͰ͖Δ ‣ ࢹઌͷՃɺআɺҰ࣌ఀࢭͳͲΛαϙʔτ ‣
͜ͷ࣌ʹWebSocket͕அ͞ΕͨΓ͠·ͤΜ ‣ ౷ܭใ͖͑·ͤΜ ‣ ͳͥͳΒσʔϞϯͳͷͰ(ʁʁʁ)
None
Slack௨αϙʔτ͍ͯ͠Δʂ ‣ ͭΓ͕ͩͬͨɺࠓόάͬͯ·ͨ͠wwww ‣ ͳͷͰಈը͕ͳ͍ʂʂʂ ‣ ·͋ɺ͏͍ͨ͝ΜͩΑʂʂʂʂ৴ͯ͘͡Εʂʂʂʂ
Keiraͷίʔυͪ͜Β ‣ https://github.com/uzulla/Keira ‣ ҙ: ։ൃதͰ͢w ຊͷࢹʹ·ͩΘͳ͍Ͱ͍ͩ͘͞w
ͩ͜ΘΓϙΠϯτ ‣ WebsocketΛॲཧ͠ͳ͕Βɺࢹܧଓ͍ͯ͠Δ͠ɺREST API ͏͖͝·͢ʂ ‣ σʔϞϯͳͷͰɺDBͱ͔ෆཁʂ(σʔλมʹ͍ͬͯ·͢) ‣ 1ϓϩηεͳͷͰɺDockerίϯςφͱ͔Ͱಈ͔͢ͷָʑʂ (SystemdͷͲ͜ʹ…ʁ)
ίʔυ͓͠ΖϙΠϯτ ‣ amphpͳͷͰɺPure PHPͰ͢ (C֦ுෆཁ) ‣ ݁ߏಡΈ͔͍ͯ͋͘͢Γ·͢(ݸਓࠩ͋Δ) ‣ ApiServer.phpͱ͔ΈͯΈ͍ͯͩ͘͞ ‣
γάφϧॲཧɺUtil/SignalHandler.phpʹॻ͍ͯ͋Γ·͢ ‣ Application.php ͰɺػೳΛϚϯτ͍ͯ͘͠ͷ͕͓͠Ζ͍ ‣ Asyncͱ͔ɺCancelͱ͔͕͋Δ (ଞͷݴޠͬͯΔͻͱͳΒ͓͠Ζ͍Ͱ͠ΐ)
## Keira/src/Keira/Application.php /$ Create signal handler $this-&signalHandler = new SignalHandler($this-&configLoader,
$this-&monitorManager, $this-&appLogger); $this-&signalHandler-®ister(); /$ Create data retention manager $this-&dataRetention = new DataRetention($this-&monitorManager, $this-&appLogger); $this-&dataRetention-&start(); /$ Create API server $this-&apiServer = new ApiServer('0.0.0.0', 8080, $this-&monitorManager, $this-&appLogger); $this-&apiServer-&start(); /$ Start monitoring $this-&monitorManager-&start();
## KKeira/src/Keira/WebSocket/WebSocketHandler.php public function handleClient( ): void { $this-%gateway-%addClient($client); try
{ foreach ($client as $message) { $payload = $message; $this-%logger-%info("[INFO][APP] Received WebSocket message: {$payload}"); } } catch (\Throwable $e) { $this-%logger-%error("[ERROR][APP] WebSocket error: {$e-%getMessage()}"); } finally { $this-%logger-%info("[INFO][APP] WebSocket client disconnected"); } } /** * Broadcast monitor result to all connected clients *( private function broadcastResult(MonitorResult $result): void { $payload = json_encode($result-%toArray()); if ($payload) { $this-%gateway-%broadcastText($payload); } }
## Keira/src/Keira/Api/ApiServer.php private function registerRoutes(): void { /% GET /monitors
- List all monitors $this-'router-'addRoute('GET', '/monitors', new ClosureRequestHandler( function ($request) { $handler = new MonitorsHandler($this-'monitorManager); return $handler($request); } )); /% GET /ws-test - WebSocket test page $this-'router-'addRoute('GET', '/ws-test', new ClosureRequestHandler( function ($request) { $templatePath = '/websocket-test.html'; if (!file_exists($templatePath)) { return new \Amp\Http\Server\Response( status: 500, headers: ['Content-Type' =+ 'text/plain'], body: 'Template file not found' ); } $html = file_get_contents($templatePath); return new \Amp\Http\Server\Response( status: 200, headers: ['Content-Type' =+ 'text/html'], body: $html ); } ));
## Keira/src/Keira/Util/SignalHandler.php public function register(): void { /% SIGHUP: Reload
configuration async(function () { while (true) { try { trapSignal(\SIGHUP); $this-(handleSighup(); } catch (SignalException $e) { /% Signal handler was cancelled break; } } });
·ͱΊ2 ‣ PHPͰɺ࣮༻తͳσʔϞϯ͕࡞ΕΔʂ ‣ ͔͠ɺҊ֎ಡΊΔʂ(ݸਓࠩ͋Γ·͢) ‣ νϡʔχϯά(CPUෛՙ)ͱ͔·ͩ·ͩͰ͢ɻ Ͱɺಈ͘͜ͱ͕Θ͔ΔɺͦΕ͕࢝·ΓͰ͢ʂʂʂ
ʮΦϨͨͪ·ͩΓ࢝Ί͔ͨΓ͔ͩΒͳɻ ͜ͷͯ͠ͳ͘ԕ͍σʔϞϯ࿉ΛΑ…!ʯ
One more thing...
DB-monitor ‣ https://github.com/uzulla/db-monitor ‣ ʮՔಇதͷσʔλϕʔεͷ౷ܭใΛϦΞϧλΠϜʹදࣔ͠ɺվળʹ ཱͯΔใΛऔಘ͢ΔπʔϧͰ͢ʯ ‣ DBʹৗ࣌ଓͯ͠ɺΫΤϦΛϞχλʔ͢ΔπʔϧΛͭ͘Γ͔ͨͬͨ ‣ ʮPHPͰʂʂʂʂʂʂʂʂʂʯ
‣ ͳͥͳΒPHPͳΒɺ৭ʑͳਖ਼نදݱͱָ͔͕ʹ͑Δ͠ɺίʔυ͕ಡΈ ͍͔͢Β(ݸਓࠩ͋Δ) ‣ ͜ΕamphpͰॻ͍ͯ·͢
None
None
͓ΘΓ ‣ ࣭͋Γ·͔͢ʁ ‣ ͳ͍ͳΒɺthrowable.bsky.social ͷσϞͰ͢Δ