Page ↑ / Page ↓ to move · scroll works too
Linux & DevOps — Lecture 4 of 8
You can navigate the machine, and you know who’s allowed to touch what.
Today: run things, watch what they say, and move code onto the box.
Lecture 2 gave you the shell. Lecture 3 gave you the map and the lock. Both were about the machine sitting still. Today is about the loop you’ll run dozens of times a day for the rest of this course, and in any real DevOps job: start a service, check whether it’s actually working, read what it’s telling you when it isn’t, and ship a new version of the code it’s running.
Starts, stops, and supervises services from declarative unit files — and restarts whatever crashes.
Starts services concurrently based on a dependency graph, not a fixed sequence.
journald collects every service's output into one structured store, read back with journalctl.
Named states — multi-user, graphical, rescue — the replacement for numbered runlevels.
This was Lecture 1’s theory. Everything after this slide is the hands-on side of it — systemctl is how you talk to systemd, unit files are what you write for it to manage.
.service — a long-running or one-shot process.target — a named grouping of units, a synchronization point.timer — triggers another unit on a schedule, systemd's answer to cron.socket — starts its paired service on first connection, not at bootsystemctl list-units --type=service filters to just one type when the full list is noisy.[Unit] describes ordering and dependencies, [Service] is what actually runs and how systemd should react if it dies, [Install] says which target pulls this unit in when enabled.daemon-reload after any edit to a unit file — systemd caches unit definitions and won't notice the change otherwise. enable only wires it into a target for next boot; it does not start it now, which is why you usually run both enable and start, or enable --now to do both at once.Active line has both the state and how long it's held that statesystemctl --failed is the fastest "what's broken on this machine" you have — it lists only units that tried to start and gave up.Before systemd, each service wrote its own log file wherever it felt like, in whatever format it felt like. journald collects everything — kernel messages, every unit’s stdout/stderr, structured metadata like the unit name and PID — into one binary, indexed store. journalctl is the query tool in front of it.
-u scopes to one unit — almost always your starting point-f follows live, like tail -f-p filters by priority (emerg…debug), -b scopes to the current boot-e jumps straight to the end of the outputBy default the journal lives in /run/log/journal — memory, wiped on reboot. Creating /var/log/journal and restarting systemd-journald switches it to persistent, on-disk storage. —vacuum-* caps how much disk it’s allowed to hold onto.
This is the loop for the rest of the course. Lecture 2’s journalctl -u sshd | tail -n 50 one-liner was your first taste of it — now you know the rest of the flags around it.
The service is up according to systemctl. Nobody can reach it. Now what.
-t TCP, -u UDP, -l listening sockets only, -p show the owning process, -n numeric ports instead of resolving names. ss is the modern replacement for netstat, which isn't installed by default on RHEL 9 or AlmaLinux — ss comes from iproute, a core package on both.-c 4 sends four pings and stops, instead of running forever. dig/nslookup come from bind-utils, which — like git — is not installed by default: sudo dnf install bind-utils.ping tells you the host is reachable at all, ss tells you something's listening on that port, curl -v tells you whether the actual HTTP conversation succeeds — three different layers, three different tools, in the order you'd reach for them.Enough to sanity-check a web service from the command line.
-L follows redirects — plain curl stops at the first 3xx-I fetches headers only, via a HEAD request-o saves to a chosen filename, -O keeps the remote filenameThis is deliberately minimal — using curl to POST data and drive an API is a later lecture’s job, once we’re building the webhook listener the capstone needs.
-s silences the progress meter, -o /dev/null throws away the body since you only care about the code, -w prints just the format you ask for. This one line is the core of a health check — the same idea a future deployment script will use to decide whether to switch traffic to a new instance.How code gets onto the machines you now know how to run services on.
Same story as bind-utils in the last part — RHEL 9 and AlmaLinux 9 don’t ship git on a minimal install. Straight out of Lecture 3: it’s just another package, one dnf install away.
A remote is just a name for a URL. fetch downloads new commits without touching your working files; pull is fetch immediately followed by a merge into your current branch — which is why a pull can produce a conflict and a bare fetch never can.
status — what's changed, what's stageddiff — the actual line-by-line change, before you commit to itadd stages a change, commit records it with a messagelog --oneline --graph — the history, compactlyLogs, caches, dependency directories, and secrets don’t belong in the repository — a stray .env committed once stays in the history forever, even if you delete it in a later commit.
switch -c creates and moves onto a new branch in one step (the older, still-common spelling is checkout -b). A merge into a branch that hasn't moved since you branched off is a fast-forward — no new commit needed, just the pointer moving.Git marks both versions in the file itself. Edit it down to what it should actually say, delete the <<<<<<</=======/>>>>>>> markers, then add and commit like normal — the commit is what tells git the conflict is resolved.
ssh — Lecture 2git pull — fetch and merge the latest commit, todaysystemctl restart — reload the service with the new code, todayEvery piece of this line is now something you’ve actually learned, not just typed.