Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
PHPer's Guide to Daemon Crafting Taming and Sum...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
uzulla
March 22, 2025
Programming
2.8k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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.8k
バイブスあるコーディングで ~PHP~ 便利ツールをつくるプラクティス
uzulla
1
600
似たもの同士のPerlとPHP
uzulla
1
320
More Context, Better Code. 既存コードやOAS等をコンテキストとしてLLMに与える事で、よりよいコード生成を行う話
uzulla
1
240
あなたのアプリ、ログはでてますか?あるいはログをだしてますか? (Funabashi.dev用 軽量版)
uzulla
3
340
セッションのトークセッション / Traps for PHP session features in growing web apps
uzulla
2
240
Crafting a Own PHP - ウキウキ手作りミニマリストPHP
uzulla
5
3.3k
例外を投げるのをやめてみないか? あるいは受け入れてみないか? - How to use exceptions other than throwing
uzulla
6
1.5k
PHPerが ISUCONでやるべき事
uzulla
1
1.8k
Other Decks in Programming
See All in Programming
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
7
2.6k
Kiroで創り、AgentCoreで繋ぐ!AWSで実践する「AI-DLC」から「AIエージェント統合」までの最新地図
licux
3
380
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
130
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
760
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
5
1.3k
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
220
週末にAI-DLCを本気で回したら$1,600溶けた
hbashimizu
0
130
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
180
AIとGame Jamで、ゲームを完成させた話
takahirosaeki
0
110
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
140
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
3
270
巨大モノリシックアプリ モダン化大作戦
ktcryomm
0
310
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
230
Discover your Explorer Soul
emna__ayadi
2
1.3k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
230
Everyday Curiosity
cassininazir
0
310
Building Adaptive Systems
keathley
44
3.2k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
270
Optimizing for Happiness
mojombo
378
71k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
Odyssey Design
rkendrick25
PRO
2
800
ラッコキーワード サービス紹介資料
rakko
1
4.8M
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 ͷσϞͰ͢Δ