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.2k
2
Share
PHPer's Guide to Daemon Crafting Taming and Summoning
at: PHPerKaigi 2025
date: 2025/03/22
speaker: uzulla
uzulla
March 22, 2025
More Decks by uzulla
See All by uzulla
ALL CODE BASE ARE BELONG TO STUDY
uzulla
30
7.7k
バイブスあるコーディングで ~PHP~ 便利ツールをつくるプラクティス
uzulla
1
560
似たもの同士のPerlとPHP
uzulla
1
300
More Context, Better Code. 既存コードやOAS等をコンテキストとしてLLMに与える事で、よりよいコード生成を行う話
uzulla
1
220
あなたのアプリ、ログはでてますか?あるいはログをだしてますか? (Funabashi.dev用 軽量版)
uzulla
3
320
セッションのトークセッション / Traps for PHP session features in growing web apps
uzulla
2
230
Crafting a Own PHP - ウキウキ手作りミニマリストPHP
uzulla
5
3.2k
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - How to use exceptions other than throwing
uzulla
6
1.5k
PHPerが ISUCONでやるべき事
uzulla
1
1.7k
Other Decks in Programming
See All in Programming
プロパティの順序で型推論が壊れる!? TypeScript6.0の修正からContext-Sensitivityの仕組みを追う
bicstone
2
980
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
120
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
3
570
開発とはなにか、Essenceカーネルで見えるもの
ukin0k0
0
210
サーバーレスで作る、動画データ管理基盤
oyasumipants
0
240
TSKaigi2026-静的解析への投資がAI時代のコード品質を支える ── カスタムESLintルールの設計と運用
hayatokudou
6
1.1k
Copilot CLI の継戦能力を高める コンテキスト管理
nozomutu
1
910
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
940
デフォルト運用のCodeRabbit、1年で何が変わったか / How CodeRabbit Changed Our Code Review in 1 Year
bake0937
1
100
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
220
AI駆動開発勉強会 広島支部 第一回勉強会 AI駆動開発概要とワークショップ
hayatoshimiu
0
360
横断組織出身のQAEがインプロセスQAEでつまずいたこと・活かせたこと
ty89
0
180
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
Facilitating Awesome Meetings
lara
57
6.9k
Navigating Weather and Climate Data
rabernat
0
200
Balancing Empowerment & Direction
lara
6
1.1k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Agile that works and the tools we love
rasmusluckow
331
21k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
810
Java REST API Framework Comparison - PWX 2021
mraible
34
9.3k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
RailsConf 2023
tenderlove
30
1.4k
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 ͷσϞͰ͢Δ