Macの開発環境のメンテナンス用シェルスクリプト

開発マシンのメンテナンスは、やるべきだと分かっていながら後回しにしがちな作業の一つです。

Homebrewのアップデート、Dockerの肥大化したキャッシュ、積み上がったDerivedData——個別には些細でも、放置すれば確実にディスクとパフォーマンスを蝕みます。

本記事では、私が普段使用しているシェルスクリプトを紹介します。

設計方針

メンテナンススクリプトには独特の要件があります。
一部のコマンドが失敗しても、残りは実行を続けてほしい。set -e を使わない理由はここにあります。

set -uo pipefail

-u で未定義変数の参照を防ぎ、pipefail でパイプ中の失敗を検知します。
-e を外すことで、例えば brew doctor が警告を返しても後続の処理は止まりません。

構成

スクリプトは5つのセクションから成ります。

Homebrewの更新とクリーンアップ

brew update && brew upgrade && brew upgrade --cask --greedy
brew cleanup && brew autoremove
brew doctor

--cask --greedy は、自動更新機能を持つアプリ(Chrome、Firefox等)も含めて強制的にアップグレードします。
brew cleanupbrew autoremove で古いバージョンと不要な依存を除去し、brew doctor で環境の整合性を確認します。

Mac App Store

mas upgrade

mas を使い、App Store経由でインストールしたアプリもCLIから更新します。

Xcode関連

xcrun simctl delete unavailable

使われなくなったシミュレータランタイムを削除します。
これだけで数十GBの空きが生まれることもあります。

DerivedDataについては、Xcodeの起動状態を確認してから削除します。

if ! pgrep -q Xcode; then
  rm -rf ~/Library/Developer/Xcode/DerivedData/*
fi

ビルドキャッシュを消すだけなので、次回ビルド時に再生成されます。
起動中のXcodeを壊す心配を避けるためのガードです。

パッケージマネージャのキャッシュ整理

npm と pnpm のキャッシュを整理します。
いずれも command -v で存在確認してから実行するため、インストールしていない環境でもエラーにはなりません。

npm cache verify    # 整合性チェック。全削除はしない
pnpm store prune    # 未参照パッケージの削除

npm cache clean --force ではなく verify を選んでいるのは、壊れたエントリだけを除去し、有効なキャッシュは維持するためです。

Docker クリーンアップ

if command -v docker &>/dev/null && docker info &>/dev/null; then
  docker system prune -f --volumes --filter "until=168h"
  docker builder prune -f --filter "until=168h"
fi

docker info でデーモンの起動確認を行い、停止中なら何もしません。
--filter "until=168h" により、1週間以内に使用したリソースは保持されます。
直近の作業を壊さない安全策です。

キャッシュ容量の可視化

最後に ~/Library/Caches の上位10ディレクトリを表示します。

du -sh ~/Library/Caches/* 2>/dev/null | sort -rh | head -n 10

自動削除はしません。
アプリケーションキャッシュの削除判断は人間に委ねるべきです。

使い方

適当な場所に保存して実行権限を付与します。

chmod +x ~/scripts/maintenance.sh

手動で定期実行してもいいですし、launchd でスケジュールしても構いません。
ただし、Homebrewやmasは対話的な認証を求めることがあるため、完全な無人実行には向かない点に留意してください。

スクリプト全文

#!/bin/bash

# -------------------------------------------
# エラーハンドリング方針:
#   メンテナンススクリプトの性質上、一部失敗しても続行したいため
#   set -e は使わず、重要なコマンドのみ個別にハンドリングする。
#   未定義変数の参照とパイプ途中の失敗は検知する。
# -------------------------------------------
set -uo pipefail

# ===========================================
# Homebrewパッケージ更新とクリーンアップ
# ===========================================
brew update && brew upgrade && brew upgrade --cask --greedy
brew cleanup && brew autoremove
brew doctor

# ===========================================
# Mac App Storeアプリのアップデート
# ===========================================
mas upgrade

# ===========================================
# Xcode関連の不要ファイル削除
# ===========================================
xcrun simctl delete unavailable

# Xcodeが起動中でなければDerivedDataを削除
if ! pgrep -q Xcode; then
  rm -rf ~/Library/Developer/Xcode/DerivedData/*
else
  echo "⚠ Xcodeが起動中のためDerivedDataの削除をスキップしました"
fi

# ===========================================
# パッケージマネージャのキャッシュ/ストア整理
# ===========================================
# npm キャッシュの検証(整合性チェックのみ、全削除はしない)
if command -v npm &>/dev/null; then
  echo "--- npm cache verify ---"
  npm cache verify
fi

# pnpm ストアの最適化(未参照の依存パッケージを削除)
if command -v pnpm &>/dev/null; then
  echo "--- pnpm store prune ---"
  pnpm store prune
fi

# ===========================================
# Docker クリーンアップ
# ===========================================
if command -v docker &>/dev/null && docker info &>/dev/null 2>&1; then
  echo "--- Docker system prune ---"
  # 1週間以上前の未使用リソース + 未使用ボリュームを削除
  docker system prune -f --volumes --filter "until=168h"

  echo "--- Docker builder prune ---"
  docker builder prune -f --filter "until=168h"
fi

# ===========================================
# キャッシュ容量の確認(削除は手動判断)
# ===========================================
echo ""
echo "=== ~/Library/Caches 容量 Top 10 ==="
du -sh ~/Library/Caches/* 2>/dev/null | sort -rh | head -n 10
echo ""
echo "※ 不要なキャッシュがあれば手動で削除してください"
echo "  例: rm -rf ~/Library/Caches/<アプリ名>"

まとめ

このスクリプトが行うのは「安全に削除できるものだけを削除し、判断が必要なものは報告する」ことです。
定型作業を自動化するだけでも、ディスク容量とビルド環境の健全性は改善します。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください