API Index — Namespaces, Packages, Reports, Indices
CLI
in package
Command-line interface handling for the ZealPHP server lifecycle (start/stop/restart/status/logs + PID-file management).
Extracted verbatim from App.php (Phase 1 of the App.php decomposition).
Every method here was previously a private/protected static on App and is
only reached internally — there are no public-API BC shims because the
CLI surface is the php app.php … command path, not App::cli*() calls.
Table of Contents
Methods
- claimOrphanIfAny() : bool
- Recover from an orphaned-daemon situation: pid file missing or stale but the port is still held. If the listener is a ZealPHP process, graceful-then-force kill it. Returns true when an orphan was cleaned up, false when there's nothing to do (port free, or held by something that isn't ours).
- parseCliArgs() : array<string, mixed>
- Parse
$argv, execute any lifecycle sub-command, and return server-config overrides. - processIsZealphp() : bool
- True when /proc/$pid/cmdline looks like a ZealPHP daemon: argv[0] is a real php binary (php, php8.3, etc.) AND the args reference app.php.
- resolvePidFile() : string
- Resolve the PID file path for the given CLI flags.
- cliHelp() : void
- Print the
php app.php --helpusage text to stdout and return. - cliLogs() : void
- cliStatus() : void
- cliStatusOne() : void
- cliStop() : void
- Stop the server identified by
$pidFile. - cliStopAuto() : void
- Stop all running ZealPHP instances when no specific port is given.
- ensurePidDir() : void
- Ensure
$direxists and is writable, creating it recursively if needed. - extractPortFromPidFile() : int
- Pull the port number from a default-shaped pid file path like /tmp/zealphp/zealphp_8080.pid. Returns 0 when the caller passed a --pid-file override that doesn't match the convention.
- findPortOwnerPid() : int|null
- Returns the PID listening on $port, or null when nothing's listening or it can't be determined (non-Linux, /proc unreadable). Linux-only: /proc/net/tcp + tcp6 give the LISTEN-state socket inode; /proc/[pid]/fd/* resolves inode → owner pid. We deliberately avoid stream_socket_server / socket_bind here — those are intercepted by OpenSwoole's runtime hook (HOOK_ALL) and become coroutine-only, which would crash this CLI path.
- forkStartupReporter() : void
- For daemonized start/restart: fork so the terminal-attached parent polls for the new daemon's PID file and prints a confirmation line BEFORE the shell prompt returns, while the child goes on to boot the (self-daemonizing) server. The parent never touches OpenSwoole — it only watches the PID file and exits, so the confirmation is always the last thing written to the terminal (fixes the issue #17 race where the prompt returned first and the message overlapped the next command).
Methods
claimOrphanIfAny()
Recover from an orphaned-daemon situation: pid file missing or stale but the port is still held. If the listener is a ZealPHP process, graceful-then-force kill it. Returns true when an orphan was cleaned up, false when there's nothing to do (port free, or held by something that isn't ours).
public
static claimOrphanIfAny(int $port) : bool
Orphan recovery is rare and notable, so messages always print even when called from a "quiet" code path (cliStop during restart) — silent recovery hides the fact that the system was in a degraded state that needed self-healing.
Parameters
- $port : int
Return values
boolparseCliArgs()
Parse $argv, execute any lifecycle sub-command, and return server-config overrides.
public
static parseCliArgs() : array<string, mixed>
Sub-commands (stop, status, logs, restart) are handled in-process and
call exit() when done. The start / default path returns an array of
OpenSwoole $server->set() override keys (_host, _port, worker_num,
daemonize, etc.) that App::run() merges into its config. Returns an
empty array when no overrides are needed.
Return values
array<string, mixed>processIsZealphp()
True when /proc/$pid/cmdline looks like a ZealPHP daemon: argv[0] is a real php binary (php, php8.3, etc.) AND the args reference app.php.
public
static processIsZealphp(int $pid) : bool
Used to gate kill operations so a recycled PID belonging to an unrelated process is never targeted.
The stricter argv[0] check matters because bash wrappers that spawn
php app.php … as a child carry "app.php" in their own cmdline — a
naive substring match falsely identifies them as ZealPHP daemons and
would happily kill them.
Non-Linux returns true (be permissive — caller still has posix_kill).
Parameters
- $pid : int
Return values
boolresolvePidFile()
Resolve the PID file path for the given CLI flags.
public
static resolvePidFile(array<string, mixed> $flags) : string
Resolution order (first match wins):
--pid-fileflag ($flags['pid_file']).ZEALPHP_PID_FILEenvironment variable.ZEALPHP_LOG_DIRenv var +zealphp_{port}.pid.resolve_log_dir()result (per-user fallback) +zealphp_{port}.pid.
Creates the parent directory when it does not exist.
Parameters
- $flags : array<string, mixed>
-
Parsed CLI flags from
parseCliArgs().
Return values
stringcliHelp()
Print the php app.php --help usage text to stdout and return.
private
static cliHelp() : void
The caller is responsible for calling exit(0) after this.
cliLogs()
private
static cliLogs(array<string, mixed> $flags) : void
Parameters
- $flags : array<string, mixed>
cliStatus()
private
static cliStatus(array<string, mixed> $flags) : void
Parameters
- $flags : array<string, mixed>
cliStatusOne()
private
static cliStatusOne(string $pidFile) : void
Parameters
- $pidFile : string
cliStop()
Stop the server identified by $pidFile.
private
static cliStop(string $pidFile[, bool $quiet = false ]) : void
Sends SIGTERM to the process group (or PID), polls up to 10 s for graceful
shutdown, then falls back to SIGKILL. Removes the PID file on success.
When the PID file is missing or stale, calls claimOrphanIfAny() to handle
a running-but-unregistered daemon. Output is suppressed when $quiet is true.
Parameters
- $pidFile : string
- $quiet : bool = false
cliStopAuto()
Stop all running ZealPHP instances when no specific port is given.
private
static cliStopAuto() : void
Globs {logDir}/zealphp_*.pid, verifies each PID with processIsZealphp(),
and stops the lone instance automatically. When multiple instances are found,
lists them and asks the user to specify a port with -p PORT.
ensurePidDir()
Ensure $dir exists and is writable, creating it recursively if needed.
private
static ensurePidDir(string $dir) : void
Logs a warning via elog() when creation fails — never throws.
Parameters
- $dir : string
extractPortFromPidFile()
Pull the port number from a default-shaped pid file path like /tmp/zealphp/zealphp_8080.pid. Returns 0 when the caller passed a --pid-file override that doesn't match the convention.
private
static extractPortFromPidFile(string $pidFile) : int
Parameters
- $pidFile : string
Return values
intfindPortOwnerPid()
Returns the PID listening on $port, or null when nothing's listening or it can't be determined (non-Linux, /proc unreadable). Linux-only: /proc/net/tcp + tcp6 give the LISTEN-state socket inode; /proc/[pid]/fd/* resolves inode → owner pid. We deliberately avoid stream_socket_server / socket_bind here — those are intercepted by OpenSwoole's runtime hook (HOOK_ALL) and become coroutine-only, which would crash this CLI path.
private
static findPortOwnerPid(int $port) : int|null
Parameters
- $port : int
Return values
int|nullforkStartupReporter()
For daemonized start/restart: fork so the terminal-attached parent polls for the new daemon's PID file and prints a confirmation line BEFORE the shell prompt returns, while the child goes on to boot the (self-daemonizing) server. The parent never touches OpenSwoole — it only watches the PID file and exits, so the confirmation is always the last thing written to the terminal (fixes the issue #17 race where the prompt returned first and the message overlapped the next command).
private
static forkStartupReporter(string $pidFile, int $port, string $verb) : void
No-op when pcntl is unavailable or the fork fails: start proceeds without a confirmation line (prior behaviour), never silently broken.
Parameters
- $pidFile : string
- $port : int
- $verb : string
-
e.g. "Restarted" or "Started ZealPHP in detached mode"
Forks + polls the daemon PID file and exits in the child — neither unit-testable in-process (pcntl_fork/exit kills the test runner) nor dumpable as a subprocess (the OpenSwoole server suppresses the PHP shutdown coverage flush). Verified manually + by the CLI behaviour.