news 2026/9/9 11:10:11

手机变身服务器:Termux+Ubuntu搭建LNMP动态网站实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手机变身服务器:Termux+Ubuntu搭建LNMP动态网站实战

1. 为什么绕一大圈装Ubuntu,而不是直接用Termux搭网站

先说结论:直接在Termux里装Nginx、PHP、MySQL完全可行,但真正把动态网站跑起来之后,你会碰到一堆"能用但别扭"的问题。我最初也试过在Termux原生环境里直接干,前半小时一切顺利,越往后越难受。

核心问题在于Termux的包管理是基于Android的bionic libc编译的,和桌面Linux生态的glibc环境有差异。你装一个php扩展,可能需要连编带调好几个小时,有些包在Termux的仓库里根本没有,只能自己找第三方编译源。而动态网站的本质是"Web服务器 + 脚本解释器 + 数据库 + 业务代码"四个环节的联动,任何一个环节缺包、版本不对、扩展装不上,整个链路就断掉。我曾经在Termux原生环境里为了装一个php的pdo_mysql扩展,折腾了快一天,最后发现官方仓库里那个php包默认没编进去,得自己重新编译整个PHP——这性价比低到让人想摔手机。

所以我在第二次尝试时换了思路:先用Termux的proot-distro工具装一个完整的Ubuntu用户空间镜像,然后在Ubuntu里干所有事。Ubuntu的apt仓库里什么都有,php、mysql、nginx、redis、composer,一条命令全解决,依赖关系也自动处理得干净利落。你得到的其实是一个"运行在手机上的、接近完整版Linux的容器",动态网站开发中遇到的各种库、扩展、工具链,在Ubuntu里几乎都能无缝搞定。

很多人一听到"容器"就以为需要root权限,其实完全不需要。Termux的proot-distro用的是proot技术,它通过用户态的ptrace系统调用翻译,把Ubuntu的rootfs模拟到Termux进程里,整个过程不碰Android内核,不需要root,也不影响你手机的保修和安全。代价是性能上会比原生执行差一些,但跑个个人网站、学习环境、演示项目完全够用。

这篇文章的主要读者,我设想是这三类人:一是在手机上学习Linux和Web开发、但手边没有电脑的学生;二是想把闲置安卓手机变成一台随身演示服务器、给客户或朋友展示网站的开发者;三是纯粹对"在手机上跑Linux"这件事好奇、想深度折腾一下的玩家。不管你是哪一类,按这篇文章的步骤走一遍,最后你会在手机浏览器里看到自己写的动态网页,而且局域网内的其他设备也能访问。

2. 环境准备:proot-distro安装Ubuntu和国内源配置

2.1 Termux基础设置

Termux可以从F-Droid渠道下载,第三方渠道的版本可能不维护,这点不需要多说。装好后先做两件事:更新包索引和升级已有包,然后安装proot-distro。

pkg update && pkg upgrade -y pkg install proot-distro -y

这个proot-distro是Termux官方维护的多发行版安装工具,支持Ubuntu、Debian、Kali、Arch等主流发行版。它会把对应发行版的rootfs解压到Termux的数据目录里,然后用proot启动一个用户态模拟环境。

有个细节值得注意:proot-distro在安装Ubuntu时,会先下载bootstrap镜像,这个下载源在国外的服务器上,速度可能很慢。你可以通过设置镜像环境变量来解决。我习惯把下载源指向国内同步节点,速度能快上十倍:

export PROOT_DISTRO_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/ proot-distro install ubuntu

如果这个变量不起效果,可以在proot-distro的脚本目录里查找它实际使用的下载地址,手动下载rootfs镜像后放到缓存目录再重装。具体路径不同版本稍微有差异,你可以用find $PREFIX -name "*.tar.*"找到它缓存的镜像文件。我自己在装的时候,就因为默认源太慢卡了五分钟,换成镜像源后两分钟搞定。

安装完成后,登录进入Ubuntu环境:

proot-distro login ubuntu

此时你会看到shell提示符变了,说明你已经进入Ubuntu环境。可以执行cat /etc/os-release确认版本信息,再执行uname -a看看内核信息——注意,内核还是Android的,但用户空间的工具链、编译器、库文件全都是Ubuntu的了。这就是proot的原理:它不替换内核,只模拟用户空间。

2.2 Ubuntu换源和基础工具安装

