diff --git a/linux-managements/setup.sh b/linux-managements/setup.sh index db30b60..1e7590a 100755 --- a/linux-managements/setup.sh +++ b/linux-managements/setup.sh @@ -300,13 +300,16 @@ setup_fish() { info "$FISH_PATH already in /etc/shells" fi - # Change default shell only if not already fish + # Change default shell only if not already fish. + # Prefer usermod (script-friendly, no TTY/PAM quirks); fall back to chsh. + # Never abort the whole setup if this fails — just warn and move on. current_shell="$(getent passwd "$USER" | cut -d: -f7)" if [ "$current_shell" = "$FISH_PATH" ]; then info "fish is already the default shell" - else - psudo chsh -s "$FISH_PATH" "$USER" + elif psudo usermod -s "$FISH_PATH" "$USER" || psudo chsh -s "$FISH_PATH" "$USER"; then success "Default shell changed to fish ($FISH_PATH)" + else + warn "Could not change default shell to fish — run manually: sudo usermod -s $FISH_PATH $USER" fi # For brew-based systems: add brew shellenv to fish config @@ -749,6 +752,24 @@ setup_passwordless_sudo() { esac } +# ─── Normalize user/group databases ────────────────────────────────────────── +# shadow's commonio_open() refuses to modify a database whose last line is not +# newline-terminated, failing with a misleading "cannot open /etc/passwd". +# Some installers/tools leave these files unterminated, which then breaks chsh, +# usermod and groupadd alike — so make sure they end with a newline first. +ensure_db_trailing_newlines() { + local f + for f in /etc/passwd /etc/group /etc/shadow; do + [ -f "$f" ] || continue + # `tail -c 1` yields the last byte; command substitution strips a + # trailing newline, so non-empty output means the file is unterminated. + if [ -n "$(psudo tail -c 1 "$f")" ]; then + psudo sh -c "printf '\\n' >> '$f'" + warn "Added missing trailing newline to $f (required by chsh/usermod)" + fi + done +} + # ─── Main ───────────────────────────────────────────────────────────────────── main() { echo -e "${BOLD}${CYAN}" @@ -759,6 +780,7 @@ main() { detect_os ensure_sudo + ensure_db_trailing_newlines setup_passwordless_sudo set_hostname