DEV Community

Warren Thinwar
Warren Thinwar

Posted on

What LuxDevHQ Week 2 Taught Me About Linux and Postgres

What LuxDevHQ Week 2 Taught Me About Linux and Postgres

Week 2 of the Data Engineering track at LuxDevHQ was the week I stopped treating the terminal like a black box that occasionally yells at me, and started treating errors like they were trying to help.

Nothing dramatic happened. I didn't break the server. I didn't lose data. If anything, the most useful moment of the whole week was a command that refused to run. But that refusal taught me more about how Linux thinks than any command that worked on the first try ever has.

Here's what stuck.

Orientation is not optional

Before this week, my instinct when I opened a terminal was to just start typing the command I came to run. This week I got burned — well, mildly singed — by jumping straight into a task without checking where I actually was.

Over the course of one session I was hopping between three different contexts: a remote droplet, my local WSL environment, and a Postgres-as-a-user shell. Half of my confusion that day wasn't about syntax at all. It was that I genuinely wasn't sure which machine or which user I was operating as when I ran a command.

So now this is muscle memory, five commands, every single time I open a new shell:

`bash
whoami                  # who am I?
hostname -I             # what machine am I on?
groups                  # what can I do here?
pwd                     # where am I?
ls -l                   # what's in front of me`?
Enter fullscreen mode Exit fullscreen mode

Boring. Cheap. Non-negotiable. It costs five seconds and it's saved me from running a "safe" command in the wrong context more than once.

SSH mistakes are loud, so don't repeat them

Small one, but worth writing down: I fat-fingered an SSH login with the wrong username (caleb instead of thinwar) and my first instinct was to just... try again with the same wrong username, thinking maybe I mistyped the password.

Bad habit. On a shared server, repeated failed logins with the same username look exactly like someone brute-forcing an account — even if it's just you being sleepy. The better habit is: if a login fails, stop, actually check which user you meant to be, and only then retry.

The usermod error that taught me the most this week

This is the one I want to spend the most time on, because it's the moment the whole week clicked for me.

I tried to change my own home directory while logged in as myself:

bash
usermod -d /home/data warren
Enter fullscreen mode Exit fullscreen mode

And it failed:

usermod
Enter fullscreen mode Exit fullscreen mode

: user warren is currently used by process 363

My first reaction, honestly, was mild annoyance — "why won't this just work." But sitting with it for a second: this is Linux doing something smart. You can't change certain fields — home directory, UID — for a user that has live running processes, because doing that mid-session could corrupt whatever's relying on the old value. And since I was logged in as warren, running the command as warren, I was always going to hit this wall.

Instead of guessing around it, I went and actually diagnosed what was running:

bash
ps -u warren                # everything running as me right now
ps -p 363 -f                # what specifically is PID 363?
ps -u warren --forest       # the whole process tree for my user
Enter fullscreen mode Exit fullscreen mode

And the real fix, if you genuinely need to change a live user's home directory, isn't a force flag — it's logging out and doing it from a different session or a different admin user entirely:

bash

sudo usermod -d /home/newpath -m warren
Enter fullscreen mode Exit fullscreen mode

The habit I'm taking from this: when usermod refuses with a "currently used by process" error, that's not a bug to route around. That's the system protecting you. My job is to log out and retry from elsewhere, not to go hunting for -f.

Shells, /etc/shells, and the case of the "no changes" mystery

Same session, different rabbit hole. I wanted to understand valid login shells before touching anything, so:

bash
cat /etc/shells
Enter fullscreen mode Exit fullscreen mode

This file is the system's allow-list — the programs it considers valid login shells. chsh and usermod -s will generally only accept a path that's listed here.

I compared my current shell against my options:

bash
echo $SHELL
grep warren /etc/passwd     # last field = configured login shell
cat /etc/shells
Enter fullscreen mode Exit fullscreen mode

Then tried setting it to something "different" just to watch the mechanism work:

bash
sudo usermod -s /usr/bin/bash warren
grep warren /etc/passwd
Enter fullscreen mode Exit fullscreen mode

And got told, essentially, "nothing changed." Turns out /bin/bash and /usr/bin/bash are usually just the same binary — one's a symlink to the other — so the system correctly recognized there was nothing to update. Not an error. Just Linux being precise.

The real lesson here is the gap between $SHELL and /etc/passwd. $SHELL reflects your current session — it can lag behind a change until you log back in. /etc/passwd is the ground truth for what's actually configured. So now: grep /etc/passwd before and after any shell change, always.

A safe checklist for changing a live user's settings

