Linux and Shell Scripting¶
Linux exposes processes, files, devices, sockets, and kernel state through a small set of composable interfaces. Learn to inspect before changing, and use shell scripts for short orchestration—not large applications.
Files and Paths¶
Important filesystem areas include:
/etc: system configuration;/var: changing service data, logs, caches, and queues;/run: volatile runtime state since boot;/tmp: temporary data with system-specific cleanup;/proc: process and kernel views;/sys: devices and kernel subsystem views;/usr: installed programs and read-only shared data;/home: user data.
Do not infer behavior from a path alone; distribution policy, mount options, containers, and services vary.
A hard link is another directory entry for the same inode and normally cannot cross filesystems. A symbolic link stores a target path and can become dangling. Renaming within one filesystem is atomic, but replacing a file does not update processes that already hold its old inode open.
ls -la path
stat path
file path
readlink -f path
find root -type f -name '*.log' -print
du -sh path
df -hT
Quote variable expansions: "$path". Use -- before untrusted path operands when a command supports it. Filenames can contain spaces, newlines, and leading hyphens; prefer null-delimited interfaces for arbitrary names.
Permissions¶
Traditional mode bits grant read, write, and execute to owner, group, and others. Directory execute means traversal; directory write allows entry changes, subject to other controls.
id
namei -l /path/to/file
chmod u=rw,go= file
chown app:app file
getfacl file
Avoid recursive permission changes until the exact target and desired file/directory differences are known. Set restrictive creation defaults with umask, but remember ACLs and application behavior also affect results.
Root bypasses many controls. Prefer a narrowly allowed privileged command through sudo over a root shell.
Processes and Signals¶
A process has an identity, parent, credentials, environment, open file descriptors, memory mappings, and resource limits. Threads share much of a process's state.
ps -eo pid,ppid,user,state,%cpu,%mem,etime,cmd
pgrep -a service-name
top
cat /proc/<pid>/status
ls -l /proc/<pid>/fd
SIGTERM requests graceful termination; SIGKILL cannot be handled and prevents cleanup. Send signals to a verified PID or service manager target—process names can match unrelated work and PIDs can be reused.
kill -TERM <pid>
wait <pid>
Load average counts runnable and uninterruptible tasks; it is not CPU percentage. Interpret CPU, run queue, I/O wait, memory pressure, and workload together.
Services and Logs¶
On systemd systems:
systemctl status myapp.service
systemctl show myapp.service
journalctl -u myapp.service --since '30 minutes ago'
systemctl cat myapp.service
systemctl reload-or-restart myapp.service
Validate configuration before reload or restart. Services should run as a dedicated user, declare dependencies, handle termination, bound resources, and write logs to the configured system path. Restart loops need backoff and an alert; automatic restart is not a repair.
Networking Inspection¶
ip address
ip route
ss -lntup
getent hosts example.com
curl --fail-with-body --show-error --verbose https://example.com/
Test each layer: name resolution, route, connection, TLS, HTTP, then application behavior. ping tests ICMP reachability only and may be blocked. Packet capture can expose credentials and user data; restrict access and retention.
Resource Diagnosis¶
free -h
vmstat 1
iostat -xz 1
pidstat 1
lsof -p <pid>
dmesg --level=err,warn
Availability depends on the installed tools and permissions. Begin from a symptom and compare normal versus affected periods. High memory use may be healthy cache; low free memory alone is not proof of a leak.
Shell Data Flow¶
Pipelines connect standard output to standard input; diagnostics should go to standard error. Exit status 0 means success by convention.
producer | filter >output.txt 2>errors.txt
Use rg for source-tree search, jq for JSON, and purpose-built parsers for structured formats. Parsing ls, human-oriented tables, or logs with unstable field positions is brittle.
A Safe Bash Skeleton¶
#!/usr/bin/env bash
set -Eeuo pipefail
usage() { printf 'usage: %s INPUT\n' "${0##*/}" >&2; }
cleanup() { [[ -n ${work_dir:-} ]] && rm -rf -- "$work_dir"; }
trap cleanup EXIT
[[ $# -eq 1 ]] || { usage; exit 2; }
input=$1
[[ -r $input ]] || { printf 'not readable: %s\n' "$input" >&2; exit 1; }
work_dir=$(mktemp -d)
cp -- "$input" "$work_dir/input"
printf 'prepared %s\n' "$input"
set -e has contextual exceptions and is not error handling. Check expected failures explicitly. The maintained Bash manual is authoritative for quoting, expansion, pipelines, and option details.
Shell Rules¶
- quote expansions unless splitting or globbing is explicitly intended;
- use arrays for lists, not space-separated strings;
- use
[[ ... ]]for Bash conditions and arithmetic syntax for numbers; - validate arguments and exact destructive targets;
- use
mktemp -dand a cleanup trap for temporary state; - prefer
while IFS= read -r line; preserve the final unterminated line when required; - make repeated execution safe or detect prior completion;
- log actions without leaking secrets;
- run
shellcheckand a small representative test.
For complex parsing, concurrency, data structures, or error recovery, use Python or another general-purpose language.
SSH¶
Use host keys to authenticate servers and protected keys or short-lived certificates for users. Verify new host fingerprints through a trusted channel; disabling host-key checking invites interception.
ssh -J bastion.example.com app.internal
ssh -L 127.0.0.1:5432:db.internal:5432 bastion.example.com
rsync -a --dry-run source/ host:/destination/
Bind forwarded ports to loopback unless external exposure is deliberate. Treat agent forwarding as delegated signing authority. Test rsync --delete with --dry-run and verified paths before use.
Scheduled Work¶
Schedulers provide a minimal environment and can overlap executions. Use absolute paths, explicit configuration, timeouts, locking where only one run is valid, durable status, and alerting on missed or failed runs. Ensure jobs are idempotent and define timezone and daylight-saving behavior.
Security Baseline¶
- patch from trusted repositories;
- minimize installed services and listening ports;
- use key-based or federated access and least privilege;
- protect secrets outside scripts and process arguments;
- configure firewall policy and audit privileged access;
- bound resources and rotate logs;
- back up required data and test restoration;
- prefer declarative, reviewed changes over interactive repair.
Checklist¶
- Did you inspect state before modifying it?
- Are paths and expansions quoted and validated?
- Is the command safe for arbitrary filenames and repeated runs?
- Are privilege, secrets, and destructive scope minimized?
- Do services handle signals, limits, logs, and restart loops?
- Can scheduled and remote operations fail visibly and recover safely?