进到Ubuntu环境后,第一件事是换源。默认的archive.ubuntu.com源在国内访问很慢,我直接把它替换成阿里云或清华的镜像地址。这里我以Ubuntu 22.04 LTS为例:

sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list apt update && apt upgrade -y

如果你装的是Ubuntu 24.04,镜像配置文件可能不在/etc/apt/sources.list,而在/etc/apt/sources.list.d/ubuntu.sources,格式是deb822,操作方式类似,把URIs那一行替换成镜像地址就行。

基础工具我建议一次性装齐,后面省得反复进apt装东西。到这一步,你已经有了一个完整的Ubuntu命令行环境。

3. 在Ubuntu里装好LNMP,网站就能先跑起来

3.1 Nginx安装与站点配置

动态网站我选择Nginx + PHP-FPM + MariaDB这套组合,也就是常说的LNMP。为什么不选Apache?一是Nginx的并发性能更好,二是配置简洁,没有Apache那套复杂的.htaccess和模块系统,在手机上本来就资源有限,Nginx更轻量。

apt install nginx -y

装完之后先别急着换配置,服务默认是没启动的。因为proot环境没有systemd,service nginx start这类命令会报错,需要用nginx命令直接前台或后台启动:

nginx

启动后验证一下进程是否正常:

ps aux | grep nginx

如果你看到master进程和worker进程都在,说明Nginx已经跑起来了。在Termux里打开浏览器访问http://127.0.0.1/,应该能看到Nginx的默认欢迎页。如果你看不到,多半是端口被占用或者Nginx的pid文件路径有问题,可以看/var/log/nginx/error.log排查。

接下来修改站点配置。默认站点配置文件在/etc/nginx/sites-available/default,我的建议是直接编辑这个文件,把根目录指到你的项目目录,并配置好PHP的转发。下面是我惯用的一个最小可用配置:

server { listen 80 default_server; root /var/www/html; index index.php index.html; server_name _; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php-fpm.sock; } }

重点在location ~ \.php$这块。动态网站的请求流程是:浏览器请求.php文件 -> Nginx收到请求后,把它转给PHP-FPM解释器去执行 -> PHP执行完把HTML结果返回给Nginx -> Nginx再回给浏览器。Nginx本身不认识PHP代码,它只是负责转发的那个"快递员"。

配好后重载Nginx配置:

nginx -t && nginx -s reload

3.2 PHP-FPM的安装与对接细节

Nginx装好了,但此时所有PHP文件都只会被当成纯文本下载,不会执行,因为还没装PHP解释器。这一步是很多人卡住的地方,我特意说明一下。

Ubuntu 22.04默认的PHP版本是8.1,执行:

apt install php-fpm php-mysql php-curl php-mbstring php-xml php-zip -y

这几个扩展是动态网站比较常用的:php-mysql负责连数据库,php-mbstring处理多字节字符串,php-xml是很多框架的依赖项。如果你后面打算跑WordPress或Laravel,这些基本是标配。

PHP-FPM装好之后,要确认它的监听方式。我配置里写的unix:/run/php/php-fpm.sock,Ubuntu 22.04的php-fpm默认就是通过Unix socket监听的,路径通常为/run/php/php8.1-fpm.sock。如果你的系统里版本号不同,把配置里的socket路径改成实际路径即可。可以用以下命令查看实际socket文件位置:

ls -l /run/php/php*-fpm.sock

如果清单里找不到socket文件,说明php-fpm还没启动,执行:

php-fpm8.1 -D

-D参数让php-fpm以daemon方式后台运行。启动后再执行ps aux | grep php确认进程在。

到这里,你可以在/var/www/html目录下创建一个测试文件,看看PHP是否已经和Nginx打通了:

echo "<?php phpinfo();" > /var/www/html/info.php

然后浏览器访问http://127.0.0.1/info.php。如果能看到PHP信息页,说明Nginx和PHP-FPM的socket对接成功,这也是动态网站能跑起来的第一道门槛。我见过不少人卡在这一步,症状是浏览器访问PHP文件直接变成下载,或者返回502 Bad Gateway——几乎所有情况都是php-fpm没启动或socket路径不匹配。

3.3 MariaDB数据库安装与初始化

没有数据库的"动态网站"是不完整的,表单提交、用户登录、文章列表这些功能都需要数据库支撑。MariaDB是MySQL的开源分支,兼容性非常好,在Ubuntu里可以直接通过apt安装:

