把鼓包的2015款MacBook Pro改成7×24小时家用服务器,从装Ubuntu到锁充电阈值的完整踩坑指南

前言:一台鼓包的2015款MacBook Pro,二手800块没人要。本文记录如何给它装Ubuntu做成7×24小时家用服务器,解决Broadcom无线网卡驱动、合盖不休眠配置、电池鼓包充电阈值锁定等核心问题,附一键优化脚本,让旧笔记本焕发第二生命。

我把一台快鼓包的2015款MacBook Pro,改成了7×24小时的服务器

前两天翻抽屉,翻出来一台2015款的MacBook Pro。

屏幕边角发黄,合页松了,最要命的是触摸板按下去咯吱咯吱响,按不动。翻过来看底壳,微微隆起,像一块发酵过头的面团。

鼓包了。

这玩意儿在我抽屉里躺了快两年。当年花一万多买的,现在二手回收大概800块,还没人愿意收。扔了可惜,卖了吧就一顿饭钱,我也懒得折腾。

但那天我鬼使神德的把它拿出来,插上电源。

居然还能开机。

我就寻思,这么一台机器,i7的CPU,16G内存,256G固态,跑几个Docker容器、Nginx反代、Redis缓存,绰绰有余吧?比网上那些人花两三千攒的迷你主机强多了。

而且它自带电池,自带屏幕,自带键盘,自带网卡,自带Wi-Fi。

这不就是一个现成的服务器吗。

鼓包的电池,像发酵过头的面团
鼓包的电池,像发酵过头的面团

于是我就干了一件可能有点神经病的事,给它装了个Ubuntu,让它7×24小时跑起来。

说真的,整个过程比我想象的顺利,也比我想象的坑多。我把踩过的坑和最后跑通的方案,从头到尾跟你们聊一遍。

先说装系统这块。

准备一个8G以上的U盘,去Ubuntu官网下个22.04或者24.04的LTS镜像,用BalenaEtcher写进去。这一步没什么好说的,正常操作。

比较骚的事在后面。

U盘插上,MacBook完全关机,按电源键的同时长按Option键不放,等到启动项选择界面出来,选EFI Boot进去。

然后就是正常的安装流程,建议直接擦除整个磁盘,别留macOS双系统,省得后面折腾分区。装完重启。

到这里你以为搞定了对吧。

并没有。

重启进Ubuntu之后,Wi-Fi图标是个空的,搜不到任何网络。

我寻思了一下没寻思明白,查了才知道,2015款MBP用的是Broadcom的无线网卡,Ubuntu默认不带这个驱动,开源驱动又支持得稀烂。

怎么办呢,得先联网才能装驱动,但没Wi-Fi怎么联网。

死循环了属于是。

解决办法其实挺土的,拿一根数据线连手机,打开手机的网络共享,让手机给笔记本供网。就这么先凑合着连上,然后打开「软件和更新」,切到「附加驱动」那个标签页,勾选Broadcom的专有驱动,也就是bcmwl-kernel-source,点应用。

等它装完,Wi-Fi就活了。

没有Wi-Fi的日子,靠手机续命
没有Wi-Fi的日子,靠手机续命

我跟你说,这个坑看着小,但你要是不知道,能卡一下午。我当时就是,以为U盘镜像有问题,重新写了三遍,后来才发现根本不是镜像的事。

系统装好了,Wi-Fi也通了,接下来才是真正有意思的部分。

怎么让一台笔记本当服务器用。

你想想看,服务器最基本的要求是什么,7×24小时开着,合上盖子不能睡。

但Ubuntu默认你一合盖子就休眠了,网络全断,SSH连不上,容器全停。这哪是服务器,这就是个合盖就睡的笔记本= =

得改。

打开终端,敲一行命令,编辑systemd的电源管理配置文件。找到HandleLidSwitch这一行,把前面的注释号去掉,值改成ignore。顺手把HandleLidSwitchExternalPower和HandleLidSwitchDocked也一起改了,免得插着电源的时候行为不一样。

保存退出,重启一下systemd-logind服务。

然后合上盖子,拿另一台设备SSH连过去,ping一下IP,不断线。

成了。

这一步不难,但很关键。不改这个,你这台「服务器」就是个摆设。

说到这个,顺带提一句散热的事。

Mac的散热设计,很大一部分热量是从键盘缝隙往上散的。你把盖子完全合上,热量散不出去,高负载的时候CPU很快就降频了,性能掉得厉害。

所以我现在的做法是,屏幕打开大概30度,不完全合,让热空气能自然往上走。看到有人更狠,直接帐篷模式倒扣着放,散热效率更高,就是看着有点抽象。

