Working remotely means I often need to maintain my Mac from afar. Over time, I've developed a script that makes this task much simpler when I'm logged in via SSH.
My bash script below helps me keep my Mac maintained and updated when I'm working remotely. It handles all the routine maintenance tasks I'd normally do if I were sitting at my desk.
xxxxxxxxxx
# Set strict error handling mode
set -euxo pipefail
# Dependency check for Homebrew
command -v brew >/dev/null 2>&1 || {
echo "Error: Homebrew is not installed. Please install Homebrew first."
exit 1
}
# Fix Homebrew permissions for Perl
sudo chown -R $(whoami) /opt/homebrew/Cellar/perl
sudo chmod -R u+rwX /opt/homebrew/Cellar/perl
# Perl wrapper for executing and colorizing commands
perl -MTerm::ANSIColor=':constants' -nlE '
# Skip empty lines and comments
next if m~^$|^\#~;
# Print current command in green
say q|> |, GREEN $_, RESET "";
# Execute the system command
system $_;
# Error handling
if ($? != 0)
{
# Print failure in red
warn q|> |, RED qq|Failure Detected: |, RESET qq|$!\n|;
}
# Final message after all commands
END
{
say q|> |, GREEN q|All Done! Bye bye :)|, RESET "";
}
' << EOF
# Homebrew package updates
brew update -q
brew upgrade -q
brew upgrade --cask -q
brew cleanup -q
brew autoremove -q
brew doctor -q
brew missing -q
# Mac App Store updates
mas upgrade -q
# System security updates
softwareupdate --install --recommended
# Command line tools
xcode-select --install 2>/dev/null || true
EOF
The script uses set -euxo pipefail
, which is a robust error handling combination in bash:
-e
stops execution if any command fails
-u
treats unset variables as errors
-x
prints each command before execution
pipefail
ensures pipeline errors aren't masked
This means I'll know exactly where things went wrong if there's an issue during remote maintenance.
The script verifies Homebrew's presence with:
xxxxxxxxxx
command -v brew >/dev/null 2>&1
This one-liner checks if the brew
command exists in the system's PATH, redirecting both standard output and errors to /dev/null
. If Homebrew isn't found, it exits with a helpful error message instead of failing mysteriously later.
Two critical permission commands ensure proper Homebrew operation:
xxxxxxxxxx
sudo chown -R $(whoami) /opt/homebrew/Cellar/perl
sudo chmod -R u+rwX /opt/homebrew/Cellar/perl
This grants the current user full ownership and read-write-execute permissions on the Perl installation directory. The capital X
in u+rwX
is intentional - it only adds execute permission to directories, not files.
The Perl wrapper uses Term::ANSIColor
for output formatting and implements a simple but effective command execution pipeline:
Skips empty lines and comments using regex m~^$|^\#~
Displays commands in green before execution
Shows errors in red if a command fails ($? != 0
)
Provides a clean exit message when everything's done
The script runs updates in a specific order:
Homebrew updates:
brew update
refreshes package lists
brew upgrade
updates all formulae
brew upgrade --cask
handles GUI applications
brew cleanup
removes old versions
brew doctor
checks system health
brew missing
finds broken dependencies
Mac App Store updates via mas upgrade -q
The -q
flag keeps output minimal and clean
System updates using softwareupdate --install --recommended
Only installs Apple's recommended updates
Avoids beta versions and optional updates
Developer tools with xcode-select --install
The 2>/dev/null || true
prevents errors if already installed
Ensures command line tools stay current
Note: Always review scripts before running them, especially when they use sudo
commands or modify system files. This script assumes you have both Homebrew and mas
(Mac App Store command line) installed.
This script has made remote management much easier for me. It's nothing fancy, but it gets the job done when I need to keep my Mac up to date from anywhere. I've been using it reliably for months now, tweaking it occasionally as my needs change.