Slide 1

Slide 1 text

PHPer's Guide to Daemon Crafting, Taming and Summoning

Slide 2

Slide 2 text

Re:લઆ

Slide 3

Slide 3 text

ݩؾͰ͔͢ʂ

Slide 4

Slide 4 text

ݩؾ͸͋Ε͹ͳΜͰ΋Ͱ͖Δʂ

Slide 5

Slide 5 text

͕ʂ PHPͱ͍͑͹ Apache΍Nginx͕͍ͳ͍ͱ͏͔͝ͳ͍ ಠΓཱͪͰ͖ͳ͍ݴޠ (ॾઆ͋Δ)

Slide 6

Slide 6 text

ࢲʮॻ͚Δ΍Ζ(աڈͷτʔΫࢀর)ʯ ʁʮPHPͰhttpdΛॻ͘ is ೉ͦ͠͏ʯ ࢲʮී௨ʹ΍Ε͹Α͍(աڈͷτʔΫࢀর)ʯ ʁʮͦ͏͍͏ͱ͜ΖͰ͢Αʁʁʁʁʯ

Slide 7

Slide 7 text

! GoogleʮPHPͰσʔϞϯʁ஌Βͳ͍ʂʯ ! Copolotʮ๻͸αϙʔτͳΜͰ…ʯ ! ChatGPTʮ௕͍ͷ͸ແཧͰ͢ʯ

Slide 8

Slide 8 text

…ͦΜͳઈ๬ͷ࣌୅͕ଓ͖·ͨ͠ ʢԶҎ֎͸ͦ͏Ͱ΋ͳ͍͔ʁʁʁʁʣ

Slide 9

Slide 9 text

͔͠͠ʂ2025೥ʂʂʂʂ ͍ͭʹٹੈओ͕ݱΕͨʂʂ

Slide 10

Slide 10 text

Devin/Claude code:ɹɹ ʮ͑ɺ͓લPHPͰσʔϞϯॻ͚ͳ͍ͷʁ ॻ͍ͯ΍ΔΑʯ

Slide 11

Slide 11 text

͍ͭʹʮͳʹ΋͔΋Θ͔ΒΜ࣌୅ʯ͕ऴΘͬͨ… ʢ͍΍ɺਓؒ͸ͳʹ΋͔΋Θ͔ͬͯ͸͓ΒΜ͕ɺಈ࡞͢Δαϯϓϧ͕ݟΕΔʂʣ

Slide 12

Slide 12 text

Ͱɺͩɻ

Slide 13

Slide 13 text

ࠓճࢲ͸AIʹίʔυΛॻ͔͍ͤͯ·͕͢ Θ͟ͱͰ͢

Slide 14

Slide 14 text

ෛ͚੯͠ΈͰ͸ͳ͘ʂʂʂ ࢲࣗ਎͕θϩ͔ΒίʔυΛॻ͚ͳ͍Θ͚Ͱ͸ͳ͍ʂʂ(ͬͯ͠ΔͩΖʂ) ෛ͚੯͠ΈͰ͸ͳ͘ʂʂʂ Θ͟ͱͰ͢ʂʂʂʂʂʂ

Slide 15

Slide 15 text

օ͞Μ͕खʹೖΕΒΕΔͱ͍͏ࣄ͕ॏཁͳͷͰ͢ʂ

Slide 16

Slide 16 text

ʁʮPHPͰσʔϞϯʁ͍Έ͋Δͷʁʯ ࢲʮϩϚϯ͕͋Γ·͢ʂʂʂʂʂʂʯ

Slide 17

Slide 17 text

ҰൠతͳΠϝʔδ

Slide 18

Slide 18 text

Apache΋Nginx΋ඞཁ͕ͳ͍ PHP γϯάϧϓϩηε୯ମͰಈ͘ϓϩάϥϜ ڵຯ͕͋Γ·ͤΜ͔ʂʁ(Զ͚͔ͩʁ)

Slide 19

Slide 19 text

