Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ tracebloc dataset push ./my-data \
--label-column label
```

> **`tracebloc: command not found` after installing?** The binary installs to `~/.local/bin` when `/usr/local/bin` isn't writable, and an already-running shell won't see the new PATH entry until you open a new terminal (or `. ~/.bashrc`). See **[Troubleshooting installation](docs/troubleshooting.md)**.

What that runs under the curtain:

1. Reads kubeconfig, discovers the parent `tracebloc/client` release in the cluster
Expand Down
110 changes: 110 additions & 0 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Troubleshooting

## `tracebloc: command not found` after install

The installer downloads a single binary and drops it in a `bin` directory. If
that directory isn't on your shell's `PATH`, the `tracebloc` command won't be
found even though the binary is installed.

### Why it happens

`install.sh` installs to `/usr/local/bin` when that's writable. The usual
unprivileged one-liner (`curl … | sh`) **can't** write there, so it falls back
to **`$HOME/.local/bin`** — which isn't on `PATH` in many setups.

The installer adds `$HOME/.local/bin` to the rc file your shell actually reads
(`~/.bashrc`, `~/.zshrc`, `~/.bash_profile` on macOS, `~/.config/fish/config.fish`,
or `~/.profile`), but a shell that's **already running** won't see the change —
you need a new shell, or to re-load the rc file.

On Linux desktops there's an extra trap: the stock `~/.profile` only adds
`~/.local/bin` to `PATH` **at login**, and only if the directory already existed
at login time. The installer creates it mid-session, and a new terminal window
is an interactive *non-login* shell that reads `~/.bashrc` (not `~/.profile`) —
so "open a new terminal" alone never triggers the `~/.profile` logic. That's why
the installer writes to `~/.bashrc` directly.

### Fix it

**1. Confirm it's only a PATH problem** — run the binary by its full path:

```sh
~/.local/bin/tracebloc version # or: /usr/local/bin/tracebloc version
```

If that prints a version, the install is fine and this is purely `PATH`.

**2. Pick up the PATH entry the installer added** — open a **new** terminal, or
re-load your rc file in the current one:

```sh
. ~/.bashrc # bash on Linux
. ~/.zshrc # zsh (macOS default)
. ~/.bash_profile # bash on macOS
```

Then:

```sh
tracebloc version
```

**3. If it's still not found**, check which shell you're in and that the entry
landed in the matching rc file:

```sh
echo "$SHELL"
grep -n '.local/bin' ~/.bashrc ~/.zshrc ~/.bash_profile ~/.profile 2>/dev/null
```

If the line is in the wrong file (e.g. `~/.bashrc` while you actually run zsh, or
`~/.bashrc` on macOS where Terminal opens a login shell that reads
`~/.bash_profile`), add it to the right one:

```sh
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # adjust file to your shell
. ~/.zshrc
```

### Cleanest alternative: install where PATH already points

`/usr/local/bin` is on `PATH` for both login and non-login shells out of the box
on Linux and macOS. Installing there sidesteps the whole rc/login-shell question:

```sh
# Move the binary you already have:
sudo mv ~/.local/bin/tracebloc /usr/local/bin/

# …or re-run the installer with write access to /usr/local/bin:
curl -fsSL https://github.com/tracebloc/cli/releases/latest/download/install.sh | sudo sh
```

### Windows (PowerShell)

`install.ps1` installs to `%LOCALAPPDATA%\Programs\tracebloc` and adds it to your
**user** `PATH` automatically. The current PowerShell session won't refresh —
**open a new PowerShell window**, then:

```powershell
tracebloc version
```

If it's still missing, confirm the entry and check nothing at Process/Machine
scope overrides it:

```powershell
[Environment]::GetEnvironmentVariable('Path','User') -split ';' | Select-String tracebloc
```

## Server / SSH sessions

Each SSH login is a *login* shell, so it reads `~/.profile` (or `~/.bash_profile`
/ `~/.bash_login` if one exists — bash reads only the **first** that's present).
If you have a `~/.bash_profile` that doesn't source `~/.profile` or `~/.bashrc`,
the PATH entry may be skipped. Either add the `export PATH=…` line to the file
your login shell actually reads, or use the `/usr/local/bin` approach above.

## Still stuck?

Open an issue at [github.com/tracebloc/cli/issues](https://github.com/tracebloc/cli/issues)
with your OS, shell (`echo "$SHELL"`), and the output of `ls -l ~/.local/bin/tracebloc`.
54 changes: 50 additions & 4 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,58 @@ echo "Verify with:"
echo " $PREFIX/$BINARY_NAME version"
echo ""

# PATH guidance for the fallback case.
# PATH handling for the fallback case. install.ps1 persists the PATH
# entry on Windows (SetEnvironmentVariable, User scope) — do the same on
# Unix by writing to the rc file the user's shell actually reads. The old
# print-only advice silently failed on Ubuntu: ~/.profile adds
# ~/.local/bin only at *login* and only if it already existed, but the
# installer creates it mid-session, so a new (non-login) terminal reading
# ~/.bashrc never picks it up.
case ":$PATH:" in
*":$PREFIX:"*) ;; # already on PATH
*":$PREFIX:"*) ;; # already on PATH — nothing to do
*)
echo "Note: $PREFIX is not on \$PATH. Add this to your shell rc file:"
echo " export PATH=\"\$PATH:$PREFIX\""
shell_name="$(basename "${SHELL:-sh}")"
case "$shell_name" in
zsh) rc="$HOME/.zshrc" ;;
bash)
# macOS Terminal opens a login shell (reads .bash_profile);
# Linux terminals are interactive non-login (read .bashrc).
if [ "$OS" = "darwin" ]; then rc="$HOME/.bash_profile"; else rc="$HOME/.bashrc"; fi
;;
fish) rc="$HOME/.config/fish/config.fish" ;;
*) rc="$HOME/.profile" ;;
esac

if [ "$shell_name" = "fish" ]; then
path_line="fish_add_path $PREFIX"
else
path_line="export PATH=\"$PREFIX:\$PATH\""
fi

added=0
mkdir -p "$(dirname "$rc")" 2>/dev/null || true
if grep -qsF "$PREFIX" "$rc" 2>/dev/null; then
added=1 # rc already references it — leave it alone (idempotent)
# Group the append so the redirection-open error (e.g. an
# existing but read-only rc, or an unwritable parent dir) is
# suppressed too: `cmd >> "$rc" 2>/dev/null` leaks the shell's
# "Permission denied" because the >> open is attempted before
# 2>/dev/null applies. Wrapping in { ... } 2>/dev/null puts the
# stderr redirect in scope first, so the fallback message below
# is the only thing the user sees.
elif { printf '\n# Added by the tracebloc CLI installer\n%s\n' "$path_line" >> "$rc"; } 2>/dev/null; then
added=1
fi

echo ""
if [ "$added" = "1" ]; then
echo "Added $PREFIX to your PATH in $rc."
echo "Open a new terminal — or load it now: . \"$rc\""
else
echo "Note: $PREFIX is not on \$PATH and the installer couldn't update your shell config."
echo "Add this line, then open a new terminal:"
echo " $path_line"
fi
echo ""
;;
esac
Expand Down
Loading