Run your own small programs inside the Linux kernel — safely, and without changing or restarting anything.
🎯 Mission: see what your programs & system are really doing, liveeBPF lets you load tiny, sandboxed programs into the running Linux kernel that fire when an event happens — so you can watch exactly what the system is doing, with no source changes, no kernel module, and no reboot.
You're an app developer. When something is slow, flaky, or weird in production, your usual move is: add log lines, redeploy, and hope you logged the right thing. eBPF flips that around.
With eBPF you can ask the already-running system a precise question — "which files is this process opening?", "what's making this syscall?", "where is the latency?" — and get an answer in seconds. No code change. No restart. No guessing.
Your program runs in user space. But almost everything you'd want to observe — opening files, sending packets, scheduling threads, disk I/O — actually happens down in kernel space, on the other side of the system-call boundary. From user space you can see that you called open(), but not what the kernel did underneath.
Historically you had only two ways to run your own code inside the kernel to look — both bad for a casual observer:
Change the kernel itself, convince the community to merge it, then wait years for it to ship in distros. Not happening for a debugging session.
Load your own C code with full kernel privileges. A bug doesn't throw an exception — it panics the whole machine. And it breaks every kernel update.
This is the mental model the eBPF community itself reaches for. A web browser lets pages run little sandboxed JavaScript programs on events (a click, a page load). The browser guarantees that script can't crash your computer, and a JIT compiler makes it run fast.
eBPF does the same thing for the Linux kernel. The kernel is the "browser." Your eBPF program is the "JavaScript." Kernel events (a syscall, a function call, a network packet) are the "click handlers." A built-in safety checker plus a JIT make it safe and fast.
Analogy from ebpf.io — "What is eBPF?", the canonical introduction.
Here's the shape of every tracing session you'll do. An event in the kernel triggers your program; your program records something into a map (a shared table); your user-space tool reads the map and prints it to you.
Lifecycle & components per ebpf.io and Brendan Gregg, Linux eBPF Tracing Tools.
This is the part that makes eBPF usable in production — and the reason it's not just "kernel modules with a nicer name." When you load an eBPF program, the kernel's verifier statically analyzes it before a single instruction runs and rejects it unless it can prove:
If the proof fails, the program simply doesn't load — you get an error, the kernel keeps running. If it passes, a JIT compiler turns the bytecode into native machine code so it runs at roughly the speed of compiled-in kernel code. Loading generally requires root or the CAP_BPF capability.
Verifier behavior & safety guarantees: ebpf.io — What is eBPF?
You won't write kernel C to start — you'll write bpftrace, a high-level tracing language where everything from the diagram above is handled for you. Here's a real one-liner. Don't worry about the syntax yet; just see the shape:
# prints every file every program opens, system-wide bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s opened %s\n", comm, str(args->filename)); }'
sudo).Read it as WHEN ... DO ...:
tracepoint:syscalls:sys_enter_openat — every time any process enters the openat syscall (the event / hook).printf(...) — print the process name (comm) and the filename argument (args->filename).That one line is an eBPF program: bpftrace compiles it, the verifier checks it, the kernel attaches it to that syscall, and the output streams back to your terminal. You'll learn to read and write every piece of this in Lesson 3.
Style from the official bpftrace One-Liner Tutorial.
| Kernel module | eBPF program | |
|---|---|---|
| A bug can crash the kernel? | Yes — panic | No — won't even load |
| Safety checked before running? | No | Yes — the verifier |
| Need a reboot / module load? | Load module (risky) | No — load & unload live |
| Survives kernel upgrades? | Often breaks | Designed to be portable |
| Speed | Native | Native (JIT-compiled) |
| Good for a quick prod question? | No | Yes — its whole point |
Not to start. For observability you begin with bpftrace — a high-level language. C + libbpf is a later, optional step (out of scope for now).
The verifier rejects unsafe programs before they run. That's the core safety guarantee — and why it's production-friendly.
That's just the historical name (it grew out of tcpdump's packet filters). Modern eBPF is general-purpose; observability is a huge use case.
Linux-only — it's Linux-kernel tech. On macOS you'll run it inside a Linux VM. That's why this course is conceptual-first for now.
Pick an answer — you'll get instant feedback. No grading, just a tight feedback loop.
Click to reveal. Come back to these later for quick review.
Stuck on a term? Curious how this maps to a problem you've actually hit? Want a sharper analogy? Just ask in the chat. Good questions to try: "Show me what comm and args mean," or "What's a real bug I could've found faster with eBPF?"