宝塔面板下改 Linux hosts 的完整流程
宝塔没有专门的 hosts 入口,用文件管理就能改完。这篇讲清怎么定位、怎么编辑、改完为什么没生效、怎么验证。
先给结论
宝塔面板没有一个叫「hosts 管理」的菜单,改 hosts 就是改 /etc/hosts 这一个文件,
而这件事用面板自带的文件管理就能从头做完 —— 不用登 SSH,也不用装 FTP 客户端。
改完文件立即生效,但已经在跑的服务要重启才会读到新记录;
验证时又必须用 getent hosts 或 ping,不能用 dig / nslookup:
那两个直接查 DNS、根本不读 hosts,会让你以为没改成功。
它只适合调试和内部接口调用
hosts 改的是本机的解析,所以它天生是个「临时、单机、排障」的手段,典型就三类用法:
- 调试:域名还没解析到这台机器,先把它指过来联调站点、签发证书, 或者只是想知道某个新 IP 到底通不通;
- 内部接口调用:服务之间调内网接口,把域名固定指向内网地址,不依赖内部 DNS 是否可靠;
- 屏蔽:挡住某些域名的更新检查、统计上报。
⚠️ 注意:别拿它当生产流量的入口。每台机器都要改一遍、新扩的机器一定会漏、 出问题时
dig又看不见 —— 排查成本比老老实实改 DNS 记录高得多。
💡 提示:hosts 只影响本机。站点挂在 CDN 后面时,在回源服务器上改 hosts 只会影响这台服务器自己的出站解析,真实用户的访问路径不会因此改变。
动手之前先做三件事
先在文件管理里复制一份备份
在文件管理里选中 hosts,用顶部工具栏或右键菜单的「复制」,再「粘贴」,
就会得到一份 hosts - 副本。把它重命名成 hosts.bak 之类的名字,
别留着带空格的名字,后面用命令处理会麻烦。
查一下文件有没有被锁
有些加固脚本会给 /etc/hosts 加上不可变属性,这时候在面板里保存会提示成功、内容却没变。
面板界面看不到这个属性,得跑一条命令(面板左侧「终端」里执行):
lsattr /etc/hosts
输出里出现 i 就是被锁了,先解开(改完可以再锁回去):
chattr -i /etc/hosts
看有没有本地 DNS 缓存服务
glibc 自身不缓存,但 nscd 或 systemd-resolved 会。装了它的话,
改完 hosts 可能要等一下、或者重启服务才彻底生效:
systemctl is-active nscd systemd-resolved
第一步:路径栏输入 /etc 回车
打开面板左侧「文件」。注意它默认停在 /www,不要一层层往上点 ——
顶部有个路径输入框,直接敲 /etc 回车最快。
如果路径栏输入 /etc 后提示无权限,说明这个面板不是以 root 运行、
或者开了目录保护 —— 那就只能退回「终端」里用命令改,这篇文章的验证部分仍然适用。
第二步:双击 hosts,在里面改
找到 hosts 双击,面板会用自带编辑器打开。把要加、要删的行改好,点保存即可。
💡 提示:编辑器的编码/换行符选项如果能看到,确认是 UTF-8 + LF。 写进 BOM、或者行尾变成 CRLF,hosts 里会出现一整行认不出来的记录, 症状就是「明明写对了却不生效」。
保存完顺手确认权限没被改坏。正常应该是 -rw-r--r--,属主和用户组都是 root;
在列表的权限列或右键「权限」里都能看到,对不上就改回来:
chown root:root /etc/hosts && chmod 644 /etc/hosts
文件格式:一行一条,第一条生效
几条容易踩的:
- 同一个域名写了多条,只有第一条生效,后面的会被静默忽略;
- 域名不区分大小写,但不要写成
test.example.com.(结尾带点会被当绝对域名,行为更绕); - 别删掉
localhost那两行,很多程序靠它连本机,删了会出现各种莫名其妙的连接超时; - 一行里不要塞多个 IP,
1.1.1.1 2.2.2.2 a.com这种只有第一个 IP 有效。
改完像没生效,先排查这四种
- 用错了验证命令。
dig/nslookup/host直接发 DNS 查询,不读/etc/hosts, 它们返回的永远是真实解析结果,跟你的修改没有关系。 nscd/systemd-resolved在缓存。 重启对应服务即可:systemctl restart nscd,或者systemctl restart systemd-resolved。- 文件被
chattr +i锁住。 保存成功但内容没变,lsattr一查就知道。 - 改的不是同一个文件。
/etc/hosts是每个环境各自一份的;容器里改的是容器自己的/etc/hosts,宿主机上的修改不会自动进去,反过来也一样。
跑着的项目要重启,nginx 要 reload
上面四条都是「文件层」的原因。还有一条跟文件无关:已经在运行的进程不会重新读 hosts。 域名通常在进程启动时就解析成 IP 了,之后一直用缓存的那份 —— 数据库连接池、长连接、 HTTP keep-alive 更是这样,改 hosts 对它们毫无影响。
不同项目各自的重启方式:
- nginx:
nginx -s reload(宝塔「网站」界面里也能点重载)。反代里proxy_pass静态写域名的,只在启动和 reload 那一刻解析一次,所以改完 hosts 必须 reload; 若配置里用了变量配resolver,nginx 就只查指定的 DNS 服务器、完全不读 hosts, 这种情况只能把上游直接写成 IP。 - Go / Node / Java 这类常驻服务:
systemctl restart <服务名>, 或者宝塔对应项目面板里的「重启」。宝塔的 Go 项目面板点完重启才算数。 - PHP 站点:一般每个请求都会重新解析;但用了持久连接(
pconnect)的就需要systemctl reload php-fpm-<版本>(宝塔「软件商店 → PHP → 重载配置」)。 - 宝塔面板自身:面板也是常驻进程,如果这次改 hosts 影响的是面板要访问的地址,
在「终端」里
bt restart重启面板。
想确认它到底还在连谁,看一眼已建立的连接就行:
ss -tnp | grep <端口>
💡 提示:只是临时验证的话,不一定要重启整个服务。
curl --resolve能让这一次请求 走指定 IP,验证完什么都不用动,见下面「验证」一节。
验证:认准这三条命令
在面板左侧「终端」里跑:
getent hosts test.example.com
ping -c 2 test.example.com
curl -I --resolve test.example.com:443:<目标IP> https://test.example.com/
getent hosts 走的是和应用程序相同的解析链路(读 hosts),是最准的一条;
ping 回显的 IP 最直观;curl --resolve 则能在完全不改 hosts 的前提下,
临时把域名指向指定 IP 发一次请求 —— 如果只是想验证某个 IP 对不对,这条比改 hosts 干净得多。
宝塔环境下的三个特有坑
- 别用面板的「计划任务」去写 hosts:定时任务里跑命令,效果和手动执行一模一样, 但这条临时记录藏在计划任务里,事后排查要多绕一层,不如直接在文件管理里改。
- 在宝塔里给站点申请证书时,如果域名还没解析到这台机,常用 hosts 把域名指过来完成验证。 验证完把那行删掉,留着会影响后续的正常解析。
- hosts 是系统文件,面板的备份/还原不会管它,网站备份里也不含它。
改之前留的那份
hosts.bak,别跟着一起删了。
怎么安全地撤销
临时加的记录(尤其是给调试和内部调用加的那些),用文件管理打开 hosts
把那一行删掉、保存就完事了;删完同样要重启一次相关进程,否则它对内还在走临时地址。
改动比较多的时候,也可以拿备份整个覆盖回来:在文件管理里删掉 hosts,
把 hosts.bak 重命名成 hosts。
⚠️ 注意:覆盖式还原会把这段时间里别人加的其他记录一起冲掉。 多人维护的机器上,优先用「按行删」的方式只删自己加的那条。
下一步
改完先用 getent hosts <域名> 确认解析正确、重启依赖它的进程,再决定要不要动 DNS 记录。
如果是在做域名迁移,建议的顺序是:本机 hosts 验证 → 小流量切 DNS → 观察回源日志 →
全量切换,每一步都留好回滚点。hosts 是调试和内部调用用的临时手段,不是长期方案。