apt install mariadb-server -y

同样,没有systemd,需要手动初始化数据库:

mariadb-install-db --user=mysql --datadir=/var/lib/mysql mysqld_safe --skip-syslog &

启动后,通过MariaDB自带的脚本做安全初始化,设置root密码、删除匿名用户、禁止root远程登录:

mariadb-secure-installation

按提示操作即可。注意一点,proot环境下的默认字符集可能不是UTF-8,中文内容的网站建议在MariaDB配置里显式加上默认字符集。在/etc/mysql/mariadb.conf.d/50-server.cnf[mysqld]段加上:

character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci

utf8mb4不仅支持中文,还覆盖表情符号,没有理由不用它。改完配置后重启MariaDB才能生效。

到这里,LNMP环境三件套已经齐了。你可以先做个最基础的动态网页验证一下:在/var/www/html里创建一个test.php,里面写一条SQL查询,如果能正常返回数据,整个链路就是通的。

4. 让数据活起来:PHP + MariaDB实现第一个动态页面

4.1 建库建表与插入测试数据

环境搭好了,接下来我带你做一个真正意义上的动态网站Demo——一个简单的留言板。它包含最基本的动态网站要素:前端HTML表单、后端PHP处理、数据库存储和读取。

先进入MariaDB创建数据库和表:

mariadb -u root -p

输入刚才设置的密码后,执行SQL:

CREATE DATABASE IF NOT EXISTS guestbook DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE guestbook; CREATE TABLE messages ( id INT AUTO_INCREMENT PRIMARY KEY, nickname VARCHAR(50) NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO messages (nickname, content) VALUES ('小明', '第一条动态网站数据,纪念一下!'); INSERT INTO messages (nickname, content) VALUES ('小红', '在手机上写代码的感觉真不错。');

这里用InnoDB引擎是因为它支持事务和外键,生产环境的基本要求。如果你的应用以后要扩展,InnoDB是更稳妥的选择。

4.2 用PHP写一个能读能写的页面

数据库有了数据,现在写两个PHP文件:一个用于展示留言列表并支持提交新留言,另一个用于处理表单数据。我把这两个逻辑直接写在同一个文件里,方便说明,也方便你直接复制测试。

/var/www/html/guestbook.php文件中创建:

<?php $servername = "127.0.0.1"; $username = "root"; $password = "你的数据库密码"; $dbname = "guestbook"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("数据库连接失败: " . $conn->connect_error); } $conn->set_charset("utf8mb4"); if ($_SERVER["REQUEST_METHOD"] === "POST") { $nickname = htmlspecialchars(trim($_POST["nickname"]), ENT_QUOTES); $content = htmlspecialchars(trim($_POST["content"]), ENT_QUOTES); if ($nickname !== "" && $content !== "") { $stmt = $conn->prepare("INSERT INTO messages (nickname, content) VALUES (?, ?)"); $stmt->bind_param("ss", $nickname, $content); $stmt->execute(); $stmt->close(); header("Location: guestbook.php"); exit; } } ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>手机里的动态留言板</title> </head> <body> <h1>手机里的动态留言板</h1> <form method="POST"> <input type="text" name="nickname" placeholder="你的昵称" required> <textarea name="content" placeholder="想说的话..." required></textarea> <button type="submit">提交留言</button> </form> <?php $result = $conn->query("SELECT nickname, content, created_at FROM messages ORDER BY created_at DESC"); if ($result->num_rows > 0) { while ($row = $result->fetch_assoc()) { echo "<div>"; echo "<strong>" . $row["nickname"] . "</strong> "; echo "<span>" . $row["created_at"] . "</span>"; echo "<p>" . nl2br($row["content"]) . "</p>"; echo "</div>"; } } else { echo "<p>还没有留言,来抢沙发吧!</p>"; } $conn->close(); ?> </body> </html>

这个页面包含了两层"动态":一是发布留言时把数据写入数据库,二是刷新页面时从数据库把记录读出来渲染成HTML。所有内容不是在代码里写死的,而是由数据库的内容决定——这正是"动态网站"和"静态网页"的本质区别。你可以对比一下:静态网页的HTML文件内容是什么,用户在浏览器里看到的就是什么,每次访问都一样;而这个留言板页面,每提交一条新留言,下一轮刷新时内容就会变。

