Linux · Lesson 16
Linux Defensive Command Line
Use the Linux command line as a defensive investigation tool: inspect users, processes, services, files, packages, networking, and logs before making controlled, verifiable changes.
Good command-line work is not about memorizing hundreds of commands. It is about asking the right question, choosing the narrowest command that answers it, preserving evidence, and verifying the result.
Lesson Snapshot
Learning objectives
Use commands to answer defensive questions safely
Use core Linux command-line tools to inspect users, processes, services, files, permissions, packages, networking, and logs safely.
Distinguish inspection commands from change commands so students know when they are observing versus modifying the system.
Build short defensive command sequences that answer specific questions instead of running broad destructive commands.
Interpret command output critically, including empty results, permission errors, symbolic links, truncated output, and stale information.
Use shell features such as pipes, grep, sort, head, tail, and redirection without accidentally overwriting evidence.
Apply verification commands after changes so the command line supports a complete defensive workflow rather than isolated actions.
Core idea
Commands should answer questions, not replace reasoning
The command line is strongest when you already know what you are trying to learn. Start with a question, gather evidence, then choose the smallest justified change.
Safety boundary
A short command can have a huge impact
Commands such as rm, chmod, chown, kill, apt remove, systemctl, and firewall edits can change the system immediately. Understand scope and rollback before execution.
Command-line principles
Six habits for defensive terminal work
Inspect before modify
Start with commands that reveal the current state. A good defender gathers context before changing accounts, services, files, packages, or firewall rules.
Ask one question at a time
Each command should answer a clear question: Which users exist? What is listening? Which service owns this process? What changed recently?
Prefer narrow scope
Target one account, one service, one directory, or one time range rather than scanning or changing the entire system without purpose.
Read output carefully
Blank output, permission errors, symbolic links, aliases, and command defaults all affect interpretation. Do not treat missing output as proof that nothing exists.
Preserve evidence
When a command reveals suspicious data, record or export it before removing files, stopping processes, or changing configurations.
Verify after change
Every modification should be followed by commands that confirm the intended result and check required functionality.
Core shell tools
Build strong inspection habits with simple commands
pwd
Show the current working directory so you know where relative paths begin.
pwdls
List directory contents. Use -l for metadata and -a to include hidden entries.
ls -la /etc/sshcat
Print file contents. Best for short text files.
cat /etc/os-releaseless
Page through long text without loading everything into the visible terminal at once.
less /var/log/auth.loghead / tail
Show the beginning or end of a file or command output.
tail -n 50 /var/log/sysloggrep
Search text for matching patterns.
grep -i 'failed' /var/log/auth.logsort / uniq
Organize repeated text and count or remove duplicates.
cut -d: -f7 /etc/passwd | sort | uniq -cfind
Search the filesystem by path, type, owner, permissions, time, or other metadata.
sudo find /etc -maxdepth 2 -type f -mtime -1 -lsstat
Show detailed file metadata such as owner, mode, size, and timestamps.
stat /etc/ssh/sshd_configfile
Identify the type of a file based on content and metadata.
file /usr/local/bin/toolreadlink
Resolve symbolic-link targets.
readlink -f /etc/resolv.confnamei
Inspect permissions and ownership along every component of a path.
namei -l /home/user/.ssh/authorized_keysUsers & privilege
Commands for account review
getent passwdWhich local and directory-backed user accounts are visible through the system's configured account sources?
getent groupWhich groups are visible through the configured group sources?
id usernameWhat UID, primary group, and supplementary groups belong to this user?
groups usernameWhich groups is this user a member of?
sudo -l -U usernameWhat sudo privileges does this user have?
passwd -S usernameWhat is the user's password state?
chage -l usernameWhat password-aging and account-expiration settings apply to the user?
lastlogWhat is the recorded last-login information for local accounts?
Processes & sockets
Commands for runtime investigation
ps auxWhich processes are currently running, under which users, and with what resource usage?
ps -ef --forestHow are processes related by parent and child relationships?
pstree -apWhat does the process tree look like with arguments and PIDs?
topWhich processes are using the most CPU or memory right now?
readlink -f /proc/PID/exeWhich executable backs this process?
tr '\0' ' ' < /proc/PID/cmdlineWhat command line launched this process?
sudo lsof -p PIDWhich files and sockets are open in this process?
ss -tulpnWhich TCP and UDP sockets are listening, and which processes own them?
Services
Commands for systemd service review
systemctl --type=service --state=runningWhich systemd services are currently running?
systemctl --failedWhich systemd units are currently failed?
systemctl status service-nameWhat is the service's current state, recent logs, PID, and unit information?
systemctl is-enabled service-nameWill the service start automatically according to systemd enablement state?
systemctl cat service-nameWhich unit file and drop-in overrides define the service?
systemctl list-dependencies service-nameWhich units does this service depend on?
journalctl -u service-name --since todayWhat has the service logged today?
Files & permissions
Commands for ownership and access review
ls -ld /path /path/to/fileWho owns the directory and file, and what are the basic permissions?
stat /path/to/fileWhat detailed mode, owner, group, size, and timestamps apply?
getfacl /path/to/fileDo ACLs grant access beyond the standard owner/group/other mode bits?
namei -l /path/to/fileAre any parent directories writable or inaccessible in a way that changes the security picture?
sudo find /home -xdev -type f -perm -0002 -lsWhich files under /home are world-writable on this filesystem?
sudo find / -xdev -type f -perm -4000 -ls 2>/dev/nullWhich files on the current filesystem have the setuid bit?
Packages
Commands for software review
apt list --installedWhich packages does APT report as installed?
dpkg -lWhat is the Debian package database state?
apt-cache policy package-nameWhich package version is installed and which repositories can provide it?
apt show package-nameWhat metadata describes this package?
dpkg -S /path/to/fileWhich installed package owns this file?
apt-mark showmanualWhich packages are marked as manually installed?
apt list --upgradableWhich installed packages have newer candidate versions available?
Networking
Commands for interfaces, routes, DNS, and firewall review
ip linkWhich network interfaces exist and which are up?
ip addrWhich IPv4 and IPv6 addresses are assigned?
ip routeWhich IPv4 routes and default gateway are active?
ip -6 routeWhich IPv6 routes are active?
ip neighWhich directly connected neighbors are in the cache?
nmcli device statusWhat device state does NetworkManager report?
resolvectl statusWhich DNS servers and search domains are active when systemd-resolved is used?
sudo ufw status verboseWhat host-firewall policy and rules are active?
Logs
Commands for system evidence
journalctl -bWhat happened during the current boot?
journalctl --list-bootsWhich boot sessions are retained?
journalctl -p warning..alert -bWhich warning-or-higher events occurred this boot?
journalctl -u service-name --since todayWhat did this service log today?
sudo grep -iE 'failed|invalid|accepted|sudo' /var/log/auth.log | tail -n 100Which recent authentication-related events match these keywords?
sudo tail -n 100 /var/log/apt/history.logWhich recent APT transactions occurred?
Pipes & redirection
Combine commands without overwriting evidence accidentally
|Pipe
Send the output of one command into the input of another.
ps aux | grep ssh>Overwrite redirection
Write command output to a file, replacing existing contents.
command > output.txt>>Append redirection
Add command output to the end of a file.
command >> notes.txt2>Standard-error redirection
Redirect error output separately.
find / -name target 2>/dev/null&&Run next on success
Run the next command only if the previous command succeeds.
sudo sshd -t && sudo systemctl reload ssh||Run next on failure
Run the next command only if the previous command fails.
command || echo 'Command failed'Be careful with >
Single greater-than redirection overwrites the destination file. If that file already contains notes or evidence, its prior contents are replaced.
Defensive sequences
Chain small commands into an investigation
Investigate an unknown listening port
ss -tulpnps -fp PIDreadlink -f /proc/PID/exetr '\0' ' ' < /proc/PID/cmdlinedpkg -S /path/to/executablesystemctl status suspected-serviceMove from socket to process, executable, package, and service context before deciding whether the listener is required.
Review an unfamiliar user
getent passwd usernameid usernamegroups usernamesudo -l -U usernamepasswd -S usernamechage -l usernamelastlog -u usernameBuild the user's identity, privilege, password, aging, and login picture before changing the account.
Review a suspicious startup file
stat /path/to/filefile /path/to/filereadlink -f /path/to/filenamei -l /path/to/filedpkg -S /path/to/filesed -n '1,220p' /path/to/filePreserve metadata, understand path security, determine package ownership, and read contents before disabling or removing it.
Troubleshoot a failing service
systemctl status service-namejournalctl -u service-name --since todaysystemctl cat service-namesystemctl list-dependencies service-nameservice-specific-config-testUse service state, logs, effective unit configuration, dependencies, and supported validation before restart.
Investigate a DNS complaint
ip addrip routeresolvectl statusreadlink -f /etc/resolv.confcat /etc/resolv.confgetent hosts example.comSeparate interface and routing health from resolver configuration and actual name-resolution behavior.
Interpretation traps
Command output can be incomplete or misleading
grep returned nothing
The pattern was not found in that input, but the data may exist elsewhere, use different capitalization, be compressed, or require permission.
Permission denied
The command may lack authorization. Do not conclude the file or directory does not exist.
Command not found
The package may be absent, PATH may be different, or the tool may have another location.
Output is truncated
Terminal width, ps defaults, pager behavior, or application output formatting may hide part of the evidence.
A process name looks familiar
Names can be misleading. Confirm executable path, command line, owner, parent, package, and service context.
A file has a recent timestamp
Recent modification can result from updates, legitimate administration, configuration management, or suspicious activity.
Change commands
Know when the command stops observing and starts modifying
Command
sudo systemctl stop service-nameEffect
Stops a service.
Caution
Confirm the service is not required and preserve evidence first.
Command
sudo systemctl disable service-nameEffect
Changes whether a service starts automatically.
Caution
Does not necessarily stop the currently running service.
Command
sudo ufw delete RULE_NUMBEREffect
Removes one firewall rule.
Caution
Re-check numbered rules immediately before deletion because numbering can change.
Command
sudo gpasswd -d username groupnameEffect
Removes a user from a supplementary group.
Caution
Confirm the user does not require the privilege for a scenario-defined role.
Command
sudo chmod MODE /path/to/fileEffect
Changes file permissions.
Caution
Use the narrowest justified mode and verify service access afterward.
Command
sudo chown OWNER:GROUP /path/to/fileEffect
Changes ownership.
Caution
Do not use broad recursive ownership changes without understanding application expectations.
High-risk shortcuts
Commands that can cause major damage when used casually
sudo rm -rf as a cleanup habit
Recursive forced deletion can destroy the operating system, evidence, or required application data.
chmod -R 777
Creates broad write access and can introduce privilege-escalation paths.
kill -9 first
Forces immediate process termination, prevents graceful cleanup, and can destroy useful runtime evidence.
apt remove based only on package name
Can remove required software and dependencies without understanding system impact.
find / with destructive -exec actions
A broad search combined with automatic deletion or chmod can affect huge portions of the system.
Redirecting evidence with > into an existing file
Overwrite redirection destroys the previous contents of the destination file.
Verification
End every command-line change with proof
Users
Do required accounts and group memberships still match the scenario?
Services
Are required services running and unnecessary confirmed services stopped or disabled as intended?
Files
Do ownership, permissions, ACLs, and parent-directory permissions match the intended state?
Packages
Are required packages present and unintended software changes documented?
Network
Are required interfaces, routes, DNS, firewall rules, and listeners still functional?
Logs
Do post-change logs show successful operation without new errors or unexpected authentication activity?
Defensive lab
Investigate a fictional unknown listener from the terminal
Read the fictional scenario: SSH and an HTTPS application are required, Morgan is the only administrator, and an unknown process is listening on TCP 9090.
Use inspection commands only to review users, sudo access, running services, listening ports, routes, UFW rules, and current-boot logs.
Trace the TCP 9090 listener from socket to PID, process owner, executable path, command line, package ownership, and service unit.
Preserve the relevant command outputs and service logs before making any change to the unknown listener.
Classify the listener as Required, Unnecessary, Suspicious, or Unknown based on scenario and evidence rather than port number alone.
If the lab evidence confirms the service is unauthorized, stop and disable only that service using controlled commands.
Verify SSH, HTTPS, UFW, service state, listening sockets, user privileges, and post-change logs.
Lesson checklist
Before moving on
I know which commands are inspection-only and which commands modify the system.
I ask a specific defensive question before choosing a command.
I use narrow paths, users, services, and time ranges instead of broad destructive scope.
I can trace a listening port to a process, executable, package, and service.
I can review a user's identity, groups, sudo privileges, password state, and login history.
I can inspect file ownership, permissions, ACLs, and parent-directory security.
I can review interfaces, routes, DNS, firewall rules, and listening services.
I understand pipes and redirection and know that > overwrites the destination.
I preserve suspicious evidence before stopping services or deleting files.
I verify the intended state after every meaningful change.
Reflection
Check your reasoning
Question 1
Why is ss -tulpn only the first step when investigating an unknown listening port?
Question 2
Why can grep returning no output be misleading?
Question 3
What is the security difference between > and >> redirection?
Question 4
Why should kill -9 usually not be the first process-control action?
Question 5
Why is package ownership useful but not sufficient to prove a file is safe?
Question 6
What commands would you use to verify that a defensive change did not break required SSH or HTTPS access?
Carry this forward
Defensive command-line work follows a simple discipline: ask a precise question, inspect narrowly, preserve important evidence, make the smallest justified change, and verify the real system function afterward.