Putting the two lessons above together, this is the sequence I'm now committing to for touching any account that might be actively logged in:

bash

1. Check if the user has active processes

ps -u <user>
Enter fullscreen mode Exit fullscreen mode

2. Check current values before you touch anything

grep <user> /etc/passwd
Enter fullscreen mode Exit fullscreen mode

3. If processes exist and you're changing something process-sensitive

(home dir, UID, GID) — log that user out first, don't force it

4. Make the change

sudo usermod <flags> <user>
Enter fullscreen mode Exit fullscreen mode

5. Verify immediately

grep <user> /etc/passwd
id <user>
Enter fullscreen mode Exit fullscreen mode

The distinction worth internalizing (this feels like the kind of thing that gets asked in interviews): shell changes and supplementary group changes are generally safe to do on a live session. Home directory and UID changes are not — and the system will tell you so, if you're paying attention.

Postgres: the 3-step grant pattern for a role that can actually do things

The Linux stuff was about being careful. The Postgres stuff was about being complete. It's easy to create a role and grant it something, run a query, see it work, and think you're done — and then discover three weeks later that half of what the role needs is still locked.

Here's the sequence that actually gives a new role (teammate, or an app) working access, not just existence:

sql
-- Step 1: create the database and the role

CREATE DATABASE project_db;
CREATE USER app_user WITH PASSWORD 'change_me';
Enter fullscreen mode Exit fullscreen mode

-- Step 2: let the role connect and create inside the schema

GRANT ALL PRIVILEGES ON DATABASE project_db TO app_user;
\c project_db
GRANT USAGE, CREATE ON SCHEMA public TO app_user;

Enter fullscreen mode Exit fullscreen mode

-- Step 3: extend rights to tables — existing AND future

GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO app_user;

Enter fullscreen mode Exit fullscreen mode

That last line is the one that's easy to skip and expensive to forget. Without ALTER DEFAULT PRIVILEGES, any table someone creates after today won't automatically be visible to app_user. It's not implied by the earlier grants — it's a separate, forward-looking rule. Now it's a habit every time I provision a role, not an afterthought.

Inspecting a database like you didn't build it

Also practiced: the muscle of walking into an unfamiliar database and figuring out its shape before touching it, which is basically the day-to-day reality of joining any real team.

SQL
\c project_db
\dt              -- what tables exist?
\d customers     -- what does this one actually look like?
\ds              -- any sequences behind it?
\di              -- any indexes I should know about?
\du              -- who else has access?

Enter fullscreen mode Exit fullscreen mode

Then confirming data actually flows the way you expect:

SQL

INSERT INTO customers (first_name, last_name, email, age)
VALUES ('Test', 'User', 'test@example.com', 99);

SELECT * FROM customers WHERE age > 25;
Enter fullscreen mode Exit fullscreen mode

The one-line habit here: run \d

before writing any query against a table you didn't create. It's the fastest way to avoid a typo'd column name costing you ten minutes of confusion.

Permissions, practiced on something that doesn't matter

Small sandbox exercise, but a good one — practicing chmod/chown on a throwaway file instead of on anything that matters:

bash
touch practice.txt
ls -l practice.txt # baseline: -rw-r--r--

chmod u+x practice.txt # add owner execute
chmod g+w practice.txt # add group write
ls -l practice.txt # confirm: -rwxrw-r--

sudo chown $(whoami):$(whoami) practice.txt
rm practice.txt # clean up after yourself

Enter fullscreen mode Exit fullscreen mode

Habit: ls -l immediately before and after any permission change. Permissions are invisible until you actually check — and checking costs one command.

The loop underneath all of it

If I zoom out, everything above collapses into the same six-step loop, and I think this loop is actually the transferable skill — more than any individual command:

Orient — whoami, hostname -I, groups, pwd

Connect deliberately — SSH in, confirm you're where you meant to be

Inspect before you change — \l, \dt, \d, ls -l

Change one thing at a time

Verify immediately after — \dt, ls -l, id, SELECT *

Clean up test artifacts — drop test rows, remove scratch files

The actual takeaway

The usermod refusal is the moment I keep coming back to. It would have been easy to read that error as "this tool is broken" or go looking for a force flag to push through it. Instead it was the system correctly refusing to let me destabilize my own live session.

That's the real Week 2 lesson, underneath all the specific commands: learning to tell the difference between "this is a typo I need to fix" and "this is a safety feature doing its job." The second one shows up a lot more often in real infrastructure work than I expected, and it's a much better use of your attention than fighting it.

On to Week 3.

Top comments (0)