这里有两个我特别想强调的安全习惯,你在任何动态网站项目里都用得上。

第一个是htmlspecialchars()。用户输入的内容不可信,如果不做HTML转义,用户提交的<script>alert(1)</script>会被浏览器直接当成脚本执行,这就是最基本的XSS攻击。用htmlspecialchars把尖括号转义掉,就安全了。

第二个是SQL预处理语句。我用了preparebind_param,而不是直接把变量拼进SQL里。直接拼接的话,如果用户提交'; DROP TABLE messages;--这段内容,SQL执行时可能会变成多条命令,把整张表删掉,这就是SQL注入。预处理语句能确保输入永远只被当作数据处理,而不是SQL语法的一部分。

4.3 从手机浏览器里看到第一个动态页面

在Termux的Ubuntu环境里,访问http://127.0.0.1/guestbook.php,你就能看到这个留言板了。提交一条留言,页面刷新后显示出来。这个瞬间还挺有成就感的——你的手机现在真的成为了一台能提供动态服务的服务器。

如果你之前一直在电脑上开发网站,可能对"把服务器装进手机"这件事没太多感觉。但当你真正在手机的Termux命令行里敲下一串SQL插入数据,再在浏览器里看到内容出现在页面上时,你会发现整个流程和操作一台云服务器其实没什么差别。这也是Termux + Ubuntu这套方案最有价值的地方:它把服务器开发的学习门槛拉到了最低,一部几百块钱的安卓手机就能当学习机用。

5. 把手机上的网站开放给局域网设备访问

动态网站在手机本机跑通了,下一步自然是让局域网里的电脑、平板、其他手机也能访问。这一步其实比很多人想象中简单,因为Nginx默认就监听在0.0.0.0:80上(也就是所有网络接口),只要你手机和别的设备在同一个局域网,理论上访问手机IP就能打开网页。

5.1 查看手机IP并处理端口权限

先查看手机在局域网里的IP地址。Termux里执行:

ifconfig

或者:

ip -4 addr show

一般来说,WiFi连接的设备IP是192.168.x.x或10.x.x.x这样的C类地址。记下wlan0接口的inet地址,例如192.168.1.8。另一台设备打开浏览器访问http://192.168.1.8/guestbook.php,如果顺利能打开,说明Nginx监听正常。

但这里有一个常见的坑:Android的8.0以上系统对普通应用直接监听80端口有严格限制吗?严格说是有的,Android认为80和443是保留端口,普通应用如果没有权限,绑定这些端口会失败。但你使用Termux时,它本身不限制普通端口的监听,80端口可能没问题,也可能在个别机型上失败。如果你发现浏览器访问超时,排查思路是:先确认Nginx确实在监听(netstat -tlnp看80端口状态),如果监听正常但访问也失败,试试把Nginx的监听端口改成8080。

改端口只需要修改Nginx配置文件里的listen 80;listen 8080;,然后重载:

nginx -s reload

访问地址变成http://192.168.1.8:8080/guestbook.php。我建议从一开始就直接用8080端口,能避开不少Android系统的坑。如果手机用的是无线调试、热点分享等方式与其他设备连接,访问IP会不太一样,热点分享的场景下,被连接设备分配的IP一般是192.168.43.x段,视手机型号而定,查一下连接设备的IP再访问就好。

5.2 确保Termux在后台不被杀掉

能访问了,但这里又有个新的致命问题:一旦你把App切到后台、锁屏几分钟,再回来访问网站可能就挂了。那是因为Android系统为了省电,把Termux进程杀掉了,Nginx、PHP-FPM、MariaDB全跟着阵亡。

解决办法是我踩了不少坑才总结出来的。首先,在Termux里执行一次:

termux-wake-lock

这个命令会让Termux申请一个唤醒锁,让手机在锁屏状态下CPU仍然保持运行,进程不会被系统休眠掉。注意,每次Termux进程重启后都需要重新执行一次,建议把它写进启动脚本里。

其次,还需要在系统层面把Termux设置为"不受电池优化限制"。在Android的「设置 -> 应用 -> Termux -> 电池」里,选择允许后台活动并关闭电池优化。不同手机厂商定义这个功能的名称不一样,有的叫"省电策略",有的叫"锁优化",可能藏得比较深,但总的原则是让Termux在后台保持活跃。我最早在MIUI系统上折腾时,光找这个设置就花了好一会儿,设置完之后进程不再动不动就消失了。

