1
0

ssh-agent.sh 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #!/bin/bash
  2. # SSH agent forwarding status.
  3. #
  4. # Sourced by both bash and zsh (see .bashrc / .zshrc), so keep this POSIX-ish.
  5. #
  6. # `ssh-agent-status` prints a one-line summary and can be run by hand any time.
  7. # It also runs automatically when you land on an interactive SSH login, so a
  8. # missing forward is obvious immediately rather than at the first git push.
  9. #
  10. # A missing forward is dim rather than red: it is usually deliberate, and the
  11. # line is there to tell you which mode you are in, not to report a fault.
  12. #
  13. # A missing forward is almost always a client-side omission: the machine you
  14. # connected FROM needs `ForwardAgent yes` for this host in its ~/.ssh/config.
  15. # Fix it there, not here.
  16. ssh-agent-status() {
  17. local reset='\033[0m' dim='\033[2m' grey='\033[90m'
  18. local green='\033[0;32m' yellow='\033[0;33m' red='\033[0;31m'
  19. # Not `status`: that is a read-only builtin in zsh and assigning to it
  20. # aborts the function on every zsh login.
  21. local keys rc count
  22. if [ -z "$SSH_AUTH_SOCK" ]; then
  23. printf "${dim}${grey}- ssh agent not forwarded (SSH_AUTH_SOCK is unset)${reset}\n"
  24. return 1
  25. fi
  26. # Keep the assignment and the status check separate: `local keys=$(...)`
  27. # would return the status of `local`, not of ssh-add.
  28. keys=$(ssh-add -l 2>/dev/null)
  29. rc=$?
  30. case $rc in
  31. 0)
  32. # Counted in-shell rather than piping through wc and tr. This runs on
  33. # every SSH login, and those are two processes spawned to count at most a
  34. # handful of lines.
  35. count=0
  36. while IFS= read -r _; do count=$((count + 1)); done <<EOF
  37. $keys
  38. EOF
  39. printf "${green}+ ssh agent forwarded${reset} ${dim}(%s keys)${reset}\n" "$count"
  40. ;;
  41. 1)
  42. printf "${yellow}! ssh agent forwarded but holds no keys${reset}\n"
  43. return 1
  44. ;;
  45. *)
  46. printf "${red}x ssh agent socket is dead${reset} ${dim}(%s)${reset}\n" "$SSH_AUTH_SOCK"
  47. return 1
  48. ;;
  49. esac
  50. }
  51. # Report on interactive SSH logins only. .zshrc sources .rc.d for
  52. # non-interactive shells too, so without this guard the banner would be written
  53. # into the stream used by scp, rsync and git-over-ssh and corrupt them.
  54. #
  55. # Local shells never reach the function at all, so this costs a local terminal
  56. # nothing: $- and SSH_CONNECTION are both shell builtins.
  57. case $- in
  58. *i*)
  59. if [ -n "$SSH_CONNECTION" ] && [ -t 1 ]; then
  60. ssh-agent-status || true
  61. fi
  62. ;;
  63. esac