The Linux File Descriptor

What Does echo "Hello" > /proc/1/fd/1 Actually Do?

If you’ve spent time debugging containers or reading shell scripts, you may have stumbled across a curious one-liner:

echo "Hello" > /proc/1/fd/1

At first glance it looks like magic. Let’s break it down piece by piece.


The /proc Filesystem

/proc is a virtual filesystem built into the Linux kernel. It doesn’t exist on disk — it’s generated on the fly by the kernel to expose information about running processes, system resources, and hardware.

Every running process gets its own directory under /proc/<PID>/, where PID is the numeric Process ID. So /proc/42/ contains everything the kernel exposes about process 42.


File Descriptors — The fd Directory

Inside each process directory you’ll find fd/, which lists all open file descriptors for that process. File descriptors are just integers that represent open files, sockets, pipes, or devices.

By convention:

FD Name Purpose
0 stdin Standard input
1 stdout Standard output
2 stderr Standard error

These are symlinks pointing to wherever the process has those streams connected — a terminal, a pipe, a log file, etc.


PID 1 — The Init Process

PID 1 is special. It’s the first process the kernel launches after boot — traditionally init, and on modern Linux systems, systemd. Every other process on the system is a descendant of PID 1.

So /proc/1/fd/1 is the stdout of PID 1.


Putting It All Together

When you run:

echo "Hello" > /proc/1/fd/1

You’re redirecting the output of echo into the stdout file descriptor of PID 1. You’re essentially hijacking the init process’s output stream and writing to it directly.


Why Is This Actually Useful?

This trick shines in Docker and container environments.

Inside a container, PID 1 is usually your entrypoint process (e.g., nginx, node, your app). Its stdout is connected to the container’s log driver, which is what surfaces when you run:

docker logs <container_id>

Now imagine a shell script running inside that container — maybe a cron job or a sidecar process. Its own stdout might be silently discarded. By writing to /proc/1/fd/1, it can inject messages directly into the container log stream, no matter where its own stdout points.

#!/bin/bash
echo "[cron] Starting backup..." > /proc/1/fd/1
# ... do work ...
echo "[cron] Backup complete." > /proc/1/fd/1

This is a clean, dependency-free way to get visibility into background processes inside containers.


A Note on Permissions

This doesn’t work for just anyone. To write to another process’s file descriptor, you typically need:

  • Root privileges, or
  • The same user as the target process

In many containers you’re running as root anyway, so it works out of the box. But in hardened or rootless container setups, you may need to adjust your approach.


Quick Reference

# Write to stdout of PID 1
echo "message" > /proc/1/fd/1

# Write to stderr of PID 1
echo "error" > /proc/1/fd/2

# Inspect what PID 1's stdout is connected to
ls -la /proc/1/fd/1

Summary

/proc/1/fd/1 is simply the standard output of the init process, exposed as a file path through Linux’s /proc virtual filesystem. Writing to it is a practical trick for surfacing log output from background processes inside containers — no extra tooling required, just a solid understanding of how Linux handles file descriptors.

Next time you’re scratching your head over why your container logs are silent, this little trick might be exactly what you need.

my DevOps Odyssey

“Σα βγεις στον πηγαιμό για την Ιθάκη, να εύχεσαι να ‘ναι μακρύς ο δρόμος, γεμάτος περιπέτειες, γεμάτος γνώσεις.” - Kavafis’ Ithaka.