Almost every web server on the internet runs Linux, which means that sooner or later, managing a website means typing commands into a shell. There is no way around it. A control panel covers the common cases, but when a deployment fails at midnight or a disk fills up, the fastest path to an answer is a terminal.
This guide is a reference to the Linux commands that actually come up in hosting work, organized by what you are trying to do rather than alphabetically. Each section covers the syntax, the flags worth remembering, and the mistakes that cost people time. Where a command deserves more than a paragraph, there is a link to a dedicated guide.
How a Linux command is structured#
Every Linux command follows the same shape:
command [options] [arguments]
The command is the program. Options (also called flags or switches) modify its behavior. Arguments are what the command acts on.
ls -la /var/www/html
Here
ls
is the command,
-la
combines two options (
-l
for long format,
-a
to include hidden files), and
/var/www/html
is the argument.
Options come in two forms. Short options use a single dash and a single letter, and can be combined:
-l -a
is the same as
-la
. Long options use two dashes and a whole word:
--all
,
--human-readable
. Long options are more readable in scripts, short options are faster to type.
Two commands help with everything else:
man ls # full manual page
ls --help # quick summary of options
man
opens the manual. Press
/
to search inside it,
n
for the next match, and
q
to quit. If a flag in this guide does not behave the way you expect on your server, the manual page for your specific distribution is the authority.
File and directory commands#
This is the largest category and the one you will use most.
Moving around and looking at things#
pwd # print the current directory
cd /var/www/html # change directory
cd .. # go up one level
cd ~ # go to your home directory
cd - # go back to the previous directory
ls # list files
ls -lh # long format, human-readable sizes
ls -la # include hidden files (dotfiles)
ls -lt # sort by modification time, newest first
ls -lt
is the one worth memorizing. When something on a site changed and you do not know what, sorting a directory by modification time usually points straight at it.
Reading files#
cat config.php # print the whole file
less error.log # page through a file (q to quit)
head -20 access.log # first 20 lines
tail -50 error.log # last 50 lines
tail -f error.log # follow the file as it grows
tail -f
is the standard way to watch a log while you reproduce a problem. Trigger the error in your browser, and the relevant lines appear as they are written. For PHP work specifically, this pairs with PHP error logging so the errors actually land in a file you can follow.
Creating, copying, and moving#
mkdir uploads # create a directory
mkdir -p a/b/c # create nested directories in one go
touch index.php # create an empty file (or update its timestamp)
cp source.txt dest.txt # copy a file
cp -r themes/ backup/ # copy a directory recursively
mv old.txt new.txt # rename
mv file.txt /tmp/ # move
cp
and
mv
overwrite the destination without asking. Add
-i
to be prompted first, or
-n
to never overwrite. On a production server,
-i
is a habit worth building. There is more detail, including preserving permissions and timestamps, in the guide on how to copy a file in Linux.
Deleting files and folders#
This is where people get hurt, so it deserves its own section.
rm file.txt # delete a file
rm -f file.txt # force, no prompts
rmdir emptydir # delete a directory, only if empty
rm -r somedir # delete a directory and everything in it
rm -rf somedir # recursive and forced
The difference between
rmdir
and
rm -r
matters.
rmdir
only removes a directory that is already empty, and it fails with an error otherwise. That failure is a feature: it means
rmdir
can never destroy data you forgot about.
rm -r
removes the directory and everything inside it, with no confirmation and no undo.
There is no recycle bin. There is no undelete.
rm -rf /
and its many typo variants have ended careers. Before running any recursive delete, run the same path through
ls
first and read what comes back. The full breakdown of the safe approaches is in how to remove a directory in Linux.
Searching for files and text#
Two commands cover almost every search:
find
locates files by their attributes,
grep
searches inside file contents.
find#
find /var/www -name "*.php" # by name
find /var/www -type d -name "cache" # directories only
find /var/www -mtime -1 # modified in the last 24 hours
find /var/www -size +50M # larger than 50 MB
find /var/www -user www-data # owned by a specific user
find
can also act on what it finds:
find /var/www -name "*.log" -delete
find /var/www -type f -exec chmod 644 {} \;
The
-mtime
search is the one that solves real problems. If a site was compromised,
find /var/www -mtime -2 -type f
lists every file changed in the last two days, which is usually a very short list of things that should not have changed. The Linux find command guide covers the time and permission predicates in depth.
grep#
grep "error" error.log # basic search
grep -i "error" error.log # case-insensitive
grep -r "wp_options" /var/www/html # recursive through a directory
grep -n "define" wp-config.php # show line numbers
grep -v "healthcheck" access.log # invert: lines that do NOT match
grep -c "404" access.log # count matching lines
Combining
grep
with a pipe is where it becomes powerful:
tail -1000 access.log | grep " 500 " | awk '{print $1}' | sort | uniq -c | sort -rn
That reads the last 1000 log lines, keeps the ones with a 500 status, extracts the IP address, and produces a count per IP sorted highest first. Diagnosing which client is triggering server errors takes one line. The grep command guide covers regular expressions and the flags in full, and there is a combined walkthrough of both tools in file and text searches via SSH.
File permissions and ownership#
Permission problems cause a large share of “it worked yesterday” incidents, particularly after a migration or a manual file upload.
chmod 644 wp-config.php # owner read/write, everyone else read
chmod 755 /var/www/html # directories need execute to be traversable
chmod -R 755 wp-content/ # recursive
chown www-data:www-data file # change owner and group
chown -R user:group /var/www # recursive
The numbers are octal: read is 4, write is 2, execute is 1, added together per position (owner, group, other). So 644 is read/write for the owner and read for everyone else. 755 adds execute, which on a directory means “can be entered.”
For a typical WordPress install, directories are 755 and files are 644. Anything set to 777 is a problem, not a fix. It is what people reach for when an upload fails, and it makes the file writable by every process on the server. The full model, including
chown
, groups, and the special bits, is in Linux file permissions: chmod and chown explained.
User and account commands#
whoami # current username
id # user ID, group ID, and group memberships
who # who is logged in right now
sudo command # run a single command as root
su - username # switch to another user
passwd # change your own password
sudo passwd username # change another user's password
To see the accounts that exist on a system, read
/etc/passwd
or use
getent
:
cat /etc/passwd | cut -d: -f1
getent passwd
Not every entry is a person. System accounts like
www-data
,
nginx
, and
mysql
exist to own processes and files, and they have UIDs below 1000 on most distributions. Human accounts start at 1000. How to list users in Linux covers the filtering, and how to change a user password in Linux covers password policy and expiry.
Process management#
ps aux # every running process
ps aux | grep php # filter for a specific process
top # live process view, sorted by CPU
htop # nicer version of top, if installed
kill 1234 # ask process 1234 to terminate (SIGTERM)
kill -9 1234 # force kill (SIGKILL)
pkill -f "php-fpm" # kill by matching the command line
Always try
kill
before
kill -9
. A plain
kill
sends SIGTERM, which lets the process flush buffers, close database connections, and shut down cleanly.
kill -9
cannot be caught or ignored, so the process dies mid-write. On a database process, that is how you get a corrupted table.
For long-running work over SSH,
nohup command &
or a terminal multiplexer like
screen
or
tmux
keeps the process alive after you disconnect. Otherwise, closing the connection kills the job. How to list running processes in Linux covers reading the output columns, which is the part most guides skip.
Services#
Modern Linux distributions manage services through systemd:
systemctl status nginx
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx # reload config without dropping connections
systemctl enable nginx # start automatically at boot
journalctl -u nginx -n 50 # last 50 log lines for the unit
Prefer
reload
over
restart
for web servers.
reload
re-reads the configuration while keeping existing connections alive.
restart
drops them. Unit names also differ between distribution families: Apache is
httpd
on Rocky Linux and RHEL,
apache2
on Ubuntu and Debian. Managing Linux services with systemctl has the full command set, and how to restart Linux from the command line covers reboots and shutdowns.
Disk and memory#
df -h # free space per filesystem
du -sh /var/www/html # total size of a directory
du -sh * | sort -rh | head # biggest items in the current directory
free -h # memory usage
lsblk # block devices and mount points
du -sh * | sort -rh | head
is the command to run when a disk fills up. It ranks everything in the current directory by size, so you can walk down the tree to the culprit in a few steps. It is usually a log file that was never rotated, an old backup, or a cache directory. How to check disk space in Linux covers the inode case, which is the confusing one:
df -h
shows free space, writes still fail, and the answer is
df -i
.
Networking and transfers#
ping example.com # basic reachability
curl -I https://example.com # response headers only
curl -v https://example.com # verbose, including the TLS handshake
wget https://example.com/file.zip # download a file
dig example.com # DNS lookup
ss -tulpn # listening ports and their processes
traceroute example.com # path to the host
curl -I
is the fastest way to check what a server is actually returning. Status code, redirects, cache headers, and security headers all come back in a few hundred milliseconds, without a browser cache in the way. The curl command guide covers POST requests, authentication, and header manipulation.
For moving files between machines:
scp file.txt user@host:/path/ # copy a file over SSH
scp -r dir/ user@host:/path/ # copy a directory
rsync -avz --progress src/ user@host:/dest/ # sync, transferring only differences
Use
scp
for one-off copies and rsync for anything repeated. rsync transfers only what changed, so the second run of a site sync takes seconds instead of minutes. Note that rsync treats a trailing slash on the source as significant, which is the single most common rsync mistake. There are practical walkthroughs in how to transfer files over SSH using SCP and how to sync directories with rsync, plus a SFTP command reference if you prefer an interactive session.
Getting to the server in the first place is SSH:
ssh user@example.com
ssh -p 2222 user@example.com # non-standard port
ssh user@host "df -h" # run one command and exit
SSH listens on port 22 by default. Running commands over SSH without opening an interactive session is useful in scripts, and passwordless SSH login with key authentication is both more convenient and more secure than typing a password.
Archiving and compression#
tar -czf backup.tar.gz /var/www/html # create a gzipped archive
tar -xzf backup.tar.gz # extract
tar -tzf backup.tar.gz # list contents without extracting
zip -r site.zip /var/www/html
unzip site.zip
The flags read as words:
c
create,
x
extract,
t
list,
z
gzip,
f
file,
v
verbose. Always run
tar -tzf
before extracting an archive someone else made. Some archives contain a top-level directory and some do not, and extracting the second kind dumps hundreds of files into your current directory. The tar command guide covers compression formats and selective extraction.
Text editors#
You need one editor you can use over SSH without thinking about it.
nano
is the simple choice. Commands are listed at the bottom of the screen,
Ctrl+O
saves,
Ctrl+X
exits. If you edit configuration files occasionally, nano is enough.
vim
is installed everywhere, including on minimal containers and rescue systems where nano is not. It has modes, which is what makes it confusing at first: press
i
to insert text,
Esc
to leave insert mode, then
:wq
to save and quit or
:q!
to quit without saving. Those four commands get you out of trouble. Vim essential commands covers the rest.
Scheduling with cron#
crontab -e # edit your crontab
crontab -l # list your cron jobs
crontab -r # remove all your cron jobs (careful, no confirmation)
A cron entry is five time fields followed by a command:
*/15 * * * * /usr/bin/php /var/www/html/cron.php
The fields are minute, hour, day of month, month, and day of week. The example runs every 15 minutes. Cron runs with a minimal environment and a different PATH than your login shell, which is why a script that works when you run it manually can silently fail from cron. Use absolute paths for everything. Cron job syntax with examples covers the special characters and the common failure modes, and running a WP-CLI command with cron covers the WordPress case specifically.
Linux distributions and which ones matter for hosting#
A Linux distribution is the kernel plus everything around it: the package manager, the init system, the default software versions, and a support and security update policy. The commands in this guide work on all of them. What differs is package management, release cadence, and how long a version receives security patches.
For servers, the field narrows to two families.
Debian family (Debian, Ubuntu). Uses
apt
for packages. Ubuntu LTS releases get five years of support and have the largest volume of documentation and tutorials, which is why most guides on the internet assume Ubuntu.
apt update && apt upgrade
apt install nginx
apt search php
RHEL family (RHEL, Rocky Linux, AlmaLinux, CentOS Stream). Uses
dnf
. These are built for long-lived production servers, with ten years of support per major release and a conservative approach to package updates.
dnf update
dnf install nginx
dnf search php
The other visible difference is the security model. RHEL-family distributions ship with SELinux enforcing by default, which adds a mandatory access control layer on top of standard file permissions. It stops a compromised web process from reading files it has no business reading. It also means a file with correct permissions can still be unreadable if its SELinux context is wrong, which surprises people the first time.
Hostney’s production servers run Rocky Linux 9 and Rocky Linux 10. Rocky is binary-compatible with Red Hat Enterprise Linux, so it inherits the ten-year support lifecycle and the RHEL security posture, without a per-server subscription. For a hosting platform, a predictable decade-long patch stream matters more than shipping the newest kernel. If you check
/etc/os-release
on a Hostney server, that is what you will see. There is more on the distribution landscape in Ubuntu vs Linux: what is the difference, and how to check your Ubuntu version covers identifying any distribution from the command line.
Quick reference#
| Task | Command |
|---|---|
| Where am I |
pwd
|
| List files by modification time |
ls -lt
|
| Follow a log live |
tail -f file.log
|
| Find files changed in 24 hours |
find . -mtime -1
|
| Search text recursively |
grep -r "text" .
|
| Fix directory permissions |
chmod 755 dir
|
| Fix file permissions |
chmod 644 file
|
| Change ownership |
chown -R user:group path
|
| See what is running |
ps aux
or
top
|
| Reload a web server config |
systemctl reload nginx
|
| Check free disk space |
df -h
|
| Find what filled the disk |
du -sh * | sort -rh | head
|
| Check response headers |
curl -I https://example.com
|
| Sync a directory to a server |
rsync -avz src/ user@host:/dest/
|
| Create an archive |
tar -czf out.tar.gz dir/
|
| Edit a cron job |
crontab -e
|
Building the habit#
The commands that stick are the ones you use on real problems. Pick a task you currently do through a graphical interface, such as checking a log file or looking at disk usage, and do it in a shell for a week instead. That is a faster path to fluency than working through a list.
Two safety habits are worth adopting immediately. Run destructive commands as a listing first: replace
rm
with
ls
, or add
--dry-run
to rsync, and read what comes back before committing. And check your working directory with
pwd
before any recursive operation. Nearly every serious command-line accident is a correct command run in the wrong directory.
On Hostney, you do not need a local SSH client to start. Every account includes browser-based terminal access from the control panel, opening a full shell in your account with your files, databases, WP-CLI, Composer, and Git already available. If you prefer a local client, SSH keys are managed in the panel as well.