在另一台电脑上查看 Python 程序日志:从创建到远程访问
在 Ubuntu 上跑一个批处理脚本离开电脑后想知道它执行到哪一步通常还得重新打开终端。假如只是看几行进度没有必要为此部署一整套日志平台让程序把过程写进文件再用一个小网页读取就足够完成这次练习。本文用两个 Python 文件实现这个过程Ubuntu 生成日志Mac 浏览器通过星空组网地址查看。代码只使用标准库不装第三方包也不需要数据库。页面每隔 3 秒重新读取日志展示最新 20 行。一、登录后台让两台设备先连起来打开星空组网官网点击“后台管理”。没有账号可以先注册已有账号直接登录。本次浏览器已有有效登录状态因此复用原账号下图拍摄的是空白登录入口没有重新注册或填写密码。首次使用时进入“设备管理 → 成员列表”点击“添加成员”为 Ubuntu 和 Mac 分别准备成员账号。名称可以按设备用途填写创建后保存完整成员账号和密码再到对应客户端登录。不要让两台长期在线设备共用一个成员账号字段说明见官方设备与成员管理文档。客户端尚未安装的读者分别按 Linux 使用说明和 macOS 使用说明操作。Linux 安装完成后根据终端输出打开控制台地址登录成员账号确认在线状态和组网 IP。本文两端均已安装并登录直接沿用现有成员没有重复创建。在这里插入图片描述这次的分工和地址如下复现时换成自己客户端显示的实际值设备用途本次组网 IPUbuntu 22.04运行示例程序与日志网页192.168.188.5Mac用浏览器查看日志192.168.188.1星空组网负责两端的网络访问日志生成和网页展示由我们自己写的程序完成。后台“组网成功”是第一步后面还要实际访问网页才能确认这条路径可用。二、检查环境创建独立目录在 Ubuntu 终端执行lsb_release-dspython3--versionip-4-briefaddress show StarVPN ss-ltnsport :18093本次 Python 为 3.10.1218093没有监听记录可以用作演示端口。若有其他程序占用换一个空闲端口并同步修改启动命令和浏览器地址。虚拟网卡的UNKNOWN不应单独作为掉线结论还要结合客户端状态与实际访问判断。随后创建项目目录mkdir~/log-viewer-demo-20260925cd~/log-viewer-demo-20260925截图使用现有 root 实验会话所以路径在/root下普通用户直接在自己的家目录执行即可不需要为了这篇教程切换 root。若提示目录已存在先检查内容或换一个新目录名避免覆盖旧文件。三、准备两个 Python 文件项目的数据流很简单demo.py → demo.log → server.py → 浏览器。一个文件负责产生日志另一个负责读取两者可以分别启动和停止。先创建demo.py。下面整段复制到 Ubuntu 终端执行包括末尾单独一行的PYcatdemo.pyPY import logging import time from pathlib import Path LOG_FILE Path(__file__).with_name(demo.log) BATCH_COUNT 12 INTERVAL_SECONDS 2 def main() - None: logging.basicConfig( filenameLOG_FILE, encodingutf-8, levellogging.INFO, format%(asctime)s %(levelname)-7s %(message)s, datefmt%H:%M:%S, ) logging.info(Demo started: processing sample batches) try: for batch in range(1, BATCH_COUNT 1): time.sleep(INTERVAL_SECONDS) logging.info(Batch %02d/%d completed, batch, BATCH_COUNT) if batch 4: logging.warning(Demo warning: sample row skipped (simulated)) except KeyboardInterrupt: logging.info(Demo interrupted by user) else: logging.info(Demo finished) if __name__ __main__: main() PY它每隔 2 秒记录一个批次共执行 12 批约 24 秒后结束。第 4 批额外写入一条模拟WARNING用来观察不同日志级别并不表示服务器真的发生故障。日志追加到脚本旁边的demo.log不是写在终端里。再创建网页服务server.pycatserver.pyPY import argparse import html import ipaddress import logging from collections import deque from datetime import datetime from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path LOG_FILE Path(__file__).with_name(demo.log) MAX_LINES 20 REFRESH_SECONDS 3 PAGE !doctype html html langzh-CNmeta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1 meta http-equivrefresh content{refresh} titlePython 程序日志/title style body {{ max-width:1040px; margin:40px auto; padding:0 24px; font:17px/1.7 system-ui,sans-serif; background:#f3f6fa; color:#21334a; }} h1 {{ font-size:32px; margin:8px 0; }} p {{ color:#52657c; }} pre {{ padding:24px; background:#132238; color:#e1ebf5; border-radius:12px; overflow:auto; font:16px/1.8 monospace; }} small {{ color:#52657c; }} /style headersmall远程查看 · 只读演示/smallh1Python 程序日志/h1 p显示 demo.log 最新 {limit} 行 · 每 {refresh} 秒刷新/p/header p页面读取时间{now}/p pre{content}/pre small示例数据由 demo.py 生成WARNING 为模拟提示。/small/html def read_tail() - str: try: with LOG_FILE.open(encodingutf-8, errorsreplace) as stream: return .join(deque(stream, maxlenMAX_LINES)) or 日志文件暂时为空。 except FileNotFoundError: return 还没有日志请在 Ubuntu 运行 python3 demo.py。 class Handler(BaseHTTPRequestHandler): def do_GET(self) - None: if self.path ! /: self.send_error(404, Not found) return try: content read_tail() except OSError: logging.exception(Cannot read demo.log) self.send_error(500, Cannot read demo.log; check server terminal) return body PAGE.format( refreshREFRESH_SECONDS, limitMAX_LINES, nowdatetime.now().astimezone().isoformat(timespecseconds), contenthtml.escape(content), ).encode(utf-8) self.send_response(200) self.send_header(Content-Type, text/html; charsetutf-8) self.send_header(Content-Length, str(len(body))) self.send_header(Cache-Control, no-store) self.send_header(X-Content-Type-Options, nosniff) self.end_headers() self.wfile.write(body) def main() - None: parser argparse.ArgumentParser() parser.add_argument(--bind, requiredTrue, typeipaddress.IPv4Address) parser.add_argument(--port, typeint, default18093) args parser.parse_args() if args.bind.is_unspecified or args.bind.is_multicast: parser.error(--bind must be one specific local IPv4 address) if not 1024 args.port 65535: parser.error(--port must be between 1024 and 65535) with ThreadingHTTPServer((str(args.bind), args.port), Handler) as server: print(fLog viewer: http://{args.bind}:{args.port}, flushTrue) print(Press CtrlC to stop., flushTrue) try: server.serve_forever() except KeyboardInterrupt: print(Log viewer stopped., flushTrue) if __name__ __main__: main() PY这里没有开放文件目录浏览也不让访问者传入任意日志路径。服务只读取固定的demo.log缺少文件时显示操作提示读取失败则返回错误并把原因留在服务终端。html.escape()用于把日志作为普通文字展示避免其中的尖括号被解释成网页标签最新 20 行只是显示范围不会删除日志文件中的旧内容。每次请求仍会顺序读取文件因此这个简版适合小型演示日志不适合直接读取几个 GB 的生产日志。完成后检查文件和语法ls-lhdemo.py server.py python3-mpy_compile demo.py server.pyechoPYTHON_SYNTAX_OK四、先启动网页再从 Mac 打开在当前 Ubuntu 终端运行python3 server.py--bind192.168.188.5--port18093--bind后面填写 Ubuntu 自己的组网 IP。不要填写 Mac 的地址也不要把它换成127.0.0.1后者只能从 Ubuntu 本机访问。本例只监听指定组网地址不监听所有网卡。保持这个终端运行在 Mac 浏览器输入完整地址http://192.168.188.5:18093/首次打开时还没有运行日志生成程序因此看到“还没有日志请在 Ubuntu 运行 python3 demo.py”是正常状态。它说明网页已经能访问只是演示文件尚未生成。页面上的“读取时间”来自 Ubuntu代表本次页面读取的时刻它与每一条日志产生的时间是两个概念。服务使用简单的整页定时刷新不是 WebSocket 推送新增内容通常在下一次刷新时出现。五、运行程序对照两端结果再打开一个连接同一台 Ubuntu、使用同一用户的终端进入刚才的目录并执行cd~/log-viewer-demo-20260925 python3 demo.py这时终端暂时没有文字输出因为内容写入了日志文件。回到 Mac 页面可以看到批次逐步增加程序结束后会出现Demo finishedUbuntu 的第二个终端也会回到命令提示符。在这个终端查看最后 5 行tail-n5demo.log再与 Mac 页面底部逐行对照本次最终运行从15:52:47开始到15:53:11完成共产生 15 行记录网页和终端中的批次、时间及完成信息一致。Mac 请求的源地址为192.168.188.1目标为192.168.188.5页面返回 HTTP 200。这证明了本次经组网地址访问日志页的结果不据此推断连接一定采用 P2P 直连。如果再次执行demo.py新内容会继续追加网页只显示文件末尾 20 行。即使程序已经结束网页读取时间仍会变化判断任务是否结束应看日志中的完成标记而不是页面时间有没有更新。六、遇到问题先查这几个位置现象优先检查启动时报地址不可用--bind是否是 Ubuntu 当前拥有的组网 IP浏览器打不开两端是否在线、服务终端是否仍在运行、IP 和端口是否一致一直提示还没有日志是否在同一台 Ubuntu、同一个项目目录运行了demo.py日志读取报错查看服务终端的异常信息确认文件权限与路径排查时先在 Ubuntu 用ss -ltn sport :18093确认服务确实监听再检查组网访问控制和主机防火墙不要为了试通而直接关闭全部防护。HTTP 请求日志与demo.log也要区分前者打印在网页服务终端后者由示例程序写入文件。七、用完停止服务保留代码先关闭 Mac 上的演示页面回到运行server.py的 Ubuntu 终端按CtrlC。看到Log viewer stopped.后检查端口ss-ltnsport :18093ls-lhdemo.py server.py demo.log本次停止后没有监听记录Mac 再次连接也被拒绝。demo.py已自行结束项目文件继续保留之后进入同一目录重新运行启动命令即可。若演示程序尚未结束也可以在它所在的终端按 CtrlC。这个页面没有额外的应用登录验证能够访问该组网地址和端口的设备可以读取展示内容因此本次只使用无敏感信息的演示日志。Python 官方文档也明确说明http.server不推荐用于生产环境。需要长期查看真实业务日志时再考虑鉴权、访问权限、日志轮转以及更合适的日志平台。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →