Skip to content

docs: FAQ on command output appearing only at exit - #453

Merged
asmacdo merged 1 commit into
con:mainfrom
asmacdo:buffer-flush-faq
Sep 30, 2026
Merged

asmacdo merged 1 commit into
con:mainfrom
asmacdo:buffer-flush-faq

Conversation

@asmacdo

@asmacdo asmacdo commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Under duct, programs that block-buffer stdout when it isn't a TTY (python, perl, C stdio tools) show their output only at exit. duct can't fix this transparently without a PTY (#26) or mutating the child's env, so instead of the --buffer-flush option proposed in #218, this adds a README FAQ with per-program workarounds.

Closes #218

  • New FAQ "My command's output only appears when it finishes", after the TTY FAQ it builds on
  • Table: python -u / PYTHONUNBUFFERED=1, stdbuf -oL (C stdio, incl. pipelines), perl $| = 1;, and unbuffer / script as a catch-all
  • Limits: stdbuf ignored by python/perl/static/setuid; PTY wrappers put escape codes in the captured logs
How the table was verified

Fedora 42, glibc, duct on main. Each child printed 3 lines 1 s apart; measured the spread between the first and last stdout line as seen on duct's terminal side (2.0 s = live, 0.0 s = buffered to exit).

Child Default Worked Did not work
bash echo loop live
python buffered python -u, PYTHONUNBUFFERED=1, unbuffer, script -qefc stdbuf -oL
C (glibc stdio, dynamic) buffered duct stdbuf -oL cmd, stdbuf -oL duct cmd
perl buffered $|=1, unbuffer, script -qefc stdbuf -oL
loop | grep in bash -c buffered grep --line-buffered, stdbuf -oL bash -c …, unbuffer, script -qefc
loop | gawk in bash -c buffered stdbuf -oL bash -c …
rust, go, node, java live

PTY log cost: grep --color=auto under unbuffer or script wrote 20 ESC bytes into _stdout (0 without). Static binaries were not tested (no static libc on the test host); macOS gstdbuf not tested.

🤖 Generated with Claude Code

Programs that block-buffer stdout when it is not a TTY (python, perl,
C stdio tools) show their output only at exit under duct. Document why
duct cannot fix this transparently and the per-program workarounds.

Closes con#218

Co-Authored-By: Claude Code 2.1.285 / Claude Opus 5.5 <noreply@anthropic.com>
@asmacdo asmacdo added the semver-documentation Changes only affect the documentation label Sep 30, 2026
@codecov

codecov Bot commented Sep 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.03%. Comparing base (7a25f42) to head (b662abc).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #453   +/-   ##
=======================================
  Coverage   92.03%   92.03%           
=======================================
  Files          15       15           
  Lines        1344     1344           
  Branches      182      182           
=======================================
  Hits         1237     1237           
  Misses         71       71           
  Partials       36       36           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@asmacdo
asmacdo marked this pull request as ready for review September 30, 2026 17:02
Copilot AI balanced review requested due to automatic review settings September 30, 2026 17:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

It is a documentation-only FAQ addition whose workarounds, links, formatting, and table escaping are accurate and consistent with existing README conventions.

Review effort: Balanced
Findings: None

What changed in this PR

This PR adds a new README FAQ entry explaining why some commands' stdout appears only at exit under duct — a consequence of duct attaching pipes (not a PTY) to the child, which triggers block-buffering in programs like Python, Perl, and C stdio tools. Rather than implementing the --buffer-flush option proposed in #218, it documents per-program workarounds, keeping duct's "output as-is" behavior intact. It builds directly on the preceding TTY FAQ and closes #218.

Changes:

  • Adds FAQ "My command's output only appears when it finishes" after the related TTY FAQ.
  • Provides a workaround table (python -u/PYTHONUNBUFFERED=1, stdbuf -oL, Perl $| = 1;, and unbuffer/script as a catch-all).
  • Documents limitations: stdbuf has no effect on Python/Perl/static/setuid binaries, and PTY wrappers inject escape codes into the captured logs.
File Description
README.md Adds a new FAQ section with a per-program workaround table and caveats for commands that buffer stdout when not attached to a TTY.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@asmacdo
asmacdo merged commit d7a5e24 into con:main Sep 30, 2026
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-documentation Changes only affect the documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--buffer-flush, -b option

2 participants