反正我觉得,只要别完全合死,问题不大。

帐篷模式,散热拉满,颜值拉垮
帐篷模式,散热拉满,颜值拉垮

好,系统装了,合盖不休眠配了,散热也凑合了。

但是我一直心里有个疙瘩。

电池。

这台机器的电池已经鼓包了,虽然还能用,但我打算让它7×24小时插着电跑,这不就是给电池上刑吗。长期满电插电,电池鼓包只会更严重,严重了顶碎触摸板,再严重一点,起火都有可能。

我查了一下,网上有人说最一劳永逸的办法是拆开底盖,直接把电池排线拔了,纯靠电源适配器供电。这样最安全,但代价是断电的时候没有电池兜底,突然停电数据库可能就崩了。

我犹豫了。

后来我发现还有个更聪明的办法,不用拔电池,用软件把充电上限锁在50%。

这个思路是这样的,电池长期满电也就是100%的时候,电芯电压处于最高位,大概4.2V到4.35V,正极材料在这个电压下氧化性很强,会持续分解电解液里的有机溶剂,产生气体。鼓包就是这么来的。

但如果你把充电上限锁在50%,电芯电压会降到3.7V到3.85V这个区间,正极的极化程度低了很多,电解液分解的副反应速率会降低成百上千倍,几乎不怎么产气了。

还有一个点,满电的时候几乎所有锂离子都被塞进负极的石墨层里,负极体积膨胀10%以上,内部机械应力巨大。50%电量的时候,锂离子均匀分布在正负极之间,负极晶格处于最松弛最稳定的状态,不容易出微裂纹。

你想想看,笔记本当服务器跑,CPU和系统发热,机器内部长期40到60度。高温加上高电压,同时存在,这是电池鼓包最大的诱因。单独的高温对50%电量的电池损伤很小,但45度加上4.2V满电,产气速率是指数级飙升的。

锁50%,等于把最危险的那个「高电压」催化剂直接拔了。

而且电池充到50%之后就进入休眠,整机直接由外接电源供电,电池不参与循环了,相当于把电池放在了一个最佳的长期存放环境里。

我当时看到这套解释的时候,第一反应是,这尼玛也太合理了吧。。。

满电是4.2V,50%是3.7V,差0.5V,差了一个世界
满电是4.2V,50%是3.7V,差0.5V,差了一个世界

那怎么锁呢。

我试了两个方案。

第一个,检查内核有没有原生暴露充电控制的接口。在终端里跑一行,cat后面跟一串路径,/sys/class/power_supply/BAT0/charge_control_end_threshold。如果这个文件存在并且能读出数字,那你直接往里面写个50就行了,一行命令搞定。

但我的机器上,这个路径不存在。

那就上第二个方案,编译一个专门针对Intel Mac的SMC工具,叫macbook-charge-limit。这个工具通过修改SMC也就是系统管理控制器的BCLM寄存器来控制充电上限。

clone下来,make,make install,然后跑一行macbook-charge-limit 50,充电上限就锁在50%了。

为了重启之后还生效,我又写了个systemd的开机自启服务,让它每次开机自动跑一次这个命令。

插上电源,等电量到50%附近,查一下电池状态,显示pending-charge,也就是「不充电」,说明生效了。

那一刻我是真的觉得,太爽了。

一块随时可能鼓包炸裂的电池,被我用一行命令驯服了。

不过说实话,上面这些操作,合盖不休眠、充电阈值、开机自启,一条一条手动敲,挺烦的。我自己配的时候就敲错了两次,sed命令写反了一次,systemd服务文件少写了一行。

后来我干脆把这些操作全写进了一个交互式脚本。

跑一下,它会问你两个问题,要不要配合盖不休眠,要不要限制充电阈值。你输个y,输个数字,剩下的它全帮你搞定。备份配置文件、改logind.conf、编译SMC工具、写systemd服务、设开机自启,一条龙。

我把这个脚本放在文末了,需要的自己拿。

坦率的讲,这台2015款的MacBook Pro当服务器,不是没有短板。

没有原生网口,得靠USB 3.0或者雷电2转接千兆网卡,高并发吞吐的稳定性比原生网卡差一点。作为服务器,我建议能插网线就别用Wi-Fi,买一个芯片靠谱的转接头,稳定第一。

合盖散热差,这个前面说了,别完全合死就行。

电池鼓包,这个是最大的风险,但如果你像我一样锁了50%的充电上限,基本可以安心了。如果你实在不放心,拔电池排线是最彻底的方案,就是没了断电保护。

但话说回来,它的优点也确实香。

