Here's a short shell script to quickly update a Mac OS-based computer.
- Run the script, like this:
bash <(curl -s https://gist.github.com/nicholasadamou/ffaf49f0e763f979ebeb86df2a8b215e/raw/d1ca21eeb6b06ae57e3aaeeb76dbbc40123c4378/update.sh)
| #!/bin/bash | |
| ask_for_sudo() { | |
| # Ask for the administrator password upfront. | |
| sudo -v &> /dev/null | |
| # Update existing `sudo` time stamp | |
| # until this script has finished. | |
| # | |
| # https://gist.github.com/cowboy/3118588 | |
| while true; do | |
| sudo -n true | |
| sleep 60 | |
| kill -0 "$$" || exit | |
| done &> /dev/null & | |
| } | |
| show_spinner() { | |
| local -r FRAMES='/-\|' | |
| # shellcheck disable=SC2034 | |
| local -r NUMBER_OR_FRAMES=${#FRAMES} | |
| local -r CMDS="$2" | |
| local -r MSG="$3" | |
| local -r PID="$1" | |
| local i=0 | |
| local frameText="" | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Note: In order for the Travis CI site to display | |
| # things correctly, it needs special treatment, hence, | |
| # the "is Travis CI?" checks. | |
| if [ "$TRAVIS" != "true" ]; then | |
| # Provide more space so that the text hopefully | |
| # doesn't reach the bottom line of the terminal window. | |
| # | |
| # This is a workaround for escape sequences not tracking | |
| # the buffer position (accounting for scrolling). | |
| # | |
| # See also: https://unix.stackexchange.com/a/278888 | |
| printf "\n\n\n" | |
| tput cuu 3 | |
| tput sc | |
| fi | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Display spinner while the commands are being executed. | |
| while kill -0 "$PID" &>/dev/null; do | |
| frameText=" [${FRAMES:i++%NUMBER_OR_FRAMES:1}] $MSG" | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Print frame text. | |
| if [ "$TRAVIS" != "true" ]; then | |
| printf "%s\n" "$frameText" | |
| else | |
| printf "%s" "$frameText" | |
| fi | |
| sleep 0.2 | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Clear frame text. | |
| if [ "$TRAVIS" != "true" ]; then | |
| tput rc | |
| else | |
| printf "\r" | |
| fi | |
| done | |
| } | |
| execute() { | |
| local -r CMDS="$1" | |
| local -r MSG="$2" | |
| local -r TMP_FILE="$(mktemp /tmp/XXXXX)" | |
| local exitCode=0 | |
| local cmdsPID="" | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # If the current process is ended, | |
| # also end all its subprocesses. | |
| set_trap "EXIT" "kill_all_subprocesses" | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Execute commands in background | |
| eval "$CMDS" \ | |
| &> /dev/null \ | |
| 2> "$TMP_FILE" & | |
| cmdsPID=$! | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Show a spinner if the commands | |
| # require more time to complete. | |
| show_spinner "$cmdsPID" "$CMDS" "$MSG" | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Wait for the commands to no longer be executing | |
| # in the background, and then get their exit code. | |
| wait "$cmdsPID" &> /dev/null | |
| exitCode=$? | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| # Print output based on what happened. | |
| print_result $exitCode "$MSG" | |
| if [ $exitCode -ne 0 ]; then | |
| print_error_stream < "$TMP_FILE" | |
| fi | |
| rm -rf "$TMP_FILE" | |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
| return $exitCode | |
| } | |
| set_trap() { | |
| trap -p "$1" | grep "$2" &> /dev/null \ | |
| || trap '$2' "$1" | |
| } | |
| print_error_stream() { | |
| while read -r line; do | |
| print_error "↳ ERROR: $line" | |
| done | |
| } | |
| print_error() { | |
| print_in_red " [✖] $1 $2\n" | |
| } | |
| print_success() { | |
| print_in_green " [✔] $1\n" | |
| } | |
| print_in_green() { | |
| print_in_color "$1" 2 | |
| } | |
| print_in_purple() { | |
| print_in_color "$1" 5 | |
| } | |
| print_in_red() { | |
| print_in_color "$1" 1 | |
| } | |
| print_in_color() { | |
| printf "%b" \ | |
| "$(tput setaf "$2" 2> /dev/null)" \ | |
| "$1" \ | |
| "$(tput sgr0 2> /dev/null)" | |
| } | |
| print_result() { | |
| if [ "$1" -eq 0 ]; then | |
| print_success "$2" | |
| else | |
| print_error "$2" | |
| fi | |
| return "$1" | |
| } | |
| update() { | |
| # Get macOS Software Updates, and update installed Ruby gems, Homebrew, npm, and their installed packages | |
| execute \ | |
| "sudo softwareupdate -i -a && \ | |
| brew update && brew upgrade && brew cleanup && \ | |
| sudo npm install npm -g && sudo npm update -g && \ | |
| sudo gem update --system && sudo gem update && sudo gem cleanup" \ | |
| "System (update)" | |
| } | |
| main() { | |
| print_in_purple "\n Updating System\n\n" | |
| update | |
| printf "\n" | |
| } | |
| main |