start here
Linux Shell Basics for PHP Developers
PHP developers do not need to become full-time system administrators, but they do need enough shell skill to run projects, inspect logs, debug paths, check permissions, and understand automation.
The shell is where many PHP tasks happen: Composer commands, test runners, syntax checks, queue workers, deployment checks, cron jobs, Docker commands, and production diagnostics.
Navigation And Files
Start with the commands that help you understand where you are and what files exist.
pwd
ls
ls -la
cd /path/to/project
find . -maxdepth 2 -type f -name "*.php"
Useful meanings:
pwdprints the current directoryls -lashows hidden files and permissionscdchanges directoryfindlocates files by name, type, or path
Before running a PHP command, confirm you are in the project directory you think you are in.
Inspecting Files
Common file-reading commands:
cat composer.json
less storage/logs/app.log
tail -n 50 storage/logs/app.log
tail -f storage/logs/app.log
tail -f follows a log as new lines are written. It is useful while reproducing a web request or running a queue worker.
Searching Code And Logs
Use rg when available because it is fast and respects many ignore files by default.
rg "DB_HOST"
rg "function handle" app
rg "RuntimeException" storage/logs
If rg is not installed, grep is common:
grep -R "DB_HOST" .
grep -R "RuntimeException" storage/logs
Search before guessing. Many configuration, route, service, and error questions can be answered by finding the exact string in the project.
PATH And Active Commands
When you type a command, the shell finds it through PATH.
echo $PATH
which php
which -a php
php -v
For PHP projects, always be ready to prove which php, composer, and framework command you are running.
which composer
composer --version
If the shell runs the wrong binary, application changes will not fix it.
Environment Variables
Environment variables are part of the process environment.
printenv
printenv APP_ENV
APP_ENV=local php -r 'echo getenv("APP_ENV") . PHP_EOL;'
That last command sets APP_ENV only for that single PHP process.
Inside PHP:
<?php
declare(strict_types=1);
echo getenv('APP_ENV') ?: 'not set';
echo PHP_EOL;
// Example:
// APP_ENV=local php env.php
//
// Prints:
// local
Shell environment, systemd environment, Docker environment, and web-server environment can all differ.
Pipes And Redirection
Pipes pass output from one command into another.
php -m | sort
php -m | grep mbstring
tail -n 200 storage/logs/app.log | grep ERROR
Redirection writes output to files.
php script.php > output.txt
php script.php 2> errors.txt
php script.php > output.txt 2> errors.txt
Normal output is stdout. Error output is stderr. Good CLI tools keep those separate.
Reading Piped Input In PHP
PHP can read piped input from STDIN.
<?php
declare(strict_types=1);
$input = stream_get_contents(STDIN);
$lines = array_filter(explode("\n", trim($input)));
echo 'Lines: ' . count($lines) . PHP_EOL;
// Example:
// printf "one\ntwo\n" | php count-lines.php
//
// Prints:
// Lines: 2
This is useful for small maintenance tools that work with command output.
Permissions And Ownership
Permission issues are common in PHP projects because web servers, queue workers, and shell users may be different users.
whoami
id
ls -la storage
ps aux | grep php-fpm
If PHP cannot write cache, sessions, logs, or uploads, check ownership and permissions before changing application logic.
Avoid blindly running chmod -R 777. It hides the problem and creates security risk.
Processes And Services
You may need to know whether PHP-FPM, a queue worker, or a local server is running.
ps aux | grep php
systemctl status php-fpm
systemctl list-units "php*"
For a local built-in server:
php -S 127.0.0.1:8000 -t public
Stop a foreground process with Ctrl+C.
Exit Codes
The shell tracks whether the last command succeeded.
php -l public/index.php
echo $?
0 means success. Non-zero means failure.
CI jobs, deploy scripts, cron, and shell pipelines depend on exit codes. A PHP script used in automation should exit non-zero when it fails.
What You Should Be Able To Do
After this lesson, you should be able to navigate a project, inspect files, search logs, prove active binaries, read environment variables, use pipes and redirection, understand basic permissions, and check PHP-related processes.
For junior PHP work, this matters because many real bugs are found from the shell first: wrong PHP version, missing extension, bad permissions, failing worker, or an error line in a log.
Practice
Practice: Shell Debugging Checklist
Create a checklist for debugging a PHP project from the Linux shell.
Task
Include commands to:
- confirm the current directory
- list files and permissions
- find PHP files
- search for an environment variable name
- show the active PHP binary and version
- show loaded PHP configuration
- follow the last lines of an application log
Afterward, add a short note explaining which command you would run first when a project behaves differently from what you expect.
Show solution
pwd
ls -la
find . -maxdepth 2 -type f -name "*.php"
rg "APP_ENV"
which php
php -v
php --ini
tail -n 100 storage/logs/app.log
If rg is not installed:
grep -R "APP_ENV" .
The first command should usually be pwd. If you are in the wrong directory or inside the wrong container, every later result can mislead you.
Task: Pipe Input
Create a small PHP CLI tool that reads lines from STDIN.
Requirements
Build a script that:
- reads piped input from
STDIN - counts non-empty lines
- prints the count to stdout
- writes an error to
STDERRand exits with1when no input is provided
Use strict types. Keep example commands and output inside the PHP code block as comments.
Show solution
This script behaves like a small shell-friendly tool.
<?php
declare(strict_types=1);
$input = stream_get_contents(STDIN);
$lines = array_values(array_filter(
explode("\n", trim($input)),
static fn (string $line): bool => trim($line) !== '',
));
if ($lines === []) {
fwrite(STDERR, "No input received.\n");
exit(1);
}
echo 'Non-empty lines: ' . count($lines) . PHP_EOL;
exit(0);
// Example:
// printf "alpha\nbeta\n\n" | php count-lines.php
//
// Prints:
// Non-empty lines: 2
//
// Failure example:
// printf "" | php count-lines.php
//
// STDERR:
// No input received.
This shape works well in automation because stdout contains normal results, stderr contains diagnostic output, and the exit code tells the shell whether the command succeeded.
Task: Debug Paths
Create a checklist for debugging wrong paths and wrong binaries in a PHP project.
Requirements
Include commands to show:
- current directory
- active PHP binary
- all visible PHP binaries
- active Composer binary
- PATH entries
- loaded PHP configuration
Afterward, add a short note explaining why path checks should happen before editing code.
Show solution
pwd
which php
which -a php
php -v
which composer
composer --version
echo $PATH
php --ini
If the project runs in Docker, WSL, or a remote server, run the same checks inside that environment.
Path checks should happen before editing code because the failure may be caused by running the wrong binary, wrong project directory, wrong shell environment, or wrong configuration file. Code changes do not fix those problems.