还有一点非常实用:给Termux应用加锁。在多任务界面把Termux的卡片下拉锁住,这能防止部分系统的一键清理功能把它清掉。

这样设置之后,你的手机只要开机、联网、Termux在运行,网站就始终是活的。我测试过一整夜锁屏,第二天早上访问,网站依然正常响应。

5.3 如果要跨网络访问:低成本的内网穿透思路

如果想让手机上的网站不止在局域网内访问,而是外面任意一个网络都能访问,就涉及到内网穿透的问题。这里我不展开太多细节,只提供一个思路和验证过的工具方案。

我们可以使用frp、cloudflared这类隧道工具,把手机本地端口映射到一台有公网IP的服务器,或者通过cloudflared的隧道服务获取一个公网HTTPS域名。比如cloudflared可以在你的手机Ubuntu里执行:

cloudflared tunnel --url http://127.0.0.1:8080

它会输出一个随机域名,任何人通过这个域名都能访问到你的站点,同时自带HTTPS加密。这个方法适合临时演示,域名每次运行会变,长期使用要绑定自己的域名。

frp则适合你有一台云服务器的情况,配置一个TCP隧道把服务器的公网端口转发到手机的8080端口。优点是稳定可控,缺点是要求你有云服务器。

关于这一部分,我要特别提醒:内网穿透工具只用于你自己的合法服务器和网站,别拿来做任何其他用途。在使用隧道服务时,也要遵守服务商的使用政策和当地法律法规。搭建个人网站、做学习演示完全没有问题。

6. 连续跑两周以后,我踩过的坑和优化建议

环境能跑通不等于稳定。我把这套Termux + Ubuntu的动态网站环境连续跑了差不多两周,期间暴露了不少问题。这一节我把印象最深的几个坑和对应的解决方案完整写出来。

6.1 端口10000和文件权限的困惑

第一次启动Nginx时,我在Termux里先创建了一个/var/www/html目录并尝试写入测试文件,结果直接返回Permission denied。一开始我以为自己权限不足,反复检查用户身份,确认是在root用户下操作还是没权限。

后来才发现,在proot环境里,文件系统的实际写入受限于Android应用的数据目录。具体来说,proot虽然向你呈现了一个完整的Ubuntu文件系统,但底层的rootfs文件存放在/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu这样的目录下,所有文件操作最终还是要经过Android的文件权限检查。如果你试图操作rootfs之外的路径(比如/sdcard),可能会遇到权限问题。

解决办法是:网站根目录文件放在rootfs内部(比如/var/www/html),不要试图直接跨到/sdcard去读写;如果需要和手机存储交换文件,可以在Termux里执行termux-setup-storage授权存储访问,然后通过/sdcard路径在Termux原生环境里操作,再拷贝进Ubuntu。

另外,如果/var/www/html目录里文件太多导致写入慢,可以考虑用htop看下内存占用——手机版Ubuntu环境默认没有配置swap,内存不足时PHP-FPM可能会频繁重启报503。

6.2 PHP-FPM频繁闪退的排查与修复

跑了大概三天之后,我发现网站偶尔会在访问时直接返回502 Bad Gateway。这个状态码的意思是Nginx把请求转发给了PHP-FPM,但PHP-FPM没有响应或者崩溃了。

我首先看了PHP-FPM的错误日志:

tail -f /var/log/php8.1-fpm.log

日志里大批量出现WARNING: [pool www] server reached pm.max_children settings (5), consider raising it

原因很明确:手机内存有限,默认的pm.max_children是5,任务一多进程就满了,后面的请求只能排队,排在队列外的请求直接失败。解决方法是修改PHP-FPM的进程管理配置,让它更适应低内存环境。编辑/etc/php/8.1/fpm/pool.d/www.conf

pm = ondemand pm.max_children = 10 pm.process_idle_timeout = 60s

我改成ondemand模式的原因在于:在这种模式下,PHP-FPM不会一启动就占满内存,而是在有请求时才动态创建子进程,空闲超过60秒自动回收。这对手机的内存环境非常友好,比默认的dynamic模式更能避免内存被占满。改完配置后重启php-fpm:

kill -USR2 $(cat /run/php-fpm.pid)