ࠓճλΠτϧੌͭ͘·Βͳͦ͏͡Όͳ͍Ͱ͔͢ʂʂʂ Ͱ΋͍ͭʹγάφϧॲཧ΍systemd౳ͷ࿩୊͕໾ཱͭΜͰ͢ʂʂʂ

Slide 20

Slide 20 text

ʮѱ͍ͳɺσʔϞϯ੡࡞͸PHPʹ͸ແཧͳΜͩʯ ΋͏͍ΘͤͶ͑ͧʂʂʂ

Slide 21

Slide 21 text

CMS࡞੒ݴޠͱ͔͍ΘΕ͍ͯͨ PHPͷ͠Ϳͱ͞Λ ͋ΒͨΊͯΈͤͯ΍Γ·͢Αʂʂʂ

Slide 22

Slide 22 text

ؓ࿩ٳ୊

Slide 23

Slide 23 text

ʮԶ͕PHPerKaigiͩʂ(???)ʯ ‣ ͱɺݴ͑Δఔ౓ʹ(ʁ) ॳճ͔Βຖ೥ొஃ(લ໷ࡇؚΉ) ‣ ओʹPHPܥόοΫΤϯυΤϯδχΞ ‣ ʮઓ৔ʹಥવ౤͛ࠐ·ΕΔ༭ฌΛͯ͠ ͍·͢ʯ ‣ ࠷ۙͷ೰Έ ʮҰମԶ͸… ɹͲ͏ࣗݾ঺հΛ͢Ε͹…ʁʯ

Slide 24

Slide 24 text

ݱࡏͷݱ৔(2025-03ݱࡏ) ‣ ༗ݶձࣾΦʔϓϯεϑΟΞ (CTO) ‣ גࣜձࣾΦτόϯΫ (όοΫΤϯυΤϯδχΞ౳) ‣ גࣜձࣾPR TIMES (PHPεϖγϟϦετɺઌഐ໾) ‣ גࣜձࣾϦϯέʔδ (༯ਫ਼) ‣ ଞ֤ࣾ…(ΞʔΩςΫτ΍ίϯαϧ΍PHPer΍ຐআ͚໾ͳͲ)

Slide 25

Slide 25 text

ͦͷଞ൪એ ‣ Youtubeͷ uzulla chͰɺBaanSeenͳͲͷYoutubeͯ͠·͢ νϟϯωϧొ࿥ͯ͠ʂग़ԋͯ͠ʂ ‣ ʮXdebugΛ։࢝͢Δ܅ʯͱ͍͏Chrome֦ுΛͭ͘Γ·ͨ͠ ੋඇ͔ͭͬͯ! ‣ BlueSkyʹɺ଴๬ͷPackagist؂ࢹBotΛ෮׆ͤ͞·ͨ͠ʂ throwable.bsky.social (ݩͷxͷcall_user_func͔Β΋ϦϯΫͯ͋͠Γ·͢)

Slide 26

Slide 26 text

DISCLAIMER ‣ ͜ͷτʔΫ͸ɺ御社ͷαʔϏεʹPHP੡ͷσʔϞϯΛಋೖ͢Δ ͜ͱΛお勧めしませんɻ ‣ (ݸਓαʔϏεͳΒɺԠԉ͠·͢ʂΏ͘Ώ͘͸ޚࣾʹ΋…ʁ) ‣ ࢲ͕ʮࣗ෼͸PHPͰσʔϞϯΛॻ͘ΜͩʂʯͱݴΘΕͨΒɺ· ͣ͸ʮ΄͔ͷݴޠɺ࢖ͬͯΈͨʁʯͱฉ͖·͢ɻ ‣ ΍Δͱͯ͠΋ɺνʔϜͰे෼ͳٞ࿦Λ͓͜ͳ͍·͠ΐ͏ɻ

Slide 27

Slide 27 text

ຊ୊ σʔϞϯ࿉੒ ࣂ͍ͳΒ͠ ঌש ͷɺPHPer޲͚ΨΠυ

