Kahibaro
Discord Login Register

6.1 Linux for Developers

Why Linux Matters for Developers

Linux is the dominant environment for servers, containers, DevOps tooling, and cloud platforms. As a developer, that means:

This chapter focuses on what you specifically need as a developer on Linux: how to build, debug, version, and package code in a Linux environment.

You should already be comfortable with basic command-line usage, package managers, and filesystem layout from earlier chapters.


Development Environment Basics on Linux

Choosing a Shell for Development

You’ll use the shell constantly for building, testing, and scripting.

Common shells:

For development work:

Set your login shell (example for bash):

chsh -s /bin/bash

Organizing Project Directories

A common pattern:

mkdir -p ~/dev/{personal,work,opensource}
cd ~/dev/personal

Within a project, typical structure:

myproject/
  src/          # source code
  include/      # headers (for C/C++)
  tests/        # tests
  build/        # build artifacts (often added to .gitignore)
  docs/
  scripts/

Keeping build/ separate is especially important for C/C++ and similar compiled languages.

Useful Developer Tools to Install

Typical essentials (Debian/Ubuntu-style names; adjust per distro):

Example (Debian/Ubuntu):

sudo apt install build-essential cmake ninja-build pkg-config \
                 git vim gdb valgrind strace

Working Effectively with the Linux Toolchain

This section focuses on the traditional Unix toolchain you’ll encounter in build systems and CI: compilers, linkers, and supporting utilities.

Key Build Concepts

At a high level, most compiled-language builds follow:

  1. Compile source files to object files:
    • Example: main.cmain.o
  2. Link object files and libraries into an executable or library:
    • Example: main.o + libfoo.amyapp
  3. Install binaries, headers, config files into standard locations (often under /usr/local/ for local builds).

Compile + link is often combined into one command by tools like gcc, but the steps are conceptually separate.

The Compiler–Linker Pipeline in Practice

Example with C:

  gcc -c main.c -o main.o
  gcc main.o util.o -o myapp

Example:

  gcc main.c -I/usr/local/include -L/usr/local/lib -lmylib -o myapp

On Linux, shared libraries typically end with .so (e.g. libm.so for the math library, which you link via -lm).

Environment Variables for Builds

Build tools rely heavily on environment variables:

Example (temporary for a single command):

CC=clang CFLAGS="-O2 -g -Wall" make

This is core to cross-compiling, customizing builds, and CI pipelines.


Using `make` and Simple Build Automation

The make tool automates builds based on file dependencies. Full build-system coverage happens elsewhere; here we focus on what’s uniquely useful in day-to-day Linux dev work.

Basic `Makefile` Ideas for Developers

A minimal Makefile:

CC      := gcc
CFLAGS  := -Wall -Wextra -O2
LDFLAGS :=
SRC  := main.c util.c
OBJ  := $(SRC:.c=.o)
BIN  := myapp
all: $(BIN)
$(BIN): $(OBJ)
	$(CC) $(OBJ) $(LDFLAGS) -o $@
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@
clean:
	rm -f $(OBJ) $(BIN)

Key points:

Usage:

make         # builds the default target (here: all)
make clean   # cleans build artifacts

In CI, make is often the single entrypoint for building the project.


Package Management for Developers

You’ll often need libraries and headers for development, not just runtime packages.

Developer vs Runtime Packages

On Debian-like systems, development headers are usually in *-dev packages:

On RPM-based systems, they typically end with -devel:

Example (Debian/Ubuntu):

sudo apt install libcurl4-openssl-dev libssl-dev

If a build fails with a missing header, search your distro’s packages for that header name or library:

apt-cache search libcurl | grep dev   # Debian/Ubuntu
dnf search libcurl-devel              # Fedora/RHEL

Using `pkg-config`

pkg-config helps discover compiler and linker flags:

pkg-config --cflags --libs libcurl

Typical output:

-I/usr/include/x86_64-linux-gnu -lcurl

You can use this in Makefiles:

CFLAGS  += $(shell pkg-config --cflags libcurl)
LDFLAGS += $(shell pkg-config --libs libcurl)

If pkg-config can’t find a library, you may need to install its -dev/-devel package or adjust PKG_CONFIG_PATH.


Git Fundamentals on Linux

Git is central to Linux-based development; this section focuses on practical daily usage rather than in-depth theory.

Initial Git Configuration

Per-user config:

git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global core.editor "vim"

Check configuration:

git config --list

Creating and Cloning Repositories

Create a new local repo:

mkdir myproject && cd myproject
git init

Clone an existing repo:

git clone https://github.com/user/repo.git
cd repo

Daily Workflow: Status, Stage, Commit

  git status
  git diff          # unstaged changes
  git diff --cached # staged changes
  git add file1.c src/module.c
  git commit -m "Implement feature X"