实测一段时间后,502出现的频率明显下降。

6.3 数据备份:一条命令打包整个Ubuntu

手机随时可能没电、重启、误卸载应用,所以在Ubuntu环境里做的所有配置和数据都面临丢失风险。我把数据备份这件事提醒排在所有优化之前,你应该先建立一个习惯:定期备份。

因为整个Ubuntu就是一个rootfs目录,备份的本质就是打包这个目录。最直接的方式是在Termux原生环境里,执行:

tar -zcf ubuntu-backup.tar.gz -C $PREFIX/var/lib/proot-distro/installed-rootfs ubuntu

这条命令把整个Ubuntu根文件系统压缩成一个tar.gz包。恢复时,执行:

proot-distro remove ubuntu tar -zxf ubuntu-backup.tar.gz -C $PREFIX/var/lib/proot-distro/installed-rootfs proot-distro login ubuntu

数据库数据的备份则是单独做一份。进入Ubuntu环境后,执行:

mysqldump -u root -p --all-databases > /root/all_databases_$(date +%F).sql

把这个SQL文件也打包进同一份tar包,或者定期同步到云盘。备份这件事我建议每周做一次,尤其是当你在上面已经积累了不小的工作成果之后。我有一天晚上不小心用rm -rf误删了一个项目目录,幸好有备份,不然整个星期的代码就没了。

6.4 为长期运行做的几项小优化

如果你打算把手机当成一台常开的微型服务器,以下几个优化能明显提升稳定性:

第一,给Termux设置开机自启动。Termux里创建一个.termux/boot目录,放入一个启动脚本,配合Termux:Boot插件,可以让手机开机后自动启动Termux并执行脚本,自动进入Ubuntu、启动Nginx、PHP-FPM和MariaDB。我写了一个简单的start_server.sh:

#!/data/data/com.termux/files/usr/bin/bash termux-wake-lock proot-distro login ubuntu -- bash -c "nginx; php-fpm8.1 -D; mysqld_safe --skip-syslog &"

第二,配置日志轮转。Nginx和PHP-FPM都会不断产生访问日志和错误日志,时间长了会撑爆手机存储。Ubuntu的logrotate工具可以按天切割日志,保留最近7天:

apt install logrotate -y

配置放在/etc/logrotate.d/nginx里,例如:

