In short: The PHP CLI (Command Line Interface) is the variant of PHP for the command line. It runs scripts without a web server, for example for cron jobs, Composer or maintenance tasks. It has its own defaults, often its own php.ini and sometimes even a different version than the website. That is why php -v is not reliable proof that the website has been patched after PHP2Shell.
What is the PHP CLI?
The PHP manual names two main areas of use for PHP: scripts for websites and scripts on the command line. For the latter there is a dedicated SAPI named cli. It needs neither a web server nor a browser, only the PHP interpreter. According to the manual, it is particularly suited to tasks that run regularly via cron on Linux or via the task scheduler on Windows.
Typical examples in everyday business: nightly imports in the shop, newsletter dispatch, cache clean-up, updates via Composer, or the command-line tools of CMS such as WP-CLI or the Symfony console. On Windows the file is called php.exe, the CGI variant php-cgi.exe.
Unlike PHP-FPM, the CLI is not a service. Every call starts a new process, re-reads the configuration according to the manual, and ends when the script is finished. A restart after an update is therefore not necessary. Exceptions are long-running processes started via the CLI, such as queue workers of frameworks or daemons under systemd or Supervisor. They run for days with the interpreter loaded once and must be restarted after a PHP update just like web workers.
For management and project leads this means: background tasks belong in the inventory and in every update plan as well.
How does the CLI differ from the web version?
According to the manual, the CLI overrides some settings with fixed values. They cannot be changed via php.ini, only at runtime with ini_set():
| Directive | Value in the CLI | Reason according to the manual |
|---|---|---|
html_errors |
off | HTML tags are disruptive in the terminal |
implicit_flush |
on | output should appear immediately |
max_execution_time |
0 (unlimited) | command-line scripts often run for a long time |
register_argc_argv |
on | scripts always receive $argc and $argv |
output_buffering |
off | hard-wired, buffering functions remain usable |
max_input_time |
off | the CLI has no GET, POST or uploads |
Another difference: the CLI does not change into the script's directory. Anyone who calls php -f ordner/skript.php from /tmp keeps working in /tmp. Relative paths in cron jobs are therefore a common source of errors.
A small script that is only meant to run on the command line:
<?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");
The check on PHP_SAPI prevents a maintenance script from being triggered through the browser if it accidentally sits in the web directory. The manual explicitly advises checking the SAPI this way rather than relying on the presence of $argv.
The most important PHP CLI options
The following options come from the options overview of the PHP manual and are particularly useful for admins:
php -vshows the version number of the CLI.php --inishows which configuration files are loaded.php -mlists the compiled-in and loaded modules.php -icallsphpinfo()and outputs the result as text.php -l datei.phpchecks syntax only (lint). Since PHP 8.3 also for several files at once.php -r 'code'executes code directly, without<?php.php -d name=wertsets an INI setting for this call.php -nignores php.ini completely.php --ri nameshows the configuration of an extension.
php --ini
php -m | grep -i -E "opcache|sodium|pdo"
php --ri session | grep upload_progress
php -l src/Controller.php src/Model.php
The built-in web server: for development only
With php -S localhost:8000, the CLI starts a small web server. The example output in the manual names PHP 5.4.0 as the starting point. The manual is unambiguous: the server is for development, is not a full web server, and should not run on public networks or in production. If it runs permanently on a server and is reachable from outside, that is a finding you should eliminate.
CLI, cron and security after PHP2Shell
The known reports on PHP2Shell name PHP-FPM, mod_php, php-cgi, FrankenPHP and LiteSpeed as affected operating modes. The CLI does not process requests from the network. For security it is nevertheless important in three respects:
- Wrong proof:
php -vshows the CLI version. The website may use a different version, and distribution backports often do not change the displayed number. How to document the state correctly is described under Checking the PHP version and patch level and in the article Why php -v shows the same number. - Persistence via cron: After a break-in, attackers like to use cron jobs that start a PHP script regularly. Notes on how to search are given in Recognising hidden cron jobs as a backdoor.
- Same package: The CLI usually comes from the same package source as PHP-FPM and belongs in the update.
How does PHP SOS help?
- Compare versions: We compare CLI and web state and document which version your website really serves.
- Check cron jobs: We list all scheduled PHP tasks of all users and map them to their applications.
- Secure maintenance: We move maintenance scripts out of the web directory and add SAPI checks.
- Support on an ongoing basis: In the security maintenance contract we keep CLI, web SAPI and cron jobs up to date together.
Frequently asked questions
Does php -v show the version of my website?
Not necessarily. php -v shows the version of the command-line variant. The website may run through a different PHP-FPM version or an Apache module. What counts for the website is the state of the web SAPI, which you determine via the service or a temporary test file.
Why do CLI scripts run for an unlimited time?
According to the PHP manual, the CLI fixes max_execution_time at 0, that is, unlimited, because scripts on the command line often perform long tasks. The runtime can be limited by the script itself or by tools such as timeout.
May I use the built-in web server php -S in production?
No. The manual describes it as an aid for development, not as a full web server, and advises against using it on public networks and in production. For live systems, Apache, Nginx or LiteSpeed with PHP-FPM belong in front.
Is OPcache active on the command line?
Not by default. According to the manual, opcache.enable_cli is set to 0. For short scripts the cache brings little anyway, because every call is a new process.