1. 项目概述:Air Surfer是什么?
最近在和一些做硬件开发的朋友聊天时,发现一个挺有意思的现象:大家手头或多或少都有一些闲置的旧手机、旧平板,或者是一些性能不那么强劲的开发板。这些设备食之无味,弃之可惜,堆在家里占地方。有没有一种方法,能让这些“电子垃圾”重新焕发生机,甚至变成我们工作流中的一个得力助手?这就是我今天想和大家分享的“Air Surfer”项目。
简单来说,Air Surfer是一个将闲置的移动设备(如旧手机、平板)或低功耗开发板,改造为轻量级、低功耗、可远程访问的Linux服务器的方案。它的核心目标不是追求极致的性能,而是极致的能效比和场景适配性。想象一下,你可以用一台插着充电宝的旧手机,7x24小时低功耗运行一个博客、一个文件同步服务、一个智能家居中枢,或者一个代码仓库的镜像站。它不占用额外的桌面空间,几乎没有噪音,功耗可能只有几瓦,却能完成许多自动化、后台服务的任务。
这个想法源于我自己的实际需求。我家里有几台淘汰下来的安卓手机,性能尚可,但电池已经不太行了。与其让它们彻底沉睡,不如利用其内置的电池(作为不间断电源)、完整的网络模块(Wi-Fi/4G)和传感器,打造一个“隐形”的服务器。经过一段时间的折腾和优化,我总结出了一套相对成熟、可复现的流程,涵盖了从系统选择、环境部署到服务配置和远程访问的全过程。无论你是想学习Linux服务部署的开发者,还是希望低成本搭建家庭自动化环境的极客,或者只是想给旧设备找个新出路,这个项目都值得一试。
2. 核心思路与方案选型:为什么是“移动设备+Linux”?
在决定启动Air Surfer项目时,我首先思考了几个核心问题:为什么要用移动设备?为什么不直接用树莓派之类的开发板?方案应该如何选型才能兼顾易用性和灵活性?
2.1 闲置移动设备的独特优势
选择旧手机或平板作为载体,主要基于以下几点考量:
- 极低的获取成本与沉没成本利用:对于大多数人来说,旧手机是“零成本”的硬件。它的价值已经在其作为通讯工具的生命周期中消耗完毕,我们是在挖掘其剩余价值。相比之下,购买一块新的树莓派或类似开发板,需要额外的资金投入。
- 高度集成的硬件模组:一部智能手机是一个高度集成的系统。它通常包含:
- 电池与电源管理:内置UPS(不间断电源),短时间停电也不怕服务中断。
- 多模网络:同时支持Wi-Fi和蜂窝移动网络(4G/5G),提供了网络冗余和灵活性。你甚至可以把它放在信号好的地方,通过移动网络提供接入。
- 丰富的传感器:GPS、光线传感器、加速度计等。这些可以为服务器增加环境感知能力,例如根据地理位置或光照自动调整服务。
- 输入输出:触摸屏可以作为临时的本地管理界面,摄像头可以用于简单的监控或OCR识别。
- 令人满意的性能功耗比:如今的旧手机,其SoC(系统级芯片)性能对于运行轻量级Linux发行版和容器化服务绰绰有余。更重要的是,移动芯片在设计之初就极度重视能效,其待机功耗可以控制得非常低,长期运行的电费成本几乎可以忽略不计。
2.2 核心方案:Termux + PRoot + Linux发行版
经过多种方案的对比测试(如LineageOS+Linux Deploy、直接刷入PostmarketOS等),我最终将Termux + PRoot的组合作为Air Surfer的基石。这个方案在灵活性、易用性和社区支持上达到了最佳平衡。
- Termux:这是一个无需root权限的强大终端模拟器和Linux环境。它在Android上提供了一个基本的Linux命令行环境,拥有自己的包管理器和软件仓库。它是我们所有操作的起点和基础容器。
- PRoot:你可以把它理解为一个“用户空间的文件系统虚拟化工具”。它允许你在Termux环境中,挂载并运行另一个完整的Linux发行版(如Ubuntu、Debian、Arch Linux)的文件系统,并模拟所需的系统调用。关键在于,这一切都不需要root权限。这大大降低了门槛和风险。
为什么选择这个组合而不是其他?
- 对比“Linux Deploy”等App:Linux Deploy同样优秀,但它通常需要设备已获取root权限,或者依赖复杂的chroot配置。对于新手和不想折腾root的用户,Termux+PRoot的方案更加友好和安全。
- 对比“直接刷入定制系统”:如PostmarketOS,它能为特定设备提供真正的Linux体验,但设备支持列表有限,刷机过程有风险,且可能失去原有的Android功能和OTA更新。Termux方案则是“非侵入式”的,与原有Android系统和平共处,随时可以卸载还原。
- 灵活性:基于PRoot,你可以随时切换不同的Linux发行版,就像更换容器一样简单。今天用Ubuntu跑Web服务,明天可以换Arch Linux玩最新的软件包。
这个方案的核心思路是:在Android这个“主机”系统上,通过Termux创建一个基础的Linux沙盒,再利用PRoot在这个沙盒里“嵌套”运行一个功能完整的Linux发行版。我们所有的服务都将部署在这个嵌套的发行版中。
3. 基础环境搭建:从零启动你的Air Surfer
理论说再多不如动手做一遍。下面我就详细拆解从一台闲置安卓手机开始,搭建Air Surfer基础Linux环境的全过程。请确保你的设备已经开启了“开发者选项”并允许了“USB调试”(后续传输文件方便),同时设备剩余存储空间最好大于8GB。
3.1 第一步:安装与配置Termux
- 获取Termux:由于某些应用商店的版本可能过旧或有问题,建议从F-Droid或GitHub Releases页面下载最新版本的Termux APK进行安装。安装完成后打开。
- 基础更新:首次打开Termux,它是一个非常精简的环境。我们需要先更新软件包列表并升级现有软件。在Termux中依次执行以下命令:
过程中会询问是否继续,输入pkg update pkg upgradey并按回车。 - 安装必要工具:为了后续操作顺畅,我们安装一些核心工具:
pkg install proot-distro wget curl git nano -yproot-distro:一个管理PRoot发行版的强大工具,让我们能一键安装各种Linux。wget,curl,git:网络下载和版本管理工具。nano:一个简单易用的命令行文本编辑器,适合新手。
注意:Termux默认的存储访问是受限的。如果你需要访问手机内部存储(如Downloads目录),需要运行
termux-setup-storage并授予权限。这会在家目录(~/storage)下创建指向手机存储的符号链接。
3.2 第二步:使用PRoot安装完整的Linux发行版
proot-distro工具内置了多个主流发行版。我们来安装一个最常用、社区支持最好的——Ubuntu。
列出可用发行版:
proot-distro list你会看到类似
alpine, archlinux, debian, ubuntu等列表。安装Ubuntu:
proot-distro install ubuntu这个命令会自动下载Ubuntu(通常是20.04或22.04 LTS版本)的文件系统镜像,并进行初始配置。下载速度取决于你的网络,镜像大小约100-200MB。
登录Ubuntu环境:
proot-distro login ubuntu执行后,你的命令行提示符会发生变化,例如从
$变成root@localhost:~#(注意,这里虽然是root用户,但权限仍被限制在PRoot容器内,不会影响真机系统)。恭喜,你现在已经进入了一个完整的Ubuntu系统!进行基础系统配置(在Ubuntu环境内操作):
- 更新系统:
apt update && apt upgrade -y - 安装基础软件:安装一些后续开发或服务部署常用的工具。
apt install vim sudo wget curl net-tools htop git build-essential -y - 创建普通用户(可选但推荐):长期使用root用户不安全也不方便。我们创建一个普通用户并赋予sudo权限。
之后可以执行adduser surfer # 根据提示设置密码和相关信息 usermod -aG sudo surfer # 将surfer用户加入sudo组su - surfer切换到这个用户。
- 更新系统:
至此,你的Air Surfer核心Linux环境已经就绪。你可以通过exit命令退出Ubuntu环境,回到Termux。任何时候想进入,再次执行proot-distro login ubuntu即可。
3.3 第三步:配置持久化与自启动(关键优化)
默认情况下,通过proot-distro login进入的环境是临时的。我们需要配置一个登录脚本,让每次进入Termux时自动启动并进入我们的Ubuntu环境,并且保持后台运行。
在Termux中创建启动脚本: 退出Ubuntu环境,回到Termux。编辑Termux的启动文件
~/.bashrc:nano ~/.bashrc在文件末尾添加以下内容:
# Auto start Ubuntu on Termux launch if [ -z "$PROOT_ENV_RUNNING" ]; then export PROOT_ENV_RUNNING=1 proot-distro login ubuntu -- bash -c "cd /home/surfer && exec bash" fi这段脚本的意思是:如果检测到我们不在PRoot环境内(通过环境变量判断),则自动登录ubuntu发行版,并切换到
/home/surfer目录,启动bash。按Ctrl+X,然后输入Y,回车保存。防止会话中断:Termux在手机锁屏或切换App后可能会被系统休眠,导致SSH连接断开。我们需要配置Termux的Wake Lock(唤醒锁)。
- 在Termux中安装相关工具:
pkg install termux-api(确保手机上也安装了Termux:API这个配套App)。 - 我们可以创建一个简单的服务脚本,在Ubuntu环境启动后,让Termux保持唤醒。方法更简单的是使用Termux的
termux-wake-lock和termux-wake-unlock命令。我们可以把加锁命令也放到.bashrc中,但更优雅的方式是使用Termux的~/.termux/boot/目录。 - 创建启动目录和脚本:
mkdir -p ~/.termux/boot nano ~/.termux/boot/start-ubuntu - 在
start-ubuntu文件中写入:#!/data/data/com.termux/files/usr/bin/bash termux-wake-lock # 这里可以添加其他你希望开机自启的命令 - 给脚本执行权限:
chmod +x ~/.termux/boot/start-ubuntu。 - 这样,当Termux服务启动时(例如设备重启后),它会自动执行这个脚本,获取唤醒锁。
- 在Termux中安装相关工具:
配置SSH服务以实现远程访问(在Ubuntu环境内操作): 这是将Air Surfer变成真正“服务器”的关键。我们安装并配置OpenSSH服务器。
sudo apt install openssh-server -y sudo systemctl enable ssh # 启用开机自启(在proot环境下,systemctl可能不工作,需要替代方案) sudo systemctl start ssh # 启动服务重要:在PRoot环境下,
systemctl通常无法直接管理宿主机的服务。我们需要手动启动SSH。一个可靠的方法是编写一个启动脚本。- 创建SSH启动脚本:
sudo nano /usr/local/bin/start_ssh.sh - 内容如下:
#!/bin/bash # 清理可能存在的旧进程 pkill -f "sshd" # 生成主机密钥(如果不存在) sudo ssh-keygen -A # 以非守护进程模式在前台启动sshd,便于观察日志 sudo /usr/sbin/sshd -D -o ListenAddress=0.0.0.0 -o PasswordAuthentication=yes & echo "SSH Server started." - 赋予执行权限:
sudo chmod +x /usr/local/bin/start_ssh.sh - 修改SSH配置以允许密码登录(仅限内网,公网强烈建议用密钥):
找到sudo nano /etc/ssh/sshd_config#PasswordAuthentication yes,去掉注释#。也可以找到PermitRootLogin,将其改为PermitRootLogin prohibit-password(推荐)或yes(临时,方便)。 - 最后,将启动SSH的命令加入到Ubuntu用户的
.bashrc或.profile中,这样每次登录Ubuntu环境就会自动启动SSH。编辑/home/surfer/.bashrc,在末尾加一行:/usr/local/bin/start_ssh.sh。
- 创建SSH启动脚本:
现在,重启Termux App,它应该会自动跳转到Ubuntu环境。在Ubuntu里,用ifconfig或ip addr命令查看容器的IP地址(通常是127.0.0.1的一个别名,或者10.0.0.0/8网段的一个地址)。但是,这个IP是容器内部的,外部无法直接访问。
4. 网络穿透与远程访问:让内网服务公网可达
让运行在手机PRoot环境里的服务能被外界访问,是Air Surfer项目从“玩具”变为“工具”的关键一步。由于设备通常位于家庭路由器后(NAT内网),我们需要解决两个问题:1. 从Termux容器到手机宿主机的网络连通;2. 从公网到家庭内网的穿透。
4.1 解决容器到宿主机的访问:Termux的SSH端口转发
Termux的PRoot环境是一个独立的网络命名空间。最简单的方法是将Ubuntu容器内的SSH端口(22)映射到Termux监听的一个本地端口,然后从手机宿主系统(或同一Wi-Fi下的其他设备)连接这个端口。
- 修改SSH启动脚本:我们不再让sshd监听所有接口,而是只监听本地环回(127.0.0.1),然后在Termux层面做端口转发。
- 修改之前的
/usr/local/bin/start_ssh.sh脚本,将sshd启动命令改为:
这里我们指定了监听sudo /usr/sbin/sshd -D -o ListenAddress=127.0.0.1 -o Port=8022 &127.0.0.1和端口8022(避免与宿主系统可能的SSH端口冲突)。
- 修改之前的
- 在Termux中设置端口转发:退出Ubuntu环境(或在另一个Termux标签页),在Termux(非Ubuntu)中执行:
termux-chroot # 这是一个轻量级的chroot,能提供更好的文件系统兼容性,非必须但推荐 socat TCP-LISTEN:2222,fork,reuseaddr TCP:127.0.0.1:8022 &socat是一个强大的网络工具。这条命令的意思是:在Termux环境中监听2222端口,当有连接到来时,将其转发到127.0.0.1:8022(即我们Ubuntu容器内的SSH服务)。 - 从宿主手机连接测试:在手机上安装一个SSH客户端App(如Termius、ConnectBot)。连接地址填写:
127.0.0.1,端口2222,使用你在Ubuntu里创建的用户名(如surfer)和密码。如果成功,说明容器到宿主机的通道打通了。
4.2 实现公网访问:内网穿透方案选型与配置
现在服务在手机本地可访问了,如何从公司或外网访问呢?这就需要内网穿透。这里我推荐两种适合移动端、资源占用低的方案:Cloudflared Tunnel和frp。
方案一:Cloudflared Tunnel(推荐,配置简单)Cloudflare Tunnel(以前叫Argo Tunnel)可以将你的本地服务安全地暴露到公网,而无需在路由器上设置端口转发,且流量经过Cloudflare的全球网络,有一定加速和安全防护作用。
在Ubuntu容器内安装Cloudflared:
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64 -O /usr/local/bin/cloudflared sudo chmod +x /usr/local/bin/cloudflared(注意:根据你手机CPU架构选择
arm或arm64,现代手机多是arm64)。认证并创建隧道:
cloudflared tunnel login这条命令会打开一个URL,让你登录Cloudflare账号并授权。授权后,会在
~/.cloudflared目录生成证书。cloudflared tunnel create air-surfer-tunnel创建一条名为
air-surfer-tunnel的隧道,记下返回的隧道ID。配置隧道:在
~/.cloudflared目录创建配置文件config.yml。tunnel: <你的隧道ID> credentials-file: /home/surfer/.cloudflared/<隧道ID>.json ingress: - hostname: ssh.yourdomain.com # 你自定义的子域名,需要在Cloudflare DNS中解析 service: http://localhost:2222 # 指向Termux转发的端口 - hostname: web.yourdomain.com # 可以暴露多个服务 service: http://localhost:8080 - service: http_status:404你需要有一个自己的域名,并在Cloudflare DNS中添加
ssh.yourdomain.com的CNAME记录,指向你的隧道ID对应的地址(格式如<隧道ID>.cfargotunnel.com)。运行隧道:
cloudflared tunnel run air-surfer-tunnel现在,访问
https://ssh.yourdomain.com,Cloudflare的网络就会将请求转发到你手机上的Termux服务,再经由socat转发到Ubuntu容器的SSH。对于SSH这种TCP服务,Cloudflared Tunnel需要额外配置,上述HTTP配置仅作示例。SSH的完整配置涉及cloudflared access命令,步骤稍复杂,但原理相通。
方案二:frp(灵活,功能强大)frp是一个高性能的反向代理应用,需要你有一台具有公网IP的VPS作为中转服务器。
在VPS(服务端)安装并配置frps:
wget https://github.com/fatedier/frp/releases/download/v0.51.3/frp_0.51.3_linux_amd64.tar.gz tar -zxvf frp_0.51.3_linux_amd64.tar.gz cd frp_0.51.3_linux_amd64编辑
frps.ini:[common] bind_port = 7000 # 服务端监听端口,用于与客户端通信 dashboard_port = 7500 # 控制台端口 dashboard_user = admin dashboard_pwd = your_strong_password token = your_secret_token_here # 客户端连接所需的令牌启动:
./frps -c ./frps.ini在Air Surfer(客户端,即Ubuntu容器内)安装并配置frpc:
wget https://github.com/fatedier/frp/releases/download/v0.51.3/frp_0.51.3_linux_arm64.tar.gz tar -zxvf frp_0.51.3_linux_arm64.tar.gz cd frp_0.51.3_linux_arm64编辑
frpc.ini:[common] server_addr = your_vps_ip # 你的VPS公网IP server_port = 7000 token = your_secret_token_here # 必须与服务端一致 [air-surfer-ssh] # 定义一个SSH代理 type = tcp local_ip = 127.0.0.1 local_port = 8022 # Ubuntu容器内SSH端口 remote_port = 60022 # 在VPS上暴露的端口启动:
./frpc -c ./frpc.ini连接:现在,你可以通过
ssh -p 60022 surfer@your_vps_ip来连接你的Air Surfer了。所有流量经由VPS中转。
实操心得:对于长期运行的服务,务必配置为系统服务或使用
systemd/supervisor管理。在Ubuntu容器内,可以用crontab -e添加@reboot任务来启动frpc或cloudflared。更稳妥的方法是编写systemd service文件,尽管在PRoot下有些限制,但通过proot-distro的--shared-systemd参数或手动调用systemd-nspawn可以部分实现。
5. 服务部署实战:将Air Surfer变为实用工具
环境搭好了,通道打通了,接下来就是赋予它灵魂——部署实际服务。考虑到手机的资源(内存、CPU、存储)和功耗限制,我们应优先选择轻量级、高效率的服务。
5.1 部署轻量级Web服务器与博客
方案:Caddy + HugoCaddy是一个用Go写的Web服务器,自动HTTPS是它的招牌功能,配置极其简单。Hugo是静态网站生成器,速度快,资源占用低,非常适合在Air Surfer上运行。
在Ubuntu容器内安装Caddy:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy安装Hugo:
sudo apt install hugo或者从GitHub下载最新版。
创建并配置Hugo站点:
hugo new site myblog cd myblog git init git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke echo "theme = 'ananke'" >> config.toml hugo new posts/first-post.md # 编辑 content/posts/first-post.md hugo -D # 生成静态网站到 `public/` 目录配置Caddy:编辑Caddy的配置文件
/etc/caddy/Caddyfile。# 假设你的穿透域名是 web.yourdomain.com web.yourdomain.com { root * /home/surfer/myblog/public file_server encode gzip }重启Caddy:
sudo systemctl restart caddy(或caddy reload --config /etc/caddy/Caddyfile)。
现在,访问你的域名,就能看到博客了。你可以将Hugo的生成命令加入cron定时任务,实现自动更新。
5.2 部署代码仓库与CI/CD辅助(Gitea)
对于个人开发者,在Air Surfer上跑一个轻量级的Git服务如Gitea,可以管理私有项目,甚至配合Webhook实现简单的CI/CD。
下载并安装Gitea:
wget -O gitea https://dl.gitea.com/gitea/1.20.5/gitea-1.20.5-linux-arm64 chmod +x gitea sudo mv gitea /usr/local/bin/创建系统用户和目录:
sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git sudo mkdir -p /var/lib/gitea/{custom,data,log} sudo chown -R git:git /var/lib/gitea/ sudo chmod -R 750 /var/lib/gitea/配置Gitea为系统服务:创建文件
/etc/systemd/system/gitea.service。[Unit] Description=Gitea (Git with a cup of tea) After=syslog.target After=network.target [Service] RestartSec=2s Type=simple User=git Group=git WorkingDirectory=/var/lib/gitea ExecStart=/usr/local/bin/gitea web --config /var/lib/gitea/app.ini Restart=always Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea [Install] WantedBy=multi-user.target初始配置:首次运行
sudo systemctl start gitea后,通过浏览器访问http://<你的设备IP>:3000进行安装配置。数据库可以选择SQLite3以简化部署。配置完成后,你就可以拥有一个私人的Git服务器了。
5.3 部署家庭自动化中枢(Home Assistant)
如果你有智能家居设备,Air Surfer可以成为一个完美的、低功耗的Home Assistant服务器。
使用Docker安装(推荐):首先在Ubuntu容器内安装Docker。
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER # 退出重新登录使组生效运行Home Assistant容器:
docker run -d \ --name homeassistant \ --privileged \ --restart=unless-stopped \ -v /home/surfer/ha-config:/config \ -v /run/dbus:/run/dbus:ro \ --network=host \ ghcr.io/home-assistant/home-assistant:stable注意:
--privileged和--network=host是为了让Home Assistant能更好地访问本地网络和设备。在PRoot环境下运行Docker可能会遇到内核模块问题,如果失败,可以尝试安装Docker的rootless模式,或者直接使用Home Assistant Core的Python虚拟环境安装方式,虽然复杂但兼容性更好。访问:安装完成后,访问
http://<设备IP>:8123即可进行初始设置。
6. 性能调优、监控与长期运行维护
让一个移动设备7x24小时稳定运行服务,需要一些额外的调优和监控手段。
6.1 资源限制与优化
限制服务资源:使用Docker时,可以通过
--memory,--cpus参数限制容器的资源使用。对于非容器进程,可以使用cpulimit和ulimit命令进行限制,防止某个服务耗尽所有资源导致系统卡死。# 示例:使用cpulimit限制某个进程的CPU使用率不超过50% sudo apt install cpulimit cpulimit -l 50 -p <进程PID>优化存储:手机存储的读写寿命和性能是瓶颈。尽量避免频繁写入日志。对于Docker,可以将容器的日志驱动改为
json-file并设置大小和数量限制,或者直接禁用某些容器的日志。# 在docker run时限制日志 docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...禁用不必要的服务:在Ubuntu容器内,关闭你不需要的系统服务,如
apt-daily-upgrade.timer,unattended-upgrades.service等。sudo systemctl disable --now apt-daily-upgrade.timer sudo systemctl disable --now unattended-upgrades.service
6.2 系统监控与告警
基础监控:安装
htop,glances或netdata进行实时监控。Netdata虽然功能强大,但资源消耗也大。对于Air Surfer,glances是一个不错的折中选择。sudo apt install glances glances -w # 以Web模式启动,可以通过浏览器访问日志集中管理:使用
journalctl查看系统日志。可以配置logrotate来管理应用日志,防止撑满磁盘。简易存活监控:可以写一个简单的Shell脚本,定时检查关键服务(如SSH, Caddy, frpc)的端口是否在监听,如果失败则尝试重启并发送通知(例如通过Telegram Bot或邮件)。
#!/bin/bash SERVICES=(":22" ":80" ":443") for svc in "${SERVICES[@]}"; do if ! ss -tuln | grep -q "$svc"; then echo "Service on $svc is down! Attempting restart..." | tee -a /var/log/service_watchdog.log # 这里添加重启对应服务的命令,例如 sudo systemctl restart ssh # 发送告警通知(需自行集成通知API) fi done然后将这个脚本加入cron定时任务,每5分钟执行一次。
6.3 电源管理与可靠性提升
这是移动设备作为服务器最大的挑战。
- 防止系统休眠:除了之前提到的Termux Wake Lock,还需要进入手机的系统设置->电池优化(或类似选项),找到Termux和可能用到的相关App(如用于穿透的客户端),将其设置为“不优化”或“允许后台活动”。
- 使用充电器而非电脑USB:确保设备连接的是稳定的电源适配器,而不是电脑的USB口,后者供电可能不稳定且在电脑休眠时断电。
- 注意电池健康:长期满电充电可能加速电池老化。一些手机有“充电优化”或“保护电池”模式,可以开启。或者使用一些自动化工具(如Tasker),在电量达到80%时停止充电,降到50%时再开始充,但这需要root权限和更复杂的配置。
- 应对意外重启:确保所有关键服务都配置了开机自启。对于Termux,可以安装
Termux:Boot这个App,它能在设备启动后自动运行Termux并执行~/.termux/boot/目录下的脚本。
7. 常见问题与故障排查实录
在折腾Air Surfer的过程中,我踩过不少坑。这里把一些典型问题和解决方法记录下来,希望能帮你节省时间。
7.1 环境与依赖问题
问题1:proot-distro login失败,提示“Failed to create the session directory”或权限错误。
- 原因:Termux的存储权限或文件系统损坏。
- 解决:
- 运行
termux-setup-storage重新获取存储权限。 - 尝试清理PRoot缓存:
proot-distro clear-cache,然后重新安装发行版。 - 最彻底的方法是备份
$PREFIX/var/lib/proot-distro目录(如果有重要数据),然后卸载并重装Termux。
- 运行
问题2:在Ubuntu容器内无法安装软件包,提示“Unable to locate package”或网络错误。
- 原因:容器内的DNS解析或网络配置有问题。
- 解决:
- 检查
/etc/resolv.conf文件,确保里面有有效的DNS服务器,如nameserver 8.8.8.8。 - 在PRoot登录时尝试使用
--shared-network参数(如果proot-distro支持)来共享宿主机的网络。 - 手动修改Ubuntu的APT源为国内镜像(如阿里云、清华源),加速下载。
- 检查
7.2 网络与服务问题
问题3:SSH连接超时或拒绝连接。
- 排查步骤:
- 确认服务是否在运行:在Ubuntu容器内执行
sudo netstat -tlnp | grep :22,看sshd进程是否在监听。 - 确认防火墙:Ubuntu容器内可能默认有
ufw防火墙。检查状态:sudo ufw status。如果是inactive,则不是它的问题。如果active,需要放行22端口:sudo ufw allow 22。 - 确认端口转发:在Termux(非Ubuntu)中执行
netstat -tlnp | grep :2222,看socat是否在监听。 - 逐层测试:
- 在Ubuntu容器内:
ssh localhost -p 8022看能否连接自己。 - 在Termux中:
ssh 127.0.0.1 -p 2222看能否通过socat转发连接。 - 在手机宿主系统:用SSH客户端App连接
127.0.0.1:2222。
- 在Ubuntu容器内:
- 检查SSH配置:确保
/etc/ssh/sshd_config中ListenAddress和PasswordAuthentication设置正确。
- 确认服务是否在运行:在Ubuntu容器内执行
问题4:内网穿透工具(frpc/cloudflared)频繁断开重连。
- 原因:移动网络不稳定、设备休眠、或穿透工具本身配置/版本问题。
- 解决:
- 增加重试机制:在frpc配置中增加
login_fail_exit = false和max_retry_interval = 7200等参数。 - 使用进程守护:用
systemd或supervisor管理穿透客户端,配置自动重启。在PRoot下,可以写一个简单的监控脚本,用cron定时检查进程是否存在。 - 尝试TCP保活:在frpc配置的
[common]部分添加tcp_mux = true和heartbeat_interval = 30、heartbeat_timeout = 90。 - 检查设备电源策略:确保Termux和穿透工具App不在系统的电池优化白名单中。
- 增加重试机制:在frpc配置中增加
7.3 性能与稳定性问题
问题5:服务运行一段时间后,设备变得非常卡顿,甚至无响应。
- 原因:内存泄漏、存储空间不足、或某个进程占用CPU过高。
- 排查与解决:
- 快速诊断:在Termux中运行
htop或glances,查看CPU、内存、Swap的使用情况。按F6排序进程,找出资源消耗大户。 - 检查存储:运行
df -h,看根分区是否已满。特别是/var/log目录,日志文件可能快速增长。 - 限制资源:对确认有问题的服务进程,使用
cpulimit或nice限制其CPU优先级。 - 增加Swap:如果内存不足,可以在手机存储上创建一个Swap文件(注意,这可能加速存储芯片磨损)。
sudo fallocate -l 2G /swapfile # 创建2G文件 sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 要永久生效,需将 `/swapfile none swap sw 0 0` 添加到 `/etc/fstab`
- 快速诊断:在Termux中运行
问题6:设备重启后,所有服务都需要手动启动。
- 解决:这是自启动配置不完整导致的。你需要一个完整的自启动链条:
- Termux自启:依赖
Termux:BootApp 或系统设置允许Termux后台运行。 - Termux内脚本自启:确保
~/.termux/boot/下的脚本正确无误,且获取了唤醒锁 (termux-wake-lock)。 - Ubuntu环境自启:确保Termux的
~/.bashrc能自动登录PRoot环境。 - Ubuntu内服务自启:将需要启动的服务(如sshd, frpc, caddy, docker容器)的启动命令,添加到Ubuntu用户的
~/.profile或~/.bashrc末尾(对于简单服务),或者配置为systemd服务(更规范)。
- Termux自启:依赖
这个过程就像搭积木,每一环都要扣紧。最可靠的测试方法是:手动重启手机,然后观察几分钟,看服务是否都能自动恢复。如果不行,就根据日志(logcat查看Android系统日志,Termux和Ubuntu内查看各自的日志)逐环排查。