Slide 28

Slide 28 text

σʔϞϯͱ͸ʁ ‣ όοΫάϥ΢ϯυͰಈ࡞͢ΔৗறϓϩάϥϜ ‣ ࣗಈతʹىಈ͠ɺಛఆͷαʔϏε΍λεΫΛܧଓతʹ࣮ߦ͠· ͢ ‣ Ϣʔβʔ͕ϩάΞ΢τͯ͠΋ऴྃͤͣɺγεςϜγϟοτμ΢ϯ ·Ͱಈ࡞͠ଓ͚·͢ɻ ‣ ϢʔβʔͷΠϯλϥΫγϣϯͳ͠ʹಈ࡞͚ͭͮ͠Δ ‣ ྫ:Apache, Nginx, MySQL, PostgreSQL, crond, sshd

Slide 29

Slide 29 text

;ͭ͏ͷPHPͱσʔϞϯͷҧ͍ Start ϒϥ΢β Request Apache PHP script Start(reset) Process PHP Response to ϒϥ΢β PHP script Finish(reset) ‣ ϦΫΤετ͕དྷͯϨεϙϯεΛฦ͢ɺຖճϦηοτ͞ΕΔ ‣ Θ͔Γ΍͍͢ʂ

Slide 30

Slide 30 text

όονͱσʔϞϯͷҧ͍ ‣ όον͸σʔϞϯʹʮࣅ͍ͯ·͢ʯ ‣ όον͸CronͳͲͰఆظతʹىಈͯ͠ऴྃ͢Δ ‣ Ұ౓ͷ࣮ߦͰ׬݁͢Δॲཧɺͱʹ͔͘ʮऴΘΓ͕͋Δʯ ‣ όον͸ຖճऴྃ͢ΔͷͰσʔλετΞʹอଘͯ࣍͠ͷόον ʹඋ͑ΔͨΓ͢Δ

Slide 31

Slide 31 text

Cron։࢝ PHP script Start(reset) Process PHP Cronऴྃ PHP script Finish(reset) Cron Cron

Slide 32

Slide 32 text

Batch(Cron)ͷݶքͱར఺ ‣ ࠷খ࣮ߦִؒ͸CronͳΒ1෼(௨ৗ) ‣ ಉ࣮࣌ߦͷ੍ޚ͕໘౗ɾ೉͍͠(ϩοΫ੍ޚ) ‣ Cronʮ΋ʯద౰Ͱ΋ಈ͘

Slide 33

Slide 33 text

σʔϞϯ - Կ͔Λॲཧ͢Δ΋ͷͰ͸͋Δ͕ɺϦΫΤετͱ͔Ϩεϙϯε͸ඞ ਢͰ͸ͳ͍ɻ - NඵʹҰ౓ूܭͯ͠DBʹॻ͖ࠐΉͱ͔ - ঢ়ଶΛௐ΂͚ͭͮͯ໰୊͕͋Ε͹ΞϥʔτΛSlackʹ͓͘Δͱ͔ - େྔͷσʔλΛʮ஗Ԇॲཧͨ͠Γɾޮ཰తʹɾॱ൪ʹʯॲཧ͢Δ ͱ͔ - ͋ͱɺ(ඞཁ͕ͳ͚Ε͹)ऴྃ͠ͳ͍

Slide 34

Slide 34 text

MainLoop PHP script Start(reset) Systemd(౳) Job౳ ऴྃʁ Main Loop Entry ॲཧA ॲཧN γάφϧ τϥοϓ NO ऴྃ ॲཧ YES killͳͲ γάφϧ ܧଓ ϑϥά ֬ೝ PHP script Finish( reset)

Slide 35

Slide 35 text

