We don’t need to be Linux experts, but we do need to be comfortable on a server. Whether we’re SSH’d into a production box, debugging a Docker container, or setting up a VPS — these commands come up constantly.
File Navigation
pwd # where am I? prints current directory
ls # list files in current directory
ls -la # show all files (hidden too), with permissions and sizes
ls -lh # human-readable file sizes (KB, MB, GB)
cd /var/log # go to an absolute path
cd .. # go up one directory
cd ~ # go to home directory
cd - # go back to the previous directory
Reading Files
cat app.log # dump entire file to terminal (fine for small files)
less app.log # scroll through file (q to quit, / to search)
head -n 20 app.log # first 20 lines
tail -n 50 app.log # last 50 lines
tail -f app.log # follow the file in real-time (great for watching logs)
tail -f is something we’ll use all the time in production. It keeps printing new lines as they’re added to the file.
File Manipulation
cp file.txt backup.txt # copy a file
cp -r src/ src_backup/ # copy a directory recursively
mv old.txt new.txt # rename or move a file
mkdir -p logs/2024/march # create nested directories in one go
touch notes.txt # create an empty file (or update timestamp)
rm file.txt # delete a file
rm -rf node_modules/ # delete directory and everything inside — BE CAREFUL
The -rf flag means “recursive” and “force” — it won’t ask for confirmation. One wrong rm -rf on a production server and we’re having a very bad day. Always double-check the path.
File Permissions
Every file has three permission groups: owner, group, and others. Each group can have read (r), write (w), and execute (x) permissions.
chmod 755 deploy.sh # owner: rwx, group: r-x, others: r-x
chmod 644 config.json # owner: rw-, group: r--, others: r--
chmod +x script.sh # add execute permission for everyone
chown manish file.txt # change file owner
chown manish:devs file.txt # change owner and group
Common permission sets: 755 for scripts we want to run, 644 for config files, 600 for private keys (SSH keys, secrets).
Process Management
ps aux # list all running processes
ps aux | grep node # find a specific process
top # real-time process viewer (q to quit)
htop # better version of top (install: apt install htop)
kill 1234 # gracefully stop process with PID 1234
kill -9 1234 # force kill (last resort, no cleanup)
lsof -i :3000 # what's using port 3000?
When a port is “already in use,” lsof -i :PORT tells us exactly which process is hogging it. Then we can kill it.
Text Search and Piping
grep "error" app.log # find lines containing "error"
grep -r "TODO" src/ # search recursively in a directory
grep -i "warning" app.log # case-insensitive search
grep -n "error" app.log # show line numbers
find . -name "*.log" # find all .log files in current directory
find /var -name "*.conf" -type f # find config files under /var
# Piping — send output of one command to another
ps aux | grep node | grep -v grep # find node processes
cat app.log | sort | uniq -c | sort -rn # count unique log lines
The | (pipe) is one of the most powerful tools in Linux. It chains commands together — the output of one becomes the input of the next.
Environment Variables
echo $PATH # print the PATH variable
echo $HOME # print home directory
export API_KEY="abc123" # set a variable for current session
env # print all environment variables
# Make it permanent — add to shell config
echo 'export API_KEY="abc123"' >> ~/.bashrc
source ~/.bashrc # reload the config without restarting terminal
Networking
curl https://api.example.com/users # make an HTTP request
curl -s https://example.com | head # silent mode, show first few lines
wget https://example.com/file.zip # download a file
ss -tlnp # list all listening TCP ports
# (older systems use: netstat -tlnp)
ping google.com # test if a host is reachable
nslookup example.com # look up DNS records
In simple language, we don’t need to memorize every flag — we need ls, cd, cat, grep, ps, kill, chmod, and curl to be comfortable on any server, and man <command> to look up everything else.