Skip to content

fix: improve non-interactive TTY detection in install.sh#3315

Open
mango766 wants to merge 1 commit intoatuinsh:mainfrom
mango766:fix/install-non-interactive-tty-detection
Open

fix: improve non-interactive TTY detection in install.sh#3315
mango766 wants to merge 1 commit intoatuinsh:mainfrom
mango766:fix/install-non-interactive-tty-detection

Conversation

@mango766
Copy link
Copy Markdown

Fixes #3294

Checks

  • I am happy for maintainers to push small adjustments to this PR, to speed up the review cycle
  • I have checked that there are no existing pull requests for the same thing

Problem

The install script's non-interactive detection uses { true </dev/tty; } to check if a terminal is available. This only tests whether /dev/tty can be opened, not whether it is actually a functional terminal. In containers, CI, and headless environments (like the Ona setup described in #3294), /dev/tty may exist as a device node that the shell can open, but isn't backed by a real terminal. This causes:

  1. The detection to incorrectly conclude the session is interactive
  2. The subsequent read </dev/tty calls to fail with cannot open /dev/tty: No such device or address
  3. The final atuin setup </dev/tty call to hang indefinitely

Fix

Two changes, both in install.sh:

1. Stronger TTY detection — Replace { true </dev/tty; } with ( exec </dev/tty && [ -t 0 ] ). This opens /dev/tty as stdin inside a subshell, then checks it's actually a terminal with test -t. The subshell ensures the redirect doesn't affect the parent process.

2. Suppress stderr on read fallbacks — Add 2>/dev/null to the two read </dev/tty calls. They already have || var="n" fallbacks, but without stderr suppression, failed redirects produce noisy error messages on shells like dash.

The `{ true </dev/tty; }` check only verifies that /dev/tty can be
opened, not that it is a functional terminal. In containers, CI, and
headless environments, /dev/tty may exist as a device node but not be
backed by a real terminal, causing subsequent `read </dev/tty` calls
to fail with "cannot open /dev/tty" errors or hang indefinitely.

Replace the check with a subshell that opens /dev/tty as stdin and
verifies it is a terminal via `test -t 0`. Also add `2>/dev/null` to
the read calls as a safety net against noisy errors if the detection
is ever bypassed.

Fixes atuinsh#3294
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 20, 2026

Greptile Summary

Fixes false-positive interactive detection in install.sh for environments where /dev/tty exists but isn't backed by a real terminal (containers, CI, headless setups). The fix is correct and POSIX-compatible.

  • Replaces { true </dev/tty; } with ( exec </dev/tty && [ -t 0 ] ) to verify /dev/tty is actually a terminal, not just openable
  • Adds 2>/dev/null to read </dev/tty calls to suppress noisy errors on dash and similar shells

Important Files Changed

Filename Overview
install.sh Strengthens TTY detection and suppresses stderr on read fallbacks; changes are correct and POSIX-compatible.

Last reviewed commit: "fix: improve non-int..."

@mentalisttraceur
Copy link
Copy Markdown
Contributor

Thank so much for taking care of this!


printf "Would you like to import your existing shell history into Atuin? [Y/n] "
read -r import_answer </dev/tty || import_answer="n"
read -r import_answer </dev/tty 2>/dev/null || import_answer="n"
Copy link
Copy Markdown
Contributor

@mentalisttraceur mentalisttraceur Mar 24, 2026

Choose a reason for hiding this comment

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

I recommend not suppressing errors from the two reads.

Think about it this way: those error messages were the reason why we were able to diagnose the issue in my bug so quickly.

Without them, it would just be an unexplained hang.

My issue is fixed with a better TTY check, but if we hit some other problem during read, the error messages would be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: unattended install broken

2 participants