自带电池就是自带UPS,断电的时候有足够时间让脚本安全停机,保护数据库。这点比那些裸奔的迷你主机强太多了。

自带屏幕和键盘,调试底层网络、改GRUB、排查故障的时候,不用满世界找外接显示器。你用过就知道,这个便利程度,不是一般的高。

4代5代Intel加8到16G内存,跑Docker、Nginx、Redis、Uptime Kuma这些,轻轻松松,毫无压力。

待机功耗极低,放在角落7×24小时跑,基本无感。

一台二手回收价800块都没人要的机器,改完之后,是一台带UPS、带屏幕、带键盘、低功耗、能跑全套服务的家用服务器。

你敢信???

800块的废铁,跑着7x24小时的服务
800块的废铁,跑着7×24小时的服务

我有时候觉得,我们这个时代对「旧」这件事太苛刻了。

一台2015年的电脑,CPU比二十年前跑整个互联网的服务器还强,内存比当年NASA登月用的计算机多几万倍,就因为出了新款,它就成了「电子垃圾」。

我之前看过一个说法,说日本人修东西有一种工艺叫金缮,破碎的瓷器用金漆修补,不掩盖裂痕,反而让裂痕变成器物的一部分,变成一种新的美。

我觉得我干的事儿跟这个有点像。不是把旧东西修回原样,而是给它一个全新的身份。一台快鼓包的笔记本,变成了一台服务器。裂痕还在,鼓包还在,但它活了,而且活得挺好。

这玩意儿现在就蹲在我书桌底下的角落里,屏幕开30度,网线插着,风扇偶尔转一下,安安静静的跑着我的容器和监控。

有时候半夜我起来喝水,路过看一眼,屏幕上Uptime Kuma的绿色小灯一闪一闪的。

还挺安心的。

说真的,如果你手头也有一台吃灰的老MacBook,别急着卖废铁。给它续个命,说不定它能给你惊喜。

磨平一些信息差,有时候就是从翻抽屉开始的。


#!/bin/bash

# =============================================
# MacBook Pro (Ubuntu) 专属优化脚本
# 适用于在 MacBook Pro 上安装 Ubuntu Linux 的场景
# macOS 用户请勿运行此脚本,请使用 bclm 工具
# =============================================

set -euo pipefail

# 颜色定义
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
CYAN='\033[36m'
NC='\033[0m'

# 确保以 root 权限运行
if [ "$EUID" -ne 0 ]; then
  echo -e "${RED}错误:请使用 sudo 执行此脚本 (例如: sudo ./init-mbp.sh)${NC}"
  exit 1
fi

# 平台检查:仅支持 Linux
if [ "$(uname)" != "Linux" ]; then
  echo -e "${RED}错误:此脚本仅适用于 Linux (Ubuntu)。${NC}"
  echo -e "${RED}当前系统为 $(uname),请勿在此平台上运行。${NC}"
  echo -e "${YELLOW}macOS 用户请使用 bclm 工具:https://github.com/zackelia/bclm${NC}"
  exit 1
fi

echo -e "${CYAN}=========================================${NC}"
echo -e "${CYAN}   MacBook Pro (Ubuntu) 专属优化脚本   ${NC}"
echo -e "${CYAN}=========================================${NC}"

# ---------------------------------------------
# 1. 配置合盖不休眠
# ---------------------------------------------
echo -e "\n${YELLOW}[1/2] 配置合盖不休眠${NC}"
read -p "是否需要配置笔记本合盖不休眠?(y/n, 默认: y): " setup_lid
setup_lid=${setup_lid:-y}

if [[ "$setup_lid" =~ ^[Yy]$ ]]; then
    LOGIND_CONF="/etc/systemd/logind.conf"

    if [ ! -f "$LOGIND_CONF" ]; then
        echo -e "${RED}错误:未找到 $LOGIND_CONF,可能不是 systemd 系统。${NC}"
        exit 1
    fi

    # 备份原文件
    cp "$LOGIND_CONF" "${LOGIND_CONF}.bak"

    # 使用 sed 修改或取消注释相关配置
    sed -i 's/^#*HandleLidSwitch=.*/HandleLidSwitch=ignore/' "$LOGIND_CONF"
    sed -i 's/^#*HandleLidSwitchExternalPower=.*/HandleLidSwitchExternalPower=ignore/' "$LOGIND_CONF"
    sed -i 's/^#*HandleLidSwitchDocked=.*/HandleLidSwitchDocked=ignore/' "$LOGIND_CONF"

    echo -e "${GREEN}合盖不休眠配置已写入。正在重启 logind 服务...${NC}"
    systemctl restart systemd-logind
    echo -e "${GREEN}合盖不休眠配置完成。${NC}"
