Linux screen Command Deep Dive: Terminal Multiplexing from Source to Practice#

If you’ve ever lost a long-running process because your SSH connection dropped, you know the pain. Today, let’s talk about screen — the terminal multiplexer that solves this problem — and dig into how it actually works.

What Problem Does screen Solve?#

Three key scenarios:

  1. Keep processes running after SSH disconnect: Network hiccups, laptop shutdown — your remote process stays alive
  2. Multiple windows in one terminal: No need for 10 SSH windows
  3. Session sharing: Pair programming, remote collaboration — two people see the same terminal

The core principle: screen creates a session management layer between kernel and user space. Your terminal window is just a “projection” — the actual process runs in screen’s virtual terminal.

Under the Hood: PTY and Session Separation#

Normal Linux terminal flow:

User input → SSH client → SSH server → PTY slave → Shell process

When SSH disconnects, the PTY slave is destroyed, and Shell receives SIGHUP → exits.

Screen inserts a layer in between:

User input → SSH client → screen client → screen server (independent process) → PTY slave → Shell

The key: screen server is an independent process, not tied to SSH. When you detach, the screen client disconnects, but the server keeps running. Shell doesn’t notice anything.

Key Data Structures (Simplified)#

struct win {
  int w_pid;              // Shell process ID
  struct pty w_pty;       // Pseudo-terminal device
  struct display *w_displays; // Connected displays
  char *w_buffer;         // Output buffer
  int w_width, w_height;  // Window size
};

Each window corresponds to one Shell process. When you switch windows, screen just changes “which window’s output to display”.

Practical Techniques: From Basics to Advanced#

Basic Usage#

# Create new session
screen -S mywork

# Create new window inside session (like opening a new tab)
Ctrl-a c

# Switch windows
Ctrl-a n  # Next window
Ctrl-a p  # Previous window
Ctrl-a 0-9  # Switch to specific window

# Detach (session keeps running)
Ctrl-a d

# List all sessions
screen -ls

# Reattach
screen -r mywork

Advanced: Logging and Monitoring#

# Start with output logging
screen -L -S build

# Log file defaults to screenlog.0
# Customize in ~/.screenrc
logfile /var/log/screen_%t.log

Shared Sessions: Pair Programming Made Easy#

# User A creates session
screen -S pair

# User B joins (same server required)
screen -x pair

Both see the exact same screen, and either one’s input shows up for both.

Session Locking: Security First#

# Lock session (password required to resume)
Ctrl-a x

# Or configure auto-lock in ~/.screenrc
autodetach on
lockscreen on

Performance Optimization and Edge Cases#

High Output Volume#

When compiling large projects, output can be massive. Screen’s default scrollback is only 100 lines:

# Set buffer size in ~/.screenrc
defscrollback 10000

# Or adjust at runtime
Ctrl-a : scrollback 50000

Window Size Sync#

When sharing sessions, if A’s terminal is 80x24 and B’s is 200x50, sizes conflict:

# Force maximum window size
termcapinfo xterm* 'hs:ts=\E]0;:fs=\007:ds=\E]0;\007'

Zombie Session Cleanup#

Sometimes screen sessions hang, showing Dead in screen -ls:

# Clean up zombie sessions
screen -wipe

# Force kill session (use carefully)
screen -S dead_session -X quit

screen vs tmux: Which to Choose?#

Similar features, but some differences:

Feature screen tmux
Config complexity Simple, works out of the box Powerful, complex config
Window management Basic Supports splits, layouts
Scripting Limited Strong (command mode)
Performance Lightweight Slightly heavier
Protocol Proprietary Can connect remotely

My experience: screen for quick tasks (mindless Ctrl-a d), tmux for complex setups (splits, scripting).

Implementing a Web Terminal Multiplexer#

To build something similar in the browser, the core is WebSocket + PTY:

import { spawn } from 'node-pty'
import { WebSocketServer } from 'ws'

const wss = new WebSocketServer({ port: 8080 })

wss.on('connection', (ws) => {
  const pty = spawn('bash', [], {
    name: 'xterm-256color',
    cols: 80,
    rows: 24
  })

  pty.onData((data) => ws.send(data))
  ws.on('message', (data) => pty.write(data.toString()))
  
  ws.on('close', () => {
    // Skip pty.kill() to persist session
    pty.kill()
  })
})

Frontend uses xterm.js for rendering, backend uses node-pty to create pseudo-terminals. For session persistence, store pty instances in Redis or memory.


Written: 2026-05-07 22:20

screen is one of those tools you don’t know you need until you try it. Once you understand how it works, debugging edge cases becomes much easier. Hope this helps.