Use .gitignore to exclude build artifacts (e.g. build/, *.o, .venv/).

Branching and Merging (Developer-Focused)

Create and switch branches:

git branch feature-x
git checkout feature-x
# or:
git checkout -b feature-x

Merge into the main branch:

git checkout main
git merge feature-x

Rebasing onto the latest main:

git checkout feature-x
git fetch origin
git rebase origin/main

For CI and code review, you’ll often:

Working with Remotes

Add a remote:

git remote add origin git@github.com:user/repo.git

Push a branch:

git push -u origin feature-x

Pull latest changes:

git pull       # fetch + merge/rebase depending on config
git fetch      # only update remote tracking branches

Git integration with SSH keys and CI-specific flows is covered elsewhere; here the focus is on your day-to-day commands.


Debugging Tools: `gdb`, `strace`, `lsof`

Linux provides powerful CLI debugging tools that integrate well with development and CI.

Building with Debug Symbols

For C/C++ debugging, compile with -g (debug info) and without heavy optimization (or with modest -O):

gcc -g -O0 main.c -o myapp

or in a CMakeLists.txt / Makefile via build-type flags.

Using `gdb` for Native Debugging

Basic session:

gdb ./myapp
(gdb) run arg1 arg2
(gdb) bt        # backtrace on crash
(gdb) info locals
(gdb) quit

Attach to a running process:

ps aux | grep myapp         # find PID
gdb -p <PID>

Useful breakpoints:

(gdb) break main
(gdb) break file.c:42
(gdb) break some_function

This is invaluable for debugging segmentation faults, memory corruption, and complex logic errors in native code.

Tracing System Calls with `strace`

strace shows system calls made by a process:

strace ./myapp

Common use cases:

  strace -e openat,stat ./myapp
  sudo strace -p <PID>

As a developer, strace is particularly useful when something behaves differently in production vs your local machine (e.g. missing config files, permission issues).

Inspecting Open Files and Ports with `lsof`

lsof lists open files (including network sockets):

  lsof -p <PID>
  sudo lsof -i :8080

This helps with debugging port conflicts and resource leaks.


Working with Interpreted Languages on Linux

Many developers primarily use Python, Node.js, or similar. Linux is often the reference platform for these runtimes.

Python Environment Basics

Typical pattern for a project:

  1. Create a virtual environment:
   python3 -m venv .venv
  1. Activate it:
   source .venv/bin/activate
  1. Install dependencies:
   pip install -r requirements.txt

Put .venv/ into .gitignore and keep requirements.txt under version control.

On Linux, you may also encounter distribution vs pip package conflicts; prefer virtual environments to avoid polluting system Python.

Node.js and npm

Common pattern:

npm init -y
npm install express --save
npm install --save-dev jest

Useful Linux-specific points:

Logs, Environment, and Configuration for Developers

Understanding how your app interacts with the Linux environment is key for debugging and operability.

Environment Variables at Runtime

Applications often rely on environment variables for configuration:

export APP_ENV=production
export DB_URL="postgres://user:pass@localhost/db"
./myapp

From code (examples):

  const char* env = getenv("APP_ENV");
  import os
  env = os.environ.get("APP_ENV")
  const env = process.env.APP_ENV;

In unit tests and CI, you typically set env vars in the test runner or CI configuration.

Working with Logs

Linux applications usually log to:

For developer-run services, you’ll often:

./myservice 2>&1 | tee myservice.log

Use tools like:

Add structured logs and log levels in your code to ease debugging in Linux environments.


Working Comfortably in Containers and CI

Modern development often targets containerized and CI environments that are Linux-based even if your desktop isn’t.

Building and Running in Docker (Developer View)

Example Dockerfile for building a simple C app:

FROM debian:stable-slim
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        build-essential && \
    rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN make
CMD ["./myapp"]

Build and run:

docker build -t myapp:latest .
docker run --rm myapp:latest

As a developer, you should:

CI-Friendliness

To run on Linux CI systems:

CI configuration specifics are covered in the DevOps chapters; your role as a developer is to structure code and commands in a CI-friendly way.


Performance and Profiling Basics for Developers

Performance tuning in depth is covered elsewhere; here is what you’re likely to touch as a developer.

Simple Timing

Use the time command:

time ./myapp

This reports real, user, and sys time.

CPU Profiling (Overview)

Common tools:

Example with perf:

perf record ./myapp
perf report

Higher-level performance tools and advanced tuning live in later chapters; as a developer, the key is to know these exist and to ensure your code can be run under them without extra interaction.


Summary: Linux Skills Every Developer Should Aim For

As a developer on Linux, you should be comfortable with:

These skills form the practical foundation for the more advanced DevOps and cloud topics that follow.

Views: 125

Comments

Please login to add a comment.

Don't have an account? Register now!