Skip to content

Commit e403496

Browse files
committed
fix(init): use process substitution instead of pipe for bootstrap
Change the canonical invocation from `curl ... | zsh` to `zsh <(curl ...)`. With process substitution, stdin remains the terminal, so sudo prompts and other interactive input work without any /dev/tty workarounds or credential caching tricks. Reject piped stdin with a helpful error message (except in CI, which has no TTY but also has no interactive prompts).
1 parent 40082b7 commit e403496

5 files changed

Lines changed: 14 additions & 28 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ Personal dotfiles for macOS and Linux.
66

77
```sh
88
# macOS
9-
curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh | zsh
9+
zsh <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh)
1010
```
1111

1212
```sh
1313
# Ubuntu
14-
curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh | bash
14+
bash <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh)
1515
```
1616

1717
## What's included

bin/init/bootstrap-macos.sh

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
#!/bin/zsh
22
set -eo pipefail
33
# Bootstrap script for a fresh Mac.
4-
# Usage: curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh | zsh
4+
# Usage: zsh <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh)
55

6-
# When invoked via `curl ... | zsh`, stdin is the pipe. sudo and other
7-
# interactive prompts need the real terminal, so we verify /dev/tty early
8-
# and cache sudo credentials before any commands that require them.
9-
if [ ! -e /dev/tty ]; then
10-
printf "error: /dev/tty is not available; cannot run interactively\n" >&2
6+
if [ ! -t 0 ] && [ "${CI:-}" != "true" ]; then
7+
printf "error: stdin must be a terminal. Run with:\n" >&2
8+
printf " zsh <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh)\n" >&2
119
exit 1
1210
fi
1311

14-
# Cache sudo credentials up front via /dev/tty (stdin is the curl pipe).
15-
# A background loop keeps them fresh so long-running steps don't re-prompt.
16-
sudo -S -v < /dev/tty
17-
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
18-
1912
DOTFILES_DIR="${HOME}/dotfiles"
2013

2114
# Install Xcode Command Line Tools if missing.
@@ -40,4 +33,4 @@ if [ ! -d "$DOTFILES_DIR" ]; then
4033
git clone https://github.com/ebkn/dotfiles "$DOTFILES_DIR"
4134
fi
4235

43-
exec zsh "${DOTFILES_DIR}/bin/init/macos.sh" </dev/tty
36+
exec "${DOTFILES_DIR}/bin/init/macos.sh"

bin/init/bootstrap-ubuntu.sh

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
#!/bin/bash
22
set -eo pipefail
33
# Bootstrap script for a fresh Ubuntu machine.
4-
# Usage: curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh | bash
4+
# Usage: bash <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh)
55

6-
# When invoked via `curl ... | bash`, stdin is the pipe. sudo and other
7-
# interactive prompts need the real terminal, so we verify /dev/tty early
8-
# and cache sudo credentials before any commands that require them.
9-
if [ ! -e /dev/tty ]; then
10-
printf "error: /dev/tty is not available; cannot run interactively\n" >&2
6+
if [ ! -t 0 ] && [ "${CI:-}" != "true" ]; then
7+
printf "error: stdin must be a terminal. Run with:\n" >&2
8+
printf " bash <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh)\n" >&2
119
exit 1
1210
fi
1311

14-
# Cache sudo credentials up front via /dev/tty (stdin is the curl pipe).
15-
# A background loop keeps them fresh so long-running steps don't re-prompt.
16-
sudo -S -v < /dev/tty
17-
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
18-
1912
DOTFILES_DIR="${HOME}/dotfiles"
2013

2114
# Install git if missing.
@@ -31,4 +24,4 @@ if [ ! -d "$DOTFILES_DIR" ]; then
3124
git clone https://github.com/ebkn/dotfiles "$DOTFILES_DIR"
3225
fi
3326

34-
exec bash "${DOTFILES_DIR}/bin/init/ubuntu.sh" </dev/tty
27+
exec "${DOTFILES_DIR}/bin/init/ubuntu.sh"

bin/init/macos.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Setup script for macOS. Requires Xcode CLT and (on Apple Silicon) Rosetta.
44
# On a fresh Mac, use the bootstrap script instead:
5-
# curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh | zsh
5+
# zsh <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-macos.sh)
66

77
set -eo pipefail
88

bin/init/ubuntu.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Setup script for Ubuntu. Requires git.
44
# On a fresh machine, use the bootstrap script instead:
5-
# curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh | bash
5+
# bash <(curl -fsSL https://raw.githubusercontent.com/ebkn/dotfiles/main/bin/init/bootstrap-ubuntu.sh)
66
#
77
set -eo pipefail
88

0 commit comments

Comments
 (0)