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.7k
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
360
似たもの同士のPerlとPHP
uzulla
1
250
More Context, Better Code. 既存コードやOAS等をコンテキストとしてLLMに与える事で、よりよいコード生成を行う話
uzulla
1
180
あなたのアプリ、ログはでてますか?あるいはログをだしてますか? (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.6k
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - How to use exceptions other than throwing
uzulla
6
1.2k
PHPerが ISUCONでやるべき事
uzulla
1
1.4k
開発生産性は上がらない - N Ways to Reduce Development Productivity
uzulla
1
320
Other Decks in Programming
See All in Programming
Django Ninja による API 開発効率化とリプレースの実践
kashewnuts
0
920
ソフトウェア設計の実践的な考え方
masuda220
PRO
3
470
育てるアーキテクチャ:戦い抜くPythonマイクロサービスの設計と進化戦略
fujidomoe
1
150
エンジニアとして高みを目指す、 利益を生み出す設計の考え方 / design-for-profit
minodriven
23
12k
Playwrightはどのようにクロスブラウザをサポートしているのか
yotahada3
7
2.3k
Introducing ReActionView: A new ActionView-Compatible ERB Engine @ Kaigi on Rails 2025, Tokyo, Japan
marcoroth
3
920
非同期jobをtransaction内で 呼ぶなよ!絶対に呼ぶなよ!
alstrocrack
0
520
XP, Testing and ninja testing ZOZ5
m_seki
2
280
明日から始めるリファクタリング
ryounasso
0
110
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
580
iOS 17で追加されたSubscriptionStoreView を利用して5分でサブスク実装チャレンジ
natmark
0
580
Web Components で実現する Hotwire とフロントエンドフレームワークの橋渡し / Bridging with Web Components
da1chi
3
1.7k
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
54
3k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
Code Review Best Practice
trishagee
72
19k
Optimising Largest Contentful Paint
csswizardry
37
3.4k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
23
1.5k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
32
2.2k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
51k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
What's in a price? How to price your products and services
michaelherold
246
12k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
How to Ace a Technical Interview
jacobian
280
23k
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 ͷσϞͰ͢Δ