Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

PHP on the Command Line (CLI)

The PHP CLI runs scripts without a web server, for example for cron jobs and maintenance. It behaves differently from the web version and often does not show the state your website uses.

Last updated 5 min readPHP knowledge

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:

  1. php -v shows the version number of the CLI.
  2. php --ini shows which configuration files are loaded.
  3. php -m lists the compiled-in and loaded modules.
  4. php -i calls phpinfo() and outputs the result as text.
  5. php -l datei.php checks syntax only (lint). Since PHP 8.3 also for several files at once.
  6. php -r 'code' executes code directly, without <?php.
  7. php -d name=wert sets an INI setting for this call.
  8. php -n ignores php.ini completely.
  9. php --ri name shows 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 -v shows 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.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help