‣ Cron͸ىಈִ͕ؒ͋Δ͕ɺσʔϞϯ͸ىಈִ͕ؒͳ͘ৗʹ࣮ߦ ‣ ىಈ͚ͭͮ͠ΔͷͰɺ࠶઀ଓ΍ɺΩϟογϡΛຖճಡΈࠐΉඞ ཁ͕ͳ͍ ‣ ʮఀࢭִؒʯ͕ͳ͍ͷͰɺଈ࠲ʹ൓ԠՄೳ ‣ ܧଓ͢ΔͷͰɺWebSocketͳͲͷ઀ଓΛҡ࣋Մೳ

Slide 36

Slide 36 text

σʔϞϯͷܽ఺ ‣ ҆ఆͯ͠ಈ࡞͢Δ΋ͷΛ࡞Δͷ͕೉͍͠ ͨͱ͑͹ϝϞϦϦʔΫɺDB࠶઀ଓॲཧͳͲ ‣ (όον͸ී௨ͷWebϓϩάϥϜͱʹͨϊϦ) ‣ ҟৗऴྃͨ͠ͱ͖ʹ࠶ىಈͤͨ͞Γ͕໘౗ ‣ ଟ͘ͷ৔߹ɺόον΍REST APIͰΑ͍΍Μ͚ ‣ ౳ʑ…

Slide 37

Slide 37 text

ͳͥPHPͰσʔϞϯΛʁ(ݴ͍༁) ‣ PHP͸WebΞϓϦʴόονͱ͍͏Πϝʔδ͕ڧ͍ ‣ PHPͷ஌ࣝΛ׆͔͠ɺ༷ʑͳόοΫάϥ΢ϯυॲཧΛॻ͘ࣄ͕ Ͱ͖Ε͹… ‣ ΧοίΠΠ(ओ؍) ‣ ͜ͷลΓͷָ͓͠Έ͸ޙ൒Ͱ…

Slide 38

Slide 38 text

ૉ๿ͳσʔϞϯΛ࡞Δ 1. CLIεΫϦϓτͱͯ͠ىಈ 2. ϝΠϯϧʔϓͰܧଓ࣮ߦ 3. γάφϧϋϯυϦϯάͷ࣮૷

Slide 39

Slide 39 text

#"/usr/bin/env php

Slide 40

Slide 40 text