else
    echo "跳过合盖不休眠配置。"
fi

# ---------------------------------------------
# 2. 配置充电上限
# ---------------------------------------------
echo -e "\n${YELLOW}[2/2] 配置电池最大充电阈值${NC}"
read -p "是否需要限制最大充电阈值以保护电池?(y/n, 默认: y): " setup_bat
setup_bat=${setup_bat:-y}

if [[ "$setup_bat" =~ ^[Yy]$ ]]; then
    read -p "请输入限制阈值 (1-100, 默认: 50): " bat_limit
    bat_limit=${bat_limit:-50}

    # 校验输入范围
    if ! [[ "$bat_limit" =~ ^[0-9]+$ ]] || [ "$bat_limit" -lt 1 ] || [ "$bat_limit" -gt 100 ]; then
        echo -e "${RED}错误:阈值必须在 1-100 之间,当前输入: ${bat_limit}${NC}"
        exit 1
    fi

    SYSFS_PATH="/sys/class/power_supply/BAT0/charge_control_end_threshold"

    # 方案 A:尝试使用内核原生接口(内核 >= 5.4 且 applesmc 驱动支持)
    if [ -f "$SYSFS_PATH" ]; then
        echo "$bat_limit" > "$SYSFS_PATH"
        echo -e "${GREEN}已通过原生接口将充电阈值设置为 ${bat_limit}%。${NC}"

    # 方案 B:安装 applesmc-next DKMS 内核模块以暴露 sysfs 接口
    else
        echo -e "${YELLOW}未检测到原生接口,准备安装 applesmc-next DKMS 内核模块...${NC}"
        echo -e "${YELLOW}该模块通过 DKMS 补丁 applesmc 驱动,暴露 charge_control_end_threshold 接口。${NC}"

        APPLESMC_TAG="0.1.6"
        APPLESMC_REPO="https://github.com/c---/applesmc-next.git"
        APPLESMC_SRC="/usr/src/applesmc-next-${APPLESMC_TAG}"

        # 安装编译依赖
        echo -e "${YELLOW}安装依赖包 (dkms, kernel headers, git)...${NC}"
        apt-get update -qq
        apt-get install -y -qq dkms "linux-headers-$(uname -r)" git

        # 克隆 applesmc-next 源码
        echo -e "${YELLOW}克隆 applesmc-next v${APPLESMC_TAG}...${NC}"
        rm -rf "$APPLESMC_SRC"
        git clone --depth 1 --branch "$APPLESMC_TAG" "$APPLESMC_REPO" "$APPLESMC_SRC"

        # 通过 DKMS 构建并安装内核模块
        echo -e "${YELLOW}通过 DKMS 构建并安装内核模块...${NC}"
        dkms install "applesmc-next/${APPLESMC_TAG}"

        # 尝试重新加载模块使接口立即可用
        echo -e "${YELLOW}尝试重新加载 applesmc 模块...${NC}"
        modprobe -r applesmc 2>/dev/null || true
        modprobe applesmc 2>/dev/null || true

        # 检查接口是否已出现
        if [ -f "$SYSFS_PATH" ]; then
            echo "$bat_limit" > "$SYSFS_PATH"
            echo -e "${GREEN}已通过 applesmc-next 模块将充电阈值设置为 ${bat_limit}%。${NC}"
        else
            echo -e "${YELLOW}模块已安装,但接口尚未出现。${NC}"
            echo -e "${YELLOW}请重启系统后重新运行此脚本以应用充电阈值。${NC}"
            echo -e "${YELLOW}(BCLM 值存储在 SMC NVRAM 中,重启后仍会保留)${NC}"
            exit 0
        fi
    fi

    # 配置 systemd 服务保障开机自启(防止 SMC 重置后阈值丢失)
    SERVICE_FILE="/etc/systemd/system/battery-charge-limit.service"
    cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=Set MacBook Battery Charge Limit to ${bat_limit}%
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo ${bat_limit} > /sys/class/power_supply/BAT0/charge_control_end_threshold'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable battery-charge-limit.service
    echo -e "${GREEN}充电阈值已设置为 ${bat_limit}%,并已配置开机自启。${NC}"
else
    echo "跳过电池充电阈值配置。"
fi

echo -e "\n${CYAN}=========================================${NC}"
echo -e "${GREEN}全部优化操作执行完毕!${NC}"

/ 注意,本项目仅在 SyncMein 的500人小群分享。
/ 谢谢你看完了我的文章,我们下次再见吧。
/ 作者:明察
/ 投稿或爆料,请联系邮箱:mingcha@gqmg.com

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容