/var/log/nginx/*.log { daily rotate 7 compress missingok notifempty postrotate /usr/sbin/nginx -s reopen endscript }

如果遇到logrotate无法正常工作,也可以直接在Nginx配置里关闭不需要的access_log,或者使用access_log off;来减轻IO压力。手机闪存寿命有限,日志写太多并不是好事。

第三,限制PHP上传大小和内存。手机内存本来就不大,PHP默认配置的memory_limit是128M,upload_max_filesize是2M。如果跑的是轻量应用,可以把memory_limit降到64M,防止某个脚本占用太多内存导致整机卡顿。在/etc/php/8.1/fpm/php.ini里修改即可。

第四,如果需要每天定时备份、定时清理临时文件,可以安装cron:

apt install cron -y crontab -e

然后添加一条凌晨3点的备份任务:

0 3 * * * mysqldump -u root -p'密码' --all-databases | gzip > /root/db_backup_$(date +\%F).sql.gz

这里注意,cron在proot环境下同样没有systemd,你需要先启动cron服务,可以在登录Ubuntu后执行cron让它后台运行,或者把它加进Termux的启动脚本里。

6.5 性能数据:手机跑动态网站到底行不行

最后我放一组自己实测的数据,给对性能有顾虑的朋友一个直观参考。测试机是一部多年前的中端安卓手机,4GB内存,CPU为骁龙660。在Termux proot环境下运行Ubuntu 22.04 + Nginx + PHP 8.1 + MariaDB,没有做任何特别的性能调优。

用另一台电脑对整个网站根目录做并发请求压测,参数是并发50,持续30秒。结果是:每秒处理约120到160个请求,平均响应时间约280毫秒,没有出现请求失败。这个性能对于个人博客、留言板、内部工具系统、学习Demo来说绰绰有余。但如果要做商城、高并发应用,手机终归不是云服务器,性能和稳定性都不在一个量级。指望手机跑大型生产网站不太现实,但作为学习环境、低流量场景的演示服务器、或者是随时随地写代码调试的沙盒,它绝对够用。

我为什么要反复强调这一点?因为很多教程把"手机上跑Linux"吹得神乎其神,让新手误以为可以彻底取代云服务器。实际体验下来,proot的性能损失主要来自系统调用翻译,CPU密集型任务差距明显,比如PHP的排序算法、图片处理这类操作会比较吃力。但普通的CRUD网站,瓶颈根本不在CPU,而在内存和IO。手机的内存通常有4到12GB,跑一个小型Web服务是富余的。

这套方案我用下来最大的收获其实不是"免费的服务器",而是打破了"没有电脑就不能学服务端开发"的限制。地铁上、咖啡馆里、午休时间,只要有手机,随时能打开一个真实可访问的Linux环境写代码、跑数据库、验证想法。手机上运行的Ubuntu并不只是一个"模拟玩具",在proot支持范围内,它就是一套正儿八经的Linux系统。你在这套环境里面掌握的Nginx配置、数据库操作、Shell命令,和在任何一台云服务器上做的事完全一样。等你以后真的有一台云服务器,你会发现操作手感是零迁移成本的。

最后再分享一个小技巧:如果你在Termux里经常需要频繁进出Ubuntu环境,可以在~/.bashrc里加一个别名,减少敲字成本:

alias ubuntu='proot-distro login ubuntu' alias ubuntu-root='proot-distro login ubuntu --bind /sdcard:/mnt/sdcard'

第二条命令额外把手机的/sdcard目录挂载进了Ubuntu的/mnt/sdcard,这样就能在Ubuntu环境里直接访问手机存储的文件,传图片、导数据都方便很多。挂载参数--bind是proot-distro支持的,用起来比在Termux和Ubuntu之间来回切换拷贝文件省事多了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 11:09:52

STM32C5与LSM6DSVE轮询驱动实战:突破中断时序瓶颈

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 11:09:27

Python二手车数据分析及可视化系统实战:从爬虫到Flask大屏展示

很多人问我&#xff0c;用 Python 做数据分析到底能做出什么像样的东西&#xff0c;我一般都会拿这个二手车数据分析及可视化项目举例。这个系统从数据采集、清洗整理、多维度分析到可视化大屏展示&#xff0c;把 Python 数据分析的全流程走了一遍。它不是教科书里那种孤立的 d…

作者头像 李华
网站建设 2026/9/9 11:09:11

太阳能追光系统实战:基于STM32与Arduino的光伏板自动追踪设计

简介&#xff1a;针对STM32与Arduino联合实现的太阳能追光系统&#xff0c;这份资料提供了完整的工程源码与硬件配置&#xff0c;适合嵌入式学习者、电子设计竞赛参赛者以及新能源应用开发者。项目以自供能为特色&#xff0c;涵盖光照检测、角度追踪算法、步进电机驱动和电源管…

作者头像 李华
网站建设 2026/9/9 11:08:13

JMeter压测实战指南:线程组选型、参数化与性能分析全流程

JMeter这个工具我前前后后用了差不多六年&#xff0c;从最开始只会对着百度一顿乱搜&#xff0c;到后来给公司搭了一整套压测环境&#xff0c;中间踩过的坑说多不多说少不少。今天就把整个JMeter做压力测试的完整思路捋一遍&#xff0c;从安装配置到脚本设计&#xff0c;从线程…

作者头像 李华
网站建设 2026/9/9 11:07:52

基于CVaR的微网动态定价与调度策略及Matlab实现

做微网优化的人&#xff0c;应该都遇到过这种纠结&#xff1a;光伏出力飘忽不定&#xff0c;批发市场电价上蹿下跳&#xff0c;靠期望值做出来的调度方案看着利润挺高&#xff0c;但一遇到极端场景就“翻车”&#xff0c;不是购电成本爆表就是被考核罚款。这两年“基于条件风险…

作者头像 李华
网站建设 2026/9/9 11:06:47

STM32红外遥控器实战:NEC协议解码与发射完整指南

简介&#xff1a;STM32 红外遥控器程序是一份面向嵌入式初学者及课程设计/毕设学生的完整工程源码包。项目以 STM32 为控制核心&#xff0c;涵盖红外通信、PWM 脉冲编解码、GPIO 与定时器中断等硬件接口处理&#xff0c;并给出基于 NEC、RC5 等标准的信号解码与校验实现&#x…

作者头像 李华