首先我有 apple care,买了一共四年(第四年快到期了),一共大概花了 3000 块钱不到,21 款的老 m1 pro 了,用了 2 年电池从 100 掉到 83,再用了 2 年 83 掉到 79,真的老吃苦了,我前几天短暂的电池飘红,结果重启了又恢复了气死了,直接开脚本嗯刷掉到 79 了
今天去售后,我和他说除了电池,屏幕上在白色背景下有黑斑(实际上是涂层脱落严重显得有一块很淡的黑斑),本来以为是天才吧不给换的,没想到很好说话,还让我寄修了,电脑继续用
所以现在是换电池,键盘,外壳(下半部分都是统一换的),屏幕,基本上只留大脑,又变成新电脑了
没花一分钱
黑斑如图(无视发绿的部分)

大家要的脚本
前置条件

免责声明:这个完全看运气的,不一定能掉的,我的循环都 1050 了也该跌了
脚本是cc写的,请稍微审阅下,不保证 macos26 是否可用
#!/bin/bash
# ============================================================================
# Battery Cycler Installer — MacBook 电池循环刷坏工具
# ============================================================================
# 用途: 通过自动循环深放 + 满充 + CPU 满载,加速 MacBook 电池健康度下降
# 目的: 在 AC+ 保修期内让 Apple 系统健康度跌破 80%,免费换电池
# for 佬友们
# 不保证最终有效,只保证快速电池重放循环,如有硬件损害请自负责任
# ============================================================================
#
# ⚠️ 使用风险
# - 长期满载 stress-ng 会让机器噪音大、发热
# - 极深放电可能触发 hibernate(机器假死)
# - 对电池是"加速损耗",目的就是把它弄低健康度
# - 效果不保证(苹果黑箱算法疑似长期锁死 80% )
# - 不建议对公司配发的电脑使用
#
# ============================================================================
set -u
# ---------- 前置检查 ----------
echo "╔════════════════════════════════════════╗"
echo "║ Battery Cycler Installer ║"
echo "╚════════════════════════════════════════╝"
echo ""
# Apple Silicon 检查
if [ "$(uname -m)" != "arm64" ]; then
echo "❌ 此工具仅支持 Apple Silicon Mac (M1/M2/M3)"
echo " 当前架构: $(uname -m)"
exit 1
fi
# macOS 版本提醒
OSVER=$(sw_vers -productVersion)
echo "✓ macOS $OSVER"
echo "✓ 芯片: $(sysctl -n machdep.cpu.brand_string)"
# 自动算 stress 核数(总核数 - 1,留一个给系统)
TOTAL_CORES=$(sysctl -n hw.ncpu)
STRESS_CORES=$((TOTAL_CORES - 1))
echo "✓ CPU 核数: $TOTAL_CORES (将使用 $STRESS_CORES 核跑 stress-ng)"
echo ""
# ---------- 依赖检查 ----------
echo "▶ 检查依赖..."
MISSING=()
if ! command -v brew >/dev/null 2>&1; then
echo "❌ 没装 Homebrew,先装:https://brew.sh"
exit 1
fi
if ! command -v battery >/dev/null 2>&1; then
MISSING+=("battery")
fi
if ! command -v stress-ng >/dev/null 2>&1; then
MISSING+=("stress-ng")
fi
if [ ${#MISSING[@]} -gt 0 ]; then
echo "⚠️ 缺少依赖: ${MISSING[*]}"
echo ""
read -p "自动用 brew 装吗?(y/n): " ans
if [ "$ans" = "y" ]; then
for dep in "${MISSING[@]}"; do
if [ "$dep" = "battery" ]; then
brew install --cask battery
else
brew install "$dep"
fi
done
else
echo "❌ 请手动装完依赖再运行本脚本"
exit 1
fi
fi
echo "✓ 依赖齐全"
echo ""
# ---------- battery CLI 授权检查 ----------
echo "▶ 检查 battery CLI 授权..."
if ! battery status >/dev/null 2>&1; then
echo "⚠️ battery CLI 尚未授权"
echo ""
echo " 请执行以下两步:"
echo " 1. 打开 /Applications/battery.app 一次,按提示输密码装 helper"
echo " 2. 在 battery app Preferences 里勾选 '✅ Allow force-discharging'"
echo ""
read -p "做完后按 Enter 继续..."
fi
if ! battery status >/dev/null 2>&1; then
echo "❌ battery CLI 仍不可用,无法继续"
exit 1
fi
echo "✓ battery CLI OK"
echo ""
# ---------- 写脚本 ----------
USER_BIN="$HOME/bin"
mkdir -p "$USER_BIN"
SCRIPT="$USER_BIN/battery-cycler.sh"
STOP_SCRIPT="$USER_BIN/battery-cycler-stop.sh"
BSTAT="$USER_BIN/bstat"
BPWR="$USER_BIN/bpwr"
PLIST_LABEL="com.$(whoami).battery-cycler"
PLIST="$HOME/Library/LaunchAgents/${PLIST_LABEL}.plist"
echo "▶ 写入脚本到 $USER_BIN/"
cat > "$SCRIPT" <<EOF
#!/bin/bash
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
set -u
LOW=1
HIGH=100
STRESS_CPU="$STRESS_CORES"
LOG="\$HOME/battery-cycler.log"
STRESS_LOG="\$HOME/battery-cycler.stress.log"
STRESS_PATTERN="stress-ng --cpu \${STRESS_CPU}"
log() { echo "[\$(date '+%F %T')] \$*" >> "\$LOG"; }
pct() { pmset -g batt | grep -Eo '[0-9]+%' | head -1 | tr -d '%'; }
log_health() {
local apple_pct cycles nominal raw design gauge_pct raw_pct
apple_pct=\$(system_profiler SPPowerDataType 2>/dev/null | awk '/Maximum Capacity/{gsub("%","",\$3); print \$3; exit}')
cycles=\$(system_profiler SPPowerDataType 2>/dev/null | awk '/Cycle Count/{print \$3; exit}')
nominal=\$(ioreg -rc AppleSmartBattery 2>/dev/null | awk '/^ +"NominalChargeCapacity" = [0-9]+\$/{print \$NF; exit}')
raw=\$(ioreg -rc AppleSmartBattery 2>/dev/null | awk '/^ +"AppleRawMaxCapacity" = [0-9]+\$/{print \$NF; exit}')
design=\$(ioreg -rc AppleSmartBattery 2>/dev/null | awk '/^ +"DesignCapacity" = [0-9]+\$/{print \$NF; exit}')
gauge_pct=\$(awk -v n="\$nominal" -v d="\$design" 'BEGIN{printf "%.2f", n/d*100}')
raw_pct=\$(awk -v r="\$raw" -v d="\$design" 'BEGIN{printf "%.2f", r/d*100}')
log "HEALTH | Apple: \${apple_pct}% | Raw: \${raw_pct}% (\${raw} mAh) | Gauge: \${gauge_pct}% (\${nominal}/\${design} mAh) | Cycles: \${cycles}"
}
start_stress() {
if ! pgrep -f "\$STRESS_PATTERN" >/dev/null; then
stress-ng --cpu "\$STRESS_CPU" --timeout 0 --temp-path /tmp >> "\$STRESS_LOG" 2>&1 &
log "stress-ng 启动 PID=\$!"
fi
}
stop_stress() {
if pgrep -f "\$STRESS_PATTERN" >/dev/null; then
pkill -f "\$STRESS_PATTERN" 2>/dev/null
log "stress-ng 已停止"
fi
}
cleanup() {
log "退出:恢复充电,杀 stress-ng"
battery charging on >/dev/null 2>&1
battery adapter on >/dev/null 2>&1
pkill -f "\$STRESS_PATTERN" 2>/dev/null
exit 0
}
trap cleanup INT TERM EXIT
cd "\$HOME"
log "========== 启动 =========="
n=0
while true; do
n=\$((n+1))
log "=== 第 \$n 轮 ==="
log_health
log "→ 放电阶段(adapter off + stress-ng 满载 \${STRESS_CPU} 核,目标 ≤\${LOW}%)"
battery adapter off >/dev/null 2>&1
start_stress
stress_stopped_emergency=0
while true; do
p=\$(pct)
[ -z "\$p" ] && { sleep 5; continue; }
if [ "\$p" -le 2 ] && [ "\$stress_stopped_emergency" -eq 0 ]; then
log "⚠️ 电量 ≤2%,紧急停 stress-ng 降负载"
stop_stress
stress_stopped_emergency=1
fi
[ "\$stress_stopped_emergency" -eq 0 ] && start_stress
log "当前 \${p}% [放电]"
[ "\$p" -le "\$LOW" ] && break
if [ "\$p" -le 3 ]; then sleep 1
elif [ "\$p" -le 8 ]; then sleep 10
elif [ "\$p" -le 15 ]; then sleep 20
else sleep 40
fi
done
log "→ 充电阶段(暂停 stress-ng,目标 ≥\${HIGH}%)"
stop_stress
battery adapter on >/dev/null 2>&1
battery charging on >/dev/null 2>&1
while true; do
p=\$(pct)
[ -z "\$p" ] && { sleep 30; continue; }
log "当前 \${p}% [充电]"
[ "\$p" -ge "\$HIGH" ] && break
sleep 120
done
log "→ 第 \$n 轮完成"
log_health
done
EOF
chmod +x "$SCRIPT"
echo " ✓ $SCRIPT"
# 停止脚本
cat > "$STOP_SCRIPT" <<EOF
#!/bin/bash
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
PLIST="\$HOME/Library/LaunchAgents/${PLIST_LABEL}.plist"
echo "→ 停止 LaunchAgent..."
launchctl unload "\$PLIST" 2>/dev/null && echo " ✓ unloaded" || echo " (未加载)"
echo "→ 杀 stress-ng..."
pkill -f 'stress-ng --cpu' 2>/dev/null && echo " ✓ killed" || echo " (未运行)"
echo "→ 杀 cycler 脚本..."
pkill -f battery-cycler.sh 2>/dev/null && echo " ✓ killed" || echo " (未运行)"
echo "→ 恢复充电..."
battery adapter on >/dev/null 2>&1 && echo " ✓ adapter on"
battery charging on >/dev/null 2>&1 && echo " ✓ charging on"
if [ "\${1:-}" = "--purge" ]; then
echo "→ 彻底清理..."
rm -f "\$PLIST" \$HOME/bin/battery-cycler.sh \$HOME/bin/battery-cycler-stop.sh
rm -f \$HOME/battery-cycler.log \$HOME/battery-cycler.{stress,out,err}.log
echo " ✓ 全部删除"
fi
echo ""
echo "✓ 完成"
EOF
chmod +x "$STOP_SCRIPT"
echo " ✓ $STOP_SCRIPT"
# bstat 工具
cat > "$BSTAT" <<'EOF'
#!/bin/bash
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
echo "╔══════════════════════════════╗"
echo "║ 电池状态看板 ║"
echo "╚══════════════════════════════╝"
pmset -g batt | tail -1
echo ""
system_profiler SPPowerDataType | grep -E "State of Charge|Cycle Count|Condition|Maximum Capacity" | head -8
echo ""
VOLT=$(ioreg -rc AppleSmartBattery | awk '/^ +"Voltage" = /{print $NF; exit}')
AMP=$(( $(ioreg -rc AppleSmartBattery | awk '/^ +"InstantAmperage" = /{print $NF; exit}') ))
TEMP=$(ioreg -rc AppleSmartBattery | awk '/^ +"Temperature" = /{print $NF; exit}')
NOMINAL=$(ioreg -rc AppleSmartBattery | awk '/^ +"NominalChargeCapacity" = [0-9]+$/{print $NF; exit}')
RAW=$(ioreg -rc AppleSmartBattery | awk '/^ +"AppleRawMaxCapacity" = [0-9]+$/{print $NF; exit}')
DESIGN=$(ioreg -rc AppleSmartBattery | awk '/^ +"DesignCapacity" = [0-9]+$/{print $NF; exit}')
CYCLE=$(ioreg -rc AppleSmartBattery | awk '/^ +"CycleCount" = [0-9]+$/{print $NF; exit}')
PHYS=$(awk -v n="$NOMINAL" -v d="$DESIGN" 'BEGIN{printf "%.2f", n/d*100}')
RAW_PCT=$(awk -v r="$RAW" -v d="$DESIGN" 'BEGIN{printf "%.2f", r/d*100}')
TEMP_C=$(awk -v t="$TEMP" 'BEGIN{printf "%.1f", t/100}')
printf " 电压: %.3f V\n" "$(awk -v v="$VOLT" 'BEGIN{printf "%.3f", v/1000}')"
printf " 电流: %d mA\n" "$AMP"
printf " 温度: %s°C\n" "$TEMP_C"
printf " gauge 估算: %s mAh (%s%%)\n" "$NOMINAL" "$PHYS"
printf " 苹果 Raw: %s mAh (%s%%) ⭐\n" "$RAW" "$RAW_PCT"
printf " 设计容量: %s mAh\n" "$DESIGN"
printf " 循环次数: %s\n" "$CYCLE"
EOF
chmod +x "$BSTAT"
echo " ✓ $BSTAT"
# bpwr 工具
cat > "$BPWR" <<'EOF'
#!/bin/bash
AMP_RAW=$(ioreg -rc AppleSmartBattery | awk '/^ +"InstantAmperage" = /{print $NF; exit}')
VOLT=$(ioreg -rc AppleSmartBattery | awk '/^ +"Voltage" = /{print $NF; exit}')
AMP=$((AMP_RAW))
awk -v amp="$AMP" -v volt="$VOLT" 'BEGIN{
p = amp * volt / 1000000
s = (p < 0) ? "充电" : (p > 0 ? "放电" : "稳态")
if (p < 0) p = -p
printf "%s | %d mA | %d mV | %.2f W\n", s, amp, volt, p
}'
EOF
chmod +x "$BPWR"
echo " ✓ $BPWR"
# ---------- 写 plist ----------
echo ""
echo "▶ 写入 LaunchAgent: $PLIST"
cat > "$PLIST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${PLIST_LABEL}</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/caffeinate</string>
<string>-ims</string>
<string>${SCRIPT}</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>ThrottleInterval</key>
<integer>30</integer>
<key>StandardOutPath</key>
<string>${HOME}/battery-cycler.out.log</string>
<key>StandardErrorPath</key>
<string>${HOME}/battery-cycler.err.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>
EOF
echo " ✓ plist 已写入"
# ---------- PATH 检查 ----------
echo ""
if ! echo "$PATH" | grep -q "$HOME/bin"; then
echo "▶ ~/bin 不在 PATH,追加到 ~/.zshrc"
echo '' >> ~/.zshrc
echo '# Battery Cycler 工具' >> ~/.zshrc
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
echo " ✓ 已追加,重开终端或跑 source ~/.zshrc 生效"
else
echo "✓ ~/bin 已在 PATH"
fi
# ---------- 完成提示 ----------
echo ""
echo "╔════════════════════════════════════════╗"
echo "║ ✓ 安装完成 ║"
echo "╚════════════════════════════════════════╝"
echo ""
echo "【启动循环】(立即开始刷电池,机器会一直满载跑)"
echo " launchctl load $PLIST"
echo ""
echo "【停止】"
echo " battery-cycler-stop.sh # 暂停"
echo " battery-cycler-stop.sh --purge # 彻底卸载(删脚本+日志)"
echo ""
echo "【查看状态】"
echo " bstat # 电池状态看板"
echo " bpwr # 实时功率"
echo " tail -f ~/battery-cycler.log # 实时日志"
echo " grep HEALTH ~/battery-cycler.log # 所有 HEALTH 记录"
echo ""
echo " - 一旦跳了或者 Condition 变成 Service Recommended → 立刻去天才吧换电池"
echo ""
echo "⚠️ 警告:"
echo " 1. 机器会持续满载 + 风扇狂转(stress-ng ${STRESS_CORES} 核)"
echo " 2. 电池真的会被伤坏(这是目的)"
echo " 3. 循环深度到 1%,有可能触发空电假死,得按电源键启动"
echo " 4. 不建议在公司机 / 家人共用机跑"
echo " 5. 效果不保证 —— 苹果黑箱健康度算法有可能短期刷不动"
echo ""
echo "祝电池早日跌下80%! 🔋💥"
我只在 macos 15 上测试过,macos26 不一定可用
有疑问请询问 ai,也是 ai 写的,也可以让 ai 来审查
拿到文件后在他自己的 Mac 上执行:
bash ~/Downloads/battery-cycler-installer.sh (改成实际路径)
可能需要 chmod +x 授权下
安装完成后朋友要主动跑一条命令才开始:
launchctl load ~/Library/LaunchAgents/com.$USER.battery-cycler.plist