一台没有独立显卡的机器,我想在上面跑一个语言模型,并且让局域网里的其他设备也能调用它。
装的部分没什么好说的,一条命令就结束了。麻烦的地方在"跑起来"之后: 它默认只肯跟自己说话,而我看不出它到底是用什么在算、为什么第一次响应要等那么久。
这篇记的是那之后的四件事:让它对外说话、确认它在跑、看懂它在用什么算、以及把那 7 秒钟拆开。
01第一件事:让它监听所有网卡
默认情况下,服务只绑定在 127.0.0.1——也就是"只有本机能连"。
这台机器上跑得好好的,我在笔记本上 curl 它就是连不上。
nohup env OLLAMA_HOST=0.0.0.0:11434 ollama serve >> /var/log/ollama.log 2>&1 &
这一行里有四个东西,缺一个都会出问题:
nohup—— 让进程脱离终端。不加它,你断开 SSH 的那一刻服务就没了。env OLLAMA_HOST=0.0.0.0:11434—— 把监听地址改成所有网卡。0.0.0.0不是某个具体地址,它的意思是"接受来自任何网卡的连接"。 这是它的默认值127.0.0.1的反面。>> /var/log/ollama.log 2>&1—— 标准输出和错误都追加到日志文件。2>&1是必须的,否则错误信息会被丢掉—— 而排查问题时,你要找的恰恰是错误信息。- 末尾的
&—— 放后台,让终端立刻还给你。
02第二件事:用三个动作确认它活着
# 1. 进程在不在 ps aux | grep ollama # 2. 日志里最后几行说了什么 tail -n 5 /var/log/ollama.log # 3. 接口通不通(注意用局域网地址,不是 localhost) curl http://192.168.1.3:11434/api/generate \ -d '{"model":"llama3.2","prompt":"Hi","stream":false}'
第三个动作有个容易做错的地方:测试要用局域网 IP,不能用 localhost。
在 localhost 上测通,只证明"它自己认识自己",
完全不能说明外部能不能连上。
03第三件事:它在用什么算
启动日志把硬件情况交代得很清楚:
level=INFO msg="discovering available GPUs..."
level=INFO msg="model list cache hydration complete" models=1 failures=0 elapsed=10.330729ms
level=INFO msg="inference compute" id=cpu library=cpu name=cpu total="10.9 GiB" available="6.3 GiB"
level=INFO msg="vram-based default context" total_vram="0 B" default_num_ctx=4096
逐行读:
- 第一行说它在找 GPU。后面没有出现任何 GPU 的名字,
而
inference compute那行里id=cpu、library=cpu—— 意思很明确:这台机器上没有它能用的加速设备,全部落到 CPU 上算。 total="10.9 GiB" available="6.3 GiB"是内存的账。 这是最关键的一行:模型必须装进 6.3 GiB 这个可用额度里, 而不是标称的 10.9。已经跑着别的服务时,这个数会更小。total_vram="0 B"+default_num_ctx=4096说明因为显存为零, 上下文长度被按 CPU 的默认值设成了 4096 个 token。想让它记住更长的对话,得手动调—— 代价是内存占用同步上升。
04第四件事:那 7 秒花在哪了
上面那条 curl 第一次跑完,返回的 JSON 里带着一组 duration 字段。
它们都是以纳秒为单位的整数,我把它换算成秒排了一遍:
| 字段 | 纳秒 | 秒 | 占比 |
|---|---|---|---|
load_duration | 6 089 822 341 | 6.09 s | 85.3% |
prompt_eval_duration | 522 756 000 | 0.52 s | 7.3% |
eval_duration | 510 453 000 | 0.51 s | 7.2% |
total_duration | 7 134 792 185 | 7.13 s | 100% |
7.13 秒里,6.09 秒花在"把模型加载进内存"上,真正算的部分只占了 1 秒。
而且这 1 秒还能再拆:prompt_eval 是处理我那句 "Hi" 的时间(0.52 秒),
eval 是生成回答的时间(0.51 秒)。生成的量是 eval_count: 8——
八个 token。
8 token ÷ 0.51 s ≈ 15.7 token/s
15.7 token/秒,纯 CPU。这个速度用于生成短句是可以接受的—— 它大概相当于人快速阅读的速度,等一两秒出半句话,感觉不算煎熬。 但用来写长文就会很难受:一千个 token 要等一分多钟。
更重要的是那个 6.09 秒。它不代表这台机器算得慢, 它代表"模型还没进内存"。所以同一台机器上第二次问同样的问题, 只要模型还在内存里,响应会明显快得多——因为最大的一块开销被跳过了。
这也是为什么"用同一句话前后测两次"这件事很重要: 第一次的数字看着吓人,但它测的是加载,不是推理。
05停掉它
pkill -f "ollama serve"
ps aux | grep "ollama serve" | grep -v grep
-f 让 pkill 匹配完整的命令行而不只是进程名,
这样能准确命中带参数启动的那个进程。
第二行的 grep -v grep 是把它自己的搜索进程过滤掉,
否则你永远会看到"似乎还有一个在跑"。
这台机器上跑着模型、Agent、还有别的服务,内存的
available是共享的。 所以"能不能跑某个模型"这个问题,答案不取决于模型有多大, 而取决于此刻还剩多少可用内存——它每天都不一样。
06留下四个可以带走的东西
- 本地服务要对外,先看它绑在哪。
127.0.0.1和0.0.0.0只差几个字符,一个只能自己用,一个全网可达。 - 测连通性要用真实 IP,不要用 localhost。 这两个测试回答的是不同的问题。
available才是能用的内存,不是total。 决定模型能不能加载的是前者,而且它随时在变。- 看耗时不要只看总数,要拆开。 加载、处理输入、生成输出是三笔独立的账。 混在一起看,你会误以为"这台机器算得慢",而实际上它只是"还没醒"。
- 关于本文
- 整理自 2026 年 8 月 31 日的便签记录。日志与 JSON 返回值为当时的真实输出, 机器为无独立显卡的 aarch64 设备(可用内存 6.3 GiB)。
- 2026.09.20 整理
- 新增第 04 节。原始便签里只是把启动命令和几条验证命令罗列在一起, 没有解释那些 duration 字段——而它们才是"为什么第一次这么慢"的答案。
留言
正在载入留言…