$running = true; while ($running) { // ϝΠϯϧʔϓ pcntl_signal_dispatch(); // γάφϧΛड৴ͨ͠ॲཧ echo "." . PHP_EOL; sleep(5); /" CPUΛ઎༗͠ͳ͍Α͏ʹεϦʔϓ } ‣ ແݶϧʔϓ(ϝΠϯϧʔϓ)͕͋Δ ‣ ʮා͍ʂʂʂʯ

Slide 41

Slide 41 text

$running = true; pcntl_signal(SIGTERM, function () use (&$running) { // γάφϧϋϯυϥͷઃఆ echo "SIGTERMΛ͏͚ͱΓ·ͨ͠ɺऴྃ͠·͢" . PHP_EOL; $running = false; }); while ($running) { // ϝΠϯϧʔϓ pcntl_signal_dispatch(); // γάφϧΛड৴ͨ͠ॲཧ }

Slide 42

Slide 42 text

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()Λݺͼग़ͯ͠ɺอཹதͷγάφϧΛॲ ཧ͠·͢ɻ͜Ε͸ॏཁͳεςοϓͰɺ͜Ε͕ͳ͍ͱγάφϧϋϯυϥͰ೚ҙͷॲཧΛઃఆͰ͖·ͤΜɻ

Slide 43

Slide 43 text

γάφϧͷૹΓํ ‣ killίϚϯυͰૹ৴Ͱ͖·͢ɺPIDͷࢦఆ͕ඞཁͰ͢ ‣ PID͸psίϚϯυͰ֬ೝͰ͖·͢ $ kill {PID} $ kill -HUP 1234 $ kill -TERM 1234 $ kill -USR1 1234 $ kill -KILL 1234 # ͜Ε͸OS͕ड͚औΓ·͢

Slide 44

Slide 44 text

ओཁͳγάφϧ ‣ SIGTERM (15): ਖ਼ৗऴྃཁٻ ‣ SIGINT (2): ΩʔϘʔυׂΓࠐΈʢCtrl+Cʣ ‣ SIGHUP (1): ୺຤੾அɺ(Α͋͘Δͷ͕ઃఆ࠶ಡΈࠐΈ) ‣ SIGUSR1 (10), SIGUSR2 (12): Ϣʔβʔఆٛ ‣ SIGKILL (9): ڧ੍ऴྃʢัଊෆՄʣ

Slide 45

Slide 45 text

খ࿩ ‣ γάφϧͷҙຯ͸ʮࡉ͔͖͘·͍ͬͯ·ͤΜʯ ‣ Apache͕γάφϧͨΓͶ͍͑ͬͯͬͯɺWINCHΛѱ༻ͯ͠Δ͜ͱ͸ Ұ෦Ͱ͸༗໊Ͱ͢Ͷ ‣ (WINCH͸΢Οϯυ΢αΠζมߋͷγάφϧͰ͢) ‣ ࠷ѱɺεΫϩʔϧόʔ͕ͰΔ͚ͩͰɺApache͕ऴྃ͢ΔΜͰ͢ΑͶ… ‣ (ݹདྷɺCLIͰApacheΛىಈ͢Δਓ͕ؒ͏·ΕΔͱ͸ࢥͬͯͳ͔ͬͨ ΜͩΖ͏…)

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

খ࿩:ద੾ͳऴྃॲཧ ‣ άϨʔεϑϧγϟοτμ΢ϯ ‣ ৽نॲཧΛఀࢭ͢Δ ‣ ਐߦதͷॲཧͷ׬ྃ͠ ‣ Ϧιʔεͷద੾ͳղ์͠ ‣ ঢ়ଶͷอଘ͢Δ ‣ ऴྃεςʔλεͷ௨஌

Slide 48

Slide 48 text

pcntl_signal(SIGTERM, function () { echo "ऴྃॲཧΛ࣮ߦத..""; /$ ਐߦதͷδϣϒΛอଘ saveCurrentState(); /$ DBίωΫγϣϯΛΫϩʔζ DB:&getConn-(close(); echo "ਖ਼ৗʹऴྃ͠·ͨ͠ɻ"; exit 0; /$ TODO ·ͱ΋ʹ࣮૷ͤΑ }); ‣ ଞʹ΋ɺSIGTERMͳΒ register_shutdown_function Λ׆༻͢Δख΋͋Δ

Slide 49

Slide 49 text

σʔϞϯͷঌשํ๏ $ php daemon.php ‣ CLI ϓϩάϥϜͷΑ͏ʹͯ͠ঌש(ىಈ)͕Ͱ͖·͢ɻ ‣ ໰୊఺͸λʔϛφϧΛด͡Δͱऴྃͯ͠͠·͏͜ͱͰ͢ ‣ ։ൃʹ͸ศར͕ͩɺσʔϞϯΛࣂ͏ͱͯ͠͸ඍົ

Slide 50

Slide 50 text

ྫ: nohupΛ࢖͏ํ๏ $ nohup php daemon.php & ‣ nohup: ϋϯάΞοϓγάφϧʢSIGHUPʣΛແࢹ͠·͢ ‣ &: όοΫάϥ΢ϯυͰ࣮ߦ

Slide 51

Slide 51 text

ྫ: screen(tmux)ͳͲΛ࢖͏ํ๏ # screenىಈ $ screen # σʔϞϯͳͲىಈ (screenͷதͰͷγΣϧ)$ php daemon.php # Ctrl+A, DͰɺγΣϧΛ੾Γ཭ͯ͠(σλον)ɺϓϩάϥϜΛऴྃͤͣʹϩάΞ΢τͰ͖Δ # ޙͰ·ͨϩάΠϯͯ͠ɺ࠶։(Ξλον)Ͱ͖Δ $ screen -r ‣ ίωΫγϣϯ͕͖Εͯ΋shell͕ऴྃͤͣɺ࠶઀ଓ͕Մೳ ‣ ։ൃ࣌ʹศར (௕࣮࣌ؒߦ͢ΔόονͰ΋͔ͭ͏ΑͶ) ‣ αʔόʔىಈ࣌ʹࣗಈىಈ͢ΔΑ͏ͳ΋ͷͰ͸ͳ͍

Slide 52

Slide 52 text

ίϯςφ؀ڥ 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͕Ͱ͖ͳ͍ͷͰऴ ྃ͸ผ్΍Δ͜ͱ

Slide 53

Slide 53 text

ຊ໋: systemdʹΑΔঌש ‣ Systemd͸LinuxͷαʔϏε؅ཧσʔϞϯ [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

Slide 54

Slide 54 text

systemctlʹΑΔૢ࡞ # αʔϏεͷొ࿥ $ systemctl enable php-daemon.service # αʔϏεͷ։࢝ $ systemctl start php-daemon.service # ঢ়ଶ֬ೝ $ systemctl status php-daemon.service # ఀࢭ $ systemctl stop php-daemon.service

Slide 55

Slide 55 text

Journalctl͍ͭͯ ‣ ϩάϑΝΠϧͷ؅ཧ͕ෆཁʂʢϩʔςʔγϣϯɺύʔϛογϣϯઃఆͳ Ͳʣ ‣ ߏ଄Խσʔλͱͯ͠อଘ͞Εɺݕࡧ͕༰қ ‣ λΠϜελϯϓɺϗετ໊ɺϓϩηεIDͳͲͷϝλσʔλ͕ࣗಈతʹ෇ ༩ ‣ γεςϜશମͷϩάͱ౷߹͞Εɺ໰୊ͷ૬ؔؔ܎Λ೺Ѳ͠΍͍͢ ‣ ϩάϨϕϧʹΑΔϑΟϧλϦϯά͕؆୯ ‣ ϩάग़ྗ͸ɺjournalctlίϚϯυͰ֬ೝͰ͖·͢ɻ

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

؂ࢹͱ݈શੑ֬อ ‣ ϩά͸JournalctlͰ؂ࢹͰ͖Δ ‣ ʁʮͱ͸͍͑ɺҟৗऴྃͨ͠ΒͲ͏͢ΔͷʁPHP͸৴༻ͳ͍ ͠…ʯ ‣ ϔϧενΣοΫΛఆظతʹ࣮ߦͯ͠…ͱ͔͋Γ·͕͢ ‣ ͳΜͱɺҟৗऴྃͳΒSystemd͕࠶ىಈΛ΍ͬͯ͘Ε· ͢ʂʂʂ ศརʂʂʂʂ

Slide 58

Slide 58 text

༨ஊɿsystemdʹΑΔεέδϡʔϧ࣮ߦ ‣ ͱ͸͍͑ɺσʔϞϯϓϩάϥϜͳΜͯ࡞Γͨ͘ͳ͍ਓͷͨΊͷ systemd͓໾ཱͪ৘ใ ‣ Systemd͸σʔϞϯͷىಈऴྃΛ͢Δ͚ͩͱ͓΋͍͖΍ɺεέ δϡʔϧ࣮ߦ΋Ͱ͖ΔʹCronͷ୅ΘΓʹ࢖͑Δ ‣ Cronͱ͕ͪͬͯϑΝΠϧΛઃஔͯ͠؅ཧ͢ΔͷͰɺIaCͱ૬ੑ͕ ྑ͍Ͱ͢ ‣ Ұ࣌ఀࢭͱ͔΋ႈ౳ʹͰ͖·͢

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

·ͱΊ ‣ Craft ‣ PHPͰ΋σʔϞϯϓϩάϥϜ͕࡞੒Մೳ ‣ Taim ‣ γάφϧॲཧ͕ॏཁ ‣ summon ‣ systemdͳͲͷπʔϧΛ׆༻͠·͠ΐ͏

Slide 62

Slide 62 text

࣭໰λΠϜͦͷ1 ࣭͝໰͕͋Ε͹Ͳ͏ͧʂ

Slide 63

Slide 63 text

͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ PHPͰσʔϞϯΛʮࣂ͍ͳΒ͠ʯɺ࣮༻తʹӡ༻͠·͠ΐ͏ʂ (͔͖ͣ͞Μ https://x.com/i999rri τʔΫϨϏϡʔ͋Γ͕ͱ͏ʂ)

Slide 64

Slide 64 text

ͬͯɺ͜ΕͰऴΘΔΘ͚ͳ͍΍Ζ͕͍ʂʂʂ ͏ͣΒͪΌΜ͸τʔΫΛ΍Ί΁ΜͰʔʂʂʂ

Slide 65

Slide 65 text

͔͜͜Βָ͓͠ΈλΠϜ ‣ ʮPHPͰͭ͘ΒΕͨσʔϞϯͬͯ΍ͭΛΈͤͯ͋͛·͢Α…ʂʯ ‣ ʮ͑͑ͬPHPͰʂʁʯʮ͸͍ʂʂʯ ‣ ʮDemon(ѱຐ)Ͱͳ͘ʂʁʯʮ͸͍ʁʁʯ

Slide 66

Slide 66 text

Keira

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

‣ Keira͸ɺPHPͱamphpͰߏங͞ΕͨWebϞχλϦϯάΞϓϦ Ͱ͢ɻෳ਺Λಉ࣌؂ࢹ͠ɺ໰୊͕ൃੜͨ͠ࡍʹϦΞϧλΠϜͰ௨ ஌͠·͢ɻ ‣ ϦΞϧλΠϜ௨஌ɿো֐ൃੜ࣌ʹଈ࠲ʹSlack௨஌(※) ‣ WebSocketରԠɿϦΞϧλΠϜߋ৽ΛWebSocketͰఏڙ ‣ RESTful APIɿγϯϓϧͳAPIͰ؂ࢹσʔλʹΞΫηε ‣ γάφϧ੍ޚɿUNIXγάφϧͰΞϓϦΛૢ࡞ ‣ ֤छΧελϚΠζ؂ࢹઃఆ

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

ࢲʮͲ͏Ͱ͢ʁʯ ʁʮJS Chart͓͔͘͠Ͷʁʯ ࢲʮຊ࣭Ͱ͸ͳ͍ʯ

Slide 71

Slide 71 text

ʢσʔϞϯͳΒͰ͸ͷʣӡ༻ʹ࢖͑ΔϙΠϯτ ‣ Ұ࣌ఀࢭ͕ USR1,2 γάφϧͰͰ͖Δ ‣ ઃఆϑΝΠϧͷϦϩʔυΛHUPͰͰ͖Δ ‣ ؂ࢹઌͷ௥Ճɺ࡟আɺҰ࣌ఀࢭͳͲΛαϙʔτ ‣ ͜ͷ࣌ʹWebSocket͕੾அ͞ΕͨΓ͸͠·ͤΜ ‣ ౷ܭ৘ใ΋͖͑·ͤΜ ‣ ͳͥͳΒσʔϞϯͳͷͰ(ʁʁʁ)

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

Slack௨஌΋αϙʔτ͍ͯ͠Δʂ ‣ ͭ΋Γ͕ͩͬͨɺࠓ೔όάͬͯ·ͨ͠wwww ‣ ͳͷͰಈը͕ͳ͍ʂʂʂ ‣ ·͋ɺ͏͍ͨ͝ΜͩΑʂʂʂʂ৴ͯ͘͡Εʂʂʂʂ

Slide 74

Slide 74 text

Keiraͷίʔυ͸ͪ͜Β ‣ https://github.com/uzulla/Keira ‣ ஫ҙ఺: ։ൃதͰ͢w ຊ෺ͷ؂ࢹʹ͸·ͩ࢖Θͳ͍Ͱ͍ͩ͘͞w

Slide 75

Slide 75 text

ͩ͜ΘΓϙΠϯτ ‣ WebsocketΛॲཧ͠ͳ͕Βɺ؂ࢹ΋ܧଓ͍ͯ͠Δ͠ɺREST API ΋໪࿦͏͖͝·͢ʂ ‣ σʔϞϯͳͷͰɺDBͱ͔ෆཁʂ(σʔλ͸ม਺ʹ΋͍ͬͯ·͢) ‣ 1ϓϩηεͳͷͰɺDockerίϯςφͱ͔Ͱಈ͔͢ͷ΋ָʑʂ (Systemdͷ࿩͸Ͳ͜ʹ…ʁ)

Slide 76

Slide 76 text

ίʔυ͓΋͠ΖϙΠϯτ ‣ amphpͳͷͰɺPure PHPͰ͢ (C֦ுෆཁ) ‣ ݁ߏಡΈ΍͔͍ͯ͋͘͢Γ·͢(ݸਓࠩ͸͋Δ) ‣ ApiServer.phpͱ͔ΈͯΈ͍ͯͩ͘͞ ‣ γάφϧॲཧ͸ɺUtil/SignalHandler.phpʹॻ͍ͯ͋Γ·͢ ‣ Application.php ͰɺػೳΛϚ΢ϯτ͍ͯ͘͠ͷ͕͓΋͠Ζ͍ ‣ Asyncͱ͔ɺCancelͱ͔͕͋Δ (ଞͷݴޠ஌ͬͯΔͻͱͳΒ͓΋͠Ζ͍Ͱ͠ΐ)

Slide 77

Slide 77 text

## Keira/src/Keira/Application.php /$ Create signal handler $this-&signalHandler = new SignalHandler($this-&configLoader, $this-&monitorManager, $this-&appLogger); $this-&signalHandler-&register(); /$ 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();

Slide 78

Slide 78 text

## 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); } }

Slide 79

Slide 79 text

## 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 ); } ));

Slide 80

Slide 80 text

## 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; } } });

Slide 81

Slide 81 text

·ͱΊ2 ‣ PHPͰɺ࣮༻తͳσʔϞϯ͕࡞ΕΔʂ ‣ ͔͠΋ɺҊ֎ಡΊΔʂ(ݸਓࠩ͋Γ·͢) ‣ νϡʔχϯά(CPUෛՙ)ͱ͔͸·ͩ·ͩͰ͢ɻ Ͱ΋ɺಈ͘͜ͱ͕Θ͔ΔɺͦΕ͕࢝·ΓͰ͢ʂʂʂ

Slide 82

Slide 82 text

ʮΦϨͨͪ͸·ͩ૸Γ࢝Ίͨ͹͔Γ͔ͩΒͳɻ ͜ͷ͸ͯ͠ͳ͘ԕ͍σʔϞϯ࿉੒ΛΑ…!ʯ

Slide 83

Slide 83 text

One more thing...

Slide 84

Slide 84 text

DB-monitor ‣ https://github.com/uzulla/db-monitor ‣ ʮՔಇதͷσʔλϕʔεͷ౷ܭ৘ใ౳ΛϦΞϧλΠϜʹදࣔ͠ɺվળʹ ໾ཱͯΔ৘ใΛऔಘ͢ΔπʔϧͰ͢ʯ ‣ DBʹৗ࣌઀ଓͯ͠ɺΫΤϦΛϞχλʔ͢ΔπʔϧΛͭ͘Γ͔ͨͬͨ ‣ ʮPHPͰʂʂʂʂʂʂʂʂʂʯ ‣ ͳͥͳΒPHPͳΒɺ৭ʑͳਖ਼نදݱͱָ͔͕ʹ࢖͑Δ͠ɺίʔυ͕ಡΈ ΍͍͔͢Β(ݸਓࠩ͸͋Δ) ‣ ͜Ε΋amphpͰॻ͍ͯ·͢

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

͓ΘΓ ‣ ࣭໰͋Γ·͔͢ʁ ‣ ͳ͍ͳΒɺthrowable.bsky.social ͷσϞͰ΋͢Δ