ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

星空组网实战:用 Python 部署一个远程 Ubuntu 状态页

星空组网实战:用 Python 部署一个远程 Ubuntu 状态页 有一台 Ubuntu 主机人在外面时想看它是否还在运行、磁盘还剩多少空间最直接的练习就是做一张只读状态页再通过星空组网地址访问它。本文从官网登录开始带零基础读者完成组网确认、代码创建、Ubuntu 部署和跨设备验证。页面只展示时间、运行时长和根分区剩余空间不需要安装第三方 Python 包。1. 登录官网确认两端已经入网打开星空组网官网进入登录页选择账号登录。登录后先看管理平台首页的“组网状态”这次操作时两台设备都显示在线页面提示组网成功。已有账号和设备的读者可直接进入下一步。如果你还没有把电脑和 Ubuntu 加入同一个组网先按官方设备与成员管理和 Linux 客户端说明完成安装与登录。官方文档将“成员账号”和设备关联需要长期同时在线的设备分别使用成员账号。本次演示沿用了已经在线的设备没有新建成员账号。2. 在 Ubuntu 上确认环境和组网 IP登录 Ubuntu 终端先执行cat/etc/os-release|head-n3python3--versionip-4addr我实际使用的是 Ubuntu 22.04 LTS、Python 3.10.12。ip -4 addr输出中StarVPN接口的地址是192.168.188.5/24。这里的192.168.188.5就是后面启动服务时要绑定的地址你的设备可能不同。若找不到组网 IP先检查客户端是否在线不要直接用公网 IP 代替。3. 创建状态页项目在 Ubuntu 上建一个演示目录mkdir-p~/starvpn-status-demo-20260925cd~/starvpn-status-demo-20260925nanoserver.py把下面的完整代码粘贴进server.py保存退出。它使用 Python 标准库读取/proc/uptime、根分区磁盘信息和当前时间再由内置 HTTP 服务返回页面。/proc/uptime是 Linux 提供的数据文件因此这份示例应在 Ubuntu 上运行。A tiny read-only Ubuntu status page for a StarVPN demo.importargparseimportipaddressimportshutilfromdatetimeimportdatetimefromhttp.serverimportBaseHTTPRequestHandler,ThreadingHTTPServerfromstringimportTemplate PAGETemplate(!doctype html html langzh-CN head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1 titleUbuntu 状态卡片/title style * { box-sizing: border-box; } body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #eef3f8; color: #172b4d; font: 16px/1.6 system-ui, sans-serif; } main { width: min(900px, calc(100% - 40px)); padding: 42px 0; } .eyebrow { color: #2771b8; font-size: 14px; font-weight: 700; letter-spacing: .08em; } h1 { margin: 6px 0; font-size: clamp(32px, 5vw, 48px); } .intro { margin: 0 0 30px; color: #58708d; } .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; } article { min-height: 170px; padding: 24px; border: 1px solid #dce5f0; border-radius: 18px; background: #fff; box-shadow: 0 12px 30px #20436a0c; } article h2 { margin: 0 0 18px; color: #58708d; font-size: 15px; font-weight: 600; } strong { display: block; font-size: 25px; line-height: 1.3; } small { display: block; margin-top: 8px; color: #6d8097; } footer { margin-top: 22px; color: #6d8097; font-size: 14px; } media (max-width: 700px) { .cards { grid-template-columns: 1fr; } article { min-height: 0; } } /style /head body main div classeyebrowSTARVPN · 远程查看/div h1Ubuntu 状态卡片/h1 p classintro打开组网地址即可查看这台主机的实时状态。/p section classcards aria-label主机状态 articleh2当前时间/h2strong$now/strongsmall以 Ubuntu 主机时区为准/small/article articleh2已运行/h2strong$uptime/strongsmall系统自上次启动以来/small/article articleh2根分区剩余/h2strong$free_gib GiB/strongsmall总容量 $total_gib GiB/small/article /section footer刷新页面可获取最新数据 · 本页仅用于组网内演示/footer /main /body /html )defstatus_page()-bytes:withopen(/proc/uptime,encodingascii)asuptime_file:secondsint(float(uptime_file.read().split()[0]))days,remainderdivmod(seconds,86400)hours,minutesdivmod(remainder,3600)minutes//60diskshutil.disk_usage(/)pagePAGE.substitute(nowdatetime.now().astimezone().strftime(%Y-%m-%d %H:%M:%S %z),uptimef{days}天{hours}小时{minutes}分钟,free_gibf{disk.free/1024**3:.1f},total_gibf{disk.total/1024**3:.1f},)returnpage.encode(utf-8)classHandler(BaseHTTPRequestHandler):defdo_GET(self)-None:ifself.path!/:self.send_error(404,Not Found)returntry:contentstatus_page()except(OSError,ValueError)asexc:self.log_error(读取主机状态失败: %s,exc)self.send_error(500,Internal Server Error)returnself.send_response(200)self.send_header(Content-Type,text/html; charsetutf-8)self.send_header(Cache-Control,no-store)self.send_header(X-Content-Type-Options,nosniff)self.send_header(Content-Length,str(len(content)))self.end_headers()self.wfile.write(content)defmain()-None:parserargparse.ArgumentParser(description只在指定组网 IP 上展示 Ubuntu 状态)parser.add_argument(bind_ip,helpUbuntu 客户端显示的组网 IP)parser.add_argument(port,typeint,help监听端口例如 18097)argsparser.parse_args()try:ipaddress.IPv4Address(args.bind_ip)exceptipaddress.AddressValueErrorasexc:parser.error(f无效的 IPv4 地址:{exc})ifnot1args.port65535:parser.error(端口必须在 1 到 65535 之间)try:withThreadingHTTPServer((args.bind_ip,args.port),Handler)asserver:print(f状态页已启动http://{args.bind_ip}:{args.port}/,flushTrue)server.serve_forever()exceptOSErrorasexc:parser.exit(1,f启动失败:{exc}n)exceptKeyboardInterrupt:print(n服务已停止)if__name____main__:main()代码只有一个页面/其他路径返回 404读取状态失败时返回 500。页面数据每次请求时重新读取刷新浏览器即可更新。服务只监听命令中指定的 IPv4 地址示例里使用组网 IP不要把它替换为0.0.0.0。4. 在 Ubuntu 上启动服务确认端口18097没被占用然后在项目目录执行cd~/starvpn-status-demo-20260925 ss-ltnp|grep:18097||truenohuppython3 server.py192.168.188.518097run.log21echo$!run.pid ss-ltnp|grep:18097curl-sS-o/dev/null-wHTTP %{http_code}nhttp://192.168.188.5:18097/nohup让服务在关闭当前终端后继续运行run.pid记录本次进程号。我的终端中可以看到192.168.188.5:18097处于LISTEN本机 HTTP 请求返回200。如果端口已被占用换一个未使用端口并在后续访问地址中同步修改。启动失败时先看cat run.log常见原因是 IP 填错或端口被占用。5. 从另一台设备访问并验证让访问端电脑也登录同一星空组网打开http://192.168.188.5:18097/我在另一台已入网电脑的浏览器中看到了 Ubuntu 的当前时间、已运行时长和根分区剩余空间。地址栏是 Ubuntu 的组网 IP说明这次访问用的是组网地址。下图是实际打开的页面数据会随时间变化。浏览器地址栏可能提示“不安全”因为这个演示应用使用普通 HTTP没有为网页配置 HTTPS。同一组网里能够访问这台主机的成员也可能看到页面所以它只适合作为只读练习不要在页面展示敏感数据也不要为了访问它而开放公网端口。如果页面打不开按顺序检查两端客户端是否在线、Ubuntu 的组网 IP 是否填对、ss -ltnp是否显示服务监听、Ubuntu 本机curl是否能拿到200。这些都正常后再检查主机防火墙对组网接口的规则。6. 演示结束后停止和清理临时项目不需要一直运行。先在项目目录停止本次进程再确认端口不再监听cd~/starvpn-status-demo-20260925ps-fp$(catrun.pid)kill$(catrun.pid)ss-ltnp|grep:18097||echo演示服务已停止确认目录里只有本教程创建的文件后可删除这个演示目录cd~rm-r~/starvpn-status-demo-20260925这次实操已按上述顺序停止并清理星空组网账号和原有设备连接未删除。下次要复现时重新放入server.py并启动即可。小结整个流程是登录管理平台确认组网在线 → 在 Ubuntu 找到组网 IP → 编写只读状态页 → 绑定组网 IP 启动 → 从另一台设备打开验证。这个小项目的价值在于把“组网成功”落到一个可访问的服务上同时避免了数据库、Docker 和额外依赖适合作为第一次动手练习。
返回列表