Stručne: PHP CLI (Command Line Interface) je variant PHP pre príkazový riadok. Spúšťa skripty bez webového servera, napríklad pre cronjoby, Composer alebo úlohy údržby. Má vlastné štandardné hodnoty, často vlastný php.ini a niekedy dokonca inú verziu než web. Preto php -v nie je spoľahlivým dôkazom, že je web po PHP2Shell záplatovaný.
Čo je PHP CLI?
Príručka PHP uvádza dve hlavné oblasti použitia PHP: skripty pre weby a skripty v príkazovom riadku. Pre tie druhé existuje samostatná SAPI s názvom cli. Nepotrebuje webový server ani prehliadač, len interpreter PHP. Podľa príručky sa hodí najmä na úlohy, ktoré pravidelne bežia cez Cron v Linuxe alebo cez plánovač úloh vo Windows.
Typické príklady z firemnej praxe: nočné importy v obchode, rozosielanie newslettera, čistenie cache, aktualizácie cez Composer alebo nástroje príkazového riadka CMS ako WP-CLI alebo konzola Symfony. Vo Windows sa súbor volá php.exe, variant CGI php-cgi.exe.
Na rozdiel od PHP-FPM nie je CLI služba. Každé volanie spustí nový proces, podľa príručky znova načíta konfiguráciu a skončí, keď je skript hotový. Reštart po aktualizácii preto nie je potrebný. Výnimkou sú dlho bežiace procesy spustené cez CLI, napríklad workery front vo frameworkoch alebo daemony pod systemd či Supervisor. Bežia celé dni s raz načítaným interpreterom a po aktualizácii PHP sa musia reštartovať rovnako ako webové workery.
Pre konateľov a vedenie projektov to znamená: aj úlohy na pozadí patria do inventára a do každého plánu aktualizácií.
Ako sa CLI líši od webovej verzie?
CLI podľa príručky niektoré nastavenia prepisuje natvrdo. Nedajú sa zmeniť cez php.ini, iba počas behu cez ini_set():
| Direktíva | Hodnota v CLI | Zdôvodnenie podľa príručky |
|---|---|---|
html_errors |
vypnuté | značky HTML rušia v termináli |
implicit_flush |
zapnuté | výstupy sa majú zobraziť okamžite |
max_execution_time |
0 (neobmedzene) | skripty v príkazovom riadku často bežia dlho |
register_argc_argv |
zapnuté | skripty vždy dostanú $argc a $argv |
output_buffering |
vypnuté | pevne zadané, funkcie vyrovnávacej pamäte zostávajú použiteľné |
max_input_time |
vypnuté | CLI nepozná GET, POST ani uploady |
Ďalší rozdiel: CLI neprechádza do adresára skriptu. Kto volá php -f ordner/skript.php z /tmp, pracuje ďalej v /tmp. Relatívne cesty v cronjoboch sú preto častým zdrojom chýb.
Malý skript, ktorý má bežať iba v príkazovom riadku:
<?php
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit('Nur für die Kommandozeile.');
}
$tage = (int) ($argv[1] ?? 30);
$grenze = time() - $tage * 86400;
$alt = 0;
foreach (glob(__DIR__ . '/cache/*.tmp') ?: [] as $datei) {
if (filemtime($datei) < $grenze) { $alt++; }
}
fwrite(STDOUT, "Dateien älter als $tage Tage: $alt\n");
Kontrola PHP_SAPI bráni tomu, aby sa skript údržby spustil cez prehliadač, ak by náhodou ležal vo webovom adresári. Príručka výslovne radí kontrolovať SAPI takto, namiesto spoliehania sa na existenciu $argv.
Najdôležitejšie voľby PHP CLI
Nasledujúce voľby pochádzajú z prehľadu volieb v príručke PHP a sú pre správcov obzvlášť užitočné:
php -vukazuje číslo verzie CLI.php --iniukazuje, ktoré konfiguračné súbory sa načítavajú.php -mvypisuje skompilované a načítané moduly.php -ivoláphpinfo()a vypíše výsledok ako text.php -l datei.phpkontroluje iba syntax (lint). Od PHP 8.3 aj pre viac súborov naraz.php -r 'code'vykoná kód priamo, bez<?php.php -d name=wertnastaví nastavenie INI pre toto volanie.php -núplne ignoruje php.ini.php --ri nameukazuje konfiguráciu rozšírenia.
php --ini
php -m | grep -i -E "opcache|sodium|pdo"
php --ri session | grep upload_progress
php -l src/Controller.php src/Model.php
Vstavaný webový server: iba pre vývoj
Pomocou php -S localhost:8000 spustí CLI malý webový server. Príkladový výstup v príručke uvádza ako východisko PHP 5.4.0. Príručka je jednoznačná: server slúži vývoju, nie je plnohodnotný webový server a nemá bežať vo verejných sieťach ani v produkcii. Ak na serveri beží trvalo a je dostupný zvonka, je to zistenie, ktoré by ste mali odstrániť.
CLI, Cron a bezpečnosť po PHP2Shell
Známe hlásenia o PHP2Shell uvádzajú ako dotknuté režimy prevádzky PHP-FPM, mod_php, php-cgi, FrankenPHP a LiteSpeed. CLI nespracúva požiadavky zo siete. Pre bezpečnosť je napriek tomu dôležité v troch ohľadoch:
- Nesprávny dôkaz:
php -vukazuje verziu CLI. Web môže používať inú verziu a backporty distribúcií často zobrazené číslo nemenia. Ako stav správne doložiť, je v časti Kontrola verzie PHP a stavu záplat a v príspevku Prečo php -v ukazuje to isté číslo. - Perzistencia cez Cron: Útočníci po prieniku radi využívajú cronjoby, ktoré pravidelne spúšťajú skript PHP. Upozornenia na hľadanie dáva Rozpoznanie skrytých cronjobov ako zadných vrátok.
- Rovnaký balík: CLI pochádza zvyčajne z toho istého zdroja balíkov ako PHP-FPM a patrí do aktualizácie.
Ako konkrétne pomáha PHP SOS?
- Zosúladiť verzie: Porovnávame stav CLI a webu a dokladáme, akú verziu váš web skutočne odovzdáva.
- Skontrolovať cronjoby: Vypisujeme všetky plánované úlohy PHP všetkých používateľov a priraďujeme ich k aplikáciám.
- Zabezpečiť údržbu: Presúvame skripty údržby z webového adresára a nastavujeme kontroly SAPI.
- Starať sa trvalo: V rámci zmluvy o bezpečnostnej údržbe udržiavame CLI, webovú SAPI a cronjoby spoločne aktuálne.
Časté otázky
Ukazuje php -v verziu môjho webu?
Nie nevyhnutne. php -v ukazuje verziu variantu pre príkazový riadok. Web môže bežať cez inú verziu PHP-FPM alebo modul Apache. Pre web je rozhodujúci stav webovej SAPI, ktorý zistíte cez službu alebo krátkodobý kontrolný súbor.
Prečo skripty CLI bežia neobmedzene dlho?
Podľa príručky PHP nastavuje CLI max_execution_time pevne na 0, teda neobmedzene, pretože skripty v príkazovom riadku často vykonávajú dlhé úlohy. Dobu behu možno obmedziť samotným skriptom alebo nástrojmi ako timeout.
Smiem vstavaný webový server php -S používať produkčne?
Nie. Príručka ho opisuje ako pomôcku pre vývoj, nie ako plnohodnotný webový server, a odrádza od jeho používania vo verejných sieťach a v produkcii. Pre živé systémy patria pred PHP-FPM Apache, Nginx alebo LiteSpeed.
Je OPcache v príkazovom riadku aktívna?
Štandardne nie. opcache.enable_cli je podľa príručky nastavené na 0. Pre krátke skripty cache aj tak prináša málo, pretože každé volanie je nový proces.