news 2026/9/17 8:13:22

Ubuntu 20.04 Samba 启动失败 status=255 排查修复

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 20.04 Samba 启动失败 status=255 排查修复

装完 Samba 敲下systemctl start smbd,终端里直接甩出一行Job for smbd.service failed because the control process exited with error code,再systemctl status smbd一看,末尾赫然写着status=255/n/a——这个画面我在 Ubuntu 20.04 上见过太多次了。它跟一般的“配置写错了”完全不是一个性质:testparm可能一句报错都没有,共享目录权限看着也没问题,但服务就是起不来。很多人第一反应是重装 Samba,apt purge三遍,结果一样。其实 error255 是 smbd 进程自己给自己判了“死刑”,代码里明确exit(255)才会出现这个退出码,它背后通常藏着路径缺失、状态目录权限被改动、接口绑定不匹配、TDB 数据库损坏这几类硬伤。这篇内容我就按 Ubuntu 20.04 + Samba 4.11 这套最典型的组合,把 error255 从“为什么”到“怎么修”整条链路拆开讲,顺带把我这些年踩过的坑全摊开。不管你是第一次在虚拟机上搭文件共享,还是给公司的内网机器配共享盘,只要你遇到 255,基本都能在这里找到对应分支。

1. 先搞清楚 error255 到底在说什么

1.1 退出码 255 的真实含义:站在 systemd 视角看问题

很多人把 255 当成“Samba 的某个报错编号”,这个理解方向就偏了。在 Linux 里,进程退出码 0 代表正常结束,1 到 125 是程序自定义的业务错误码,126 和 127 与“命令不可执行 / 找不到命令”相关,128 到 254 通常跟信号量挂钩,而255 是一个“兜底值”——当程序内部判定自己处于一种“无法继续、也不属于任何已知错误分类”的状态时,最省事的做法就是直接exit(255)。Samba 源码里大量存在这种写法:初始化阶段一旦发现某个必须存在的目录拿不到、某个文件打不开、某个配置文件无法解析,代码不走恢复逻辑,直接返回 255 收场。

systemd 的角色只是“记录者”。Ubuntu 20.04 上smbd.serviceType=notify类型,意思是 systemd 启动 smbd 之后会等它通过 sd_notify 发一个READY=1的信号,才认为服务启动成功。如果 smbd 在发信号之前就退出了,systemd 就会把它的退出码原样报出来,于是你看到的日志长这样:

smbd.service: Main process exited, code=exited, status=255/n/a smbd.service: Failed with result 'exit-code'. Failed to start Samba SMB Daemon.

注意最后那行Failed with result 'exit-code',它跟result 'timeout'(超时未就绪)和result 'signal'(被信号杀掉)是两个不同的分支。看到exit-code,就说明进程是主动退的,不是被 OOM 干掉,也不是卡死。这一点很关键,它直接决定了排查方向:你要找的是“smbd 在启动过程中主动放弃”的原因,而不是“端口被占”或者“内存不够”这类外部因素——虽然端口冲突有时也会以 255 的形式表现,但那是少数派。

另外提醒一句,status=255后面那个/n/a表示 systemd 没能拿到更细的信号信息,这是正常的,别被它误导。真正有用的信息在它上面的几行,以及journalctl -xeu smbd展开后的上下文里。

1.2 三类最典型的触发场景与我的分类法

踩坑多了以后,我把 Samba 的 error255 归结成三大类,按出现频率从高到低排:路径与权限类、配置与接口类、数据与状态残留类

路径与权限类占了我遇到案例的一半以上。典型的比如/var/run/samba这个运行时目录被清掉或者权限被改成了 0755 以下,/var/lib/samba/private的属主从 root 变成了别的用户,/var/log/samba不存在导致log file写不进去。这类问题的共同特点是:testparm -s会告诉你语法全对,但smbd -i前台运行时会立刻抛出一行Unable to create directory ...或者Could not open ...,然后就退出了。

配置与接口类相对隐蔽一些。interfacesbind interfaces only这两个参数组合是经典陷阱:有人从别的机器上抄了一份 smb.conf,里面写着interfaces = lo eth0bind interfaces only = yes,而 Ubuntu 20.04 的网卡叫ens33enp0s3,结果 smbd 绑定不到任何有效接口,直接退出。还有一个隐藏更深的变体是netbios name字段——它默认为主机名,但 NetBIOS 名字长度上限是 15 个字符,且不允许空格和下划线之外的怪符号,主机名一旦超标或者带特殊字符,nmbd 那侧就会出问题,有些发行版会把错误合并报给 smbd,最终表现为 255。

数据与状态残留类最难查,也最容易让人怀疑人生。典型代表是passdb.tdbsecrets.tdb这类 TDB 数据库在断电或强制关机后损坏,smbd读它时直接失败。另一个变体是系统里同时存在两套 Samba:一个是 apt 装的/usr/sbin/smbd,另一个是手工编译装在/usr/local/samba的,PATH或者 systemd unit 指向了错误的那个,两边状态目录对不上,也会 255。

提示:判断属于哪一类,有一个 30 秒的快速方法——直接sudo smbd -i -d 3(前台、调试级别 3)跑一次,看它在退出前最后打印的那几行。所有 255 场景里,日志的最后 5 行几乎都直指根因。

2. 从零复现:Ubuntu 20.04 上 Samba 安装与最小可用配置

2.1 安装包选型与 apt 源确认

先把环境说清楚。Ubuntu 20.04 官方源里的 Samba 版本是 4.11.x,这一代的配置语法和 4.0 之前的差异非常大,网上大量老教程里的security = share早就被移除了,照抄必翻车。安装本身很简单:

sudo apt update sudo apt install -y samba samba-common-bin smbd --version

smbd --version应该输出类似Version 4.11.6-Ubuntu。如果这条命令报找不到,多半是sambasamba-common-bin只装了一个,或者PATH被人改过——这也算是一种“伪 255”,服务能起但客户端连不上,容易被误判。

关于源,我个人的习惯是保持官方源不动。见过不少人为了让下载快点,把源换成一堆乱七八糟的镜像,结果samba-common-binsamba版本不一致,运行期库函数对不上,启动阶段直接崩。真遇到源慢,换一个国内主流的镜像站就够,不要混用多个源。

安装完成后,先别急着改配置,先确认几个关键目录的状态:

ls -ld /etc/samba /var/log/samba /var/lib/samba /var/lib/samba/private /run/samba

正常输出的属主组装应该全是root:root,权限大致是/var/log/samba为 0755、/var/lib/samba/private为 0700、/run/samba为 0755。这里任何一项不对,后面都可能演化成 255。我习惯在改配置之前先把这四行输出存到笔记里,出问题时有对比基线。

2.2 一份经过验证的最小 smb.conf

与其在 Ubuntu 默认那 300 行带注释的smb.conf上改来改去,不如直接换成一份干净的最小配置。默认文件先备份:

sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.orig sudo tee /etc/samba/smb.conf > /dev/null <<'EOF' [global] workgroup = WORKGROUP server string = Ubuntu 20.04 File Server netbios name = UBSRV server role = standalone server security = user map to guest = never log file = /var/log/samba/log.%m max log size = 5000 logging = file log level = 1 obey pam restrictions = yes unix password sync = yes passwd program = /usr/bin/passwd %u pam password change = yes usershare allow guests = no idmap config * : backend = tdb [share] path = /srv/share browseable = yes read only = no valid users = smbuser create mask = 0664 directory mask = 2775 force group = smbgroup EOF

这份配置里每一行都有理由。server role = standalone server明确告诉 Samba 这是一台独立服务器,不是域控,很多 255 案例就是因为从域控配置里抄了server role = active directory domain controller,但环境里根本没有 Kerberos,smbd 启动初始化阶段就会放弃。logging = file是 4.11 推荐的新写法,替代老旧的syslog only之类。idmap config * : backend = tdb单独列出来,是因为 Ubuntu 上如果这个参数缺失且系统又装过 winbind,idmap 初始化可能失败。

create mask = 0664directory mask = 2775这两个值值得展开算一下。0664 拆成二进制是rw-rw-r--,意思是新建文件时,属主和属组都有读写权限,其他人只读。2775 里的首位 2 是setgid 位,它让目录里新建的子目录和文件自动继承父目录的属组——这正是团队共享盘最需要的特性。775 部分即rwxrwxr-x。这两个 mask 和后面要设置的目录权限必须互相匹配,否则会出现“能连上但写不进去”的二级故障。

注意:绝对不要在[share]段里写path = /或者path = /home。共享根目录会把自己 open 到 AppArmor 和权限系统最容易出问题的区域,我见过因为共享/home导致 smbd 启动时尝试遍历目录,撞上某个用户的 0700 家目录而退出的案例。

2.3 用户与目录权限的建立顺序(顺序错了就出 255)

顺序非常重要:先建系统组和系统用户,再建共享目录并设权限,最后才加 Samba 密码。颠倒这个顺序,是新手最容易制造 255 的方式之一。

sudo groupadd -r smbgroup sudo useradd -r -M -s /usr/sbin/nologin -G smbgroup smbuser sudo mkdir -p /srv/share sudo chown -R root:smbgroup /srv/share sudo chmod 2775 /srv/share sudo smbpasswd -a smbuser sudo pdbedit -L

useradd那几个参数不是随便写的。-r建的是系统用户,UID 落在 1000 以下的区间,不会在登录界面出现;-M表示不建家目录,因为 Samba 用户不需要登录 shell;-s /usr/sbin/nologin明确禁止交互登录,这是安全上的基本要求。smbpasswd -a才是真正往passdb.tdb里写 Samba 独立密码的动作,它和 Linux 系统密码是分开的两套,这一点务必记住——很多人改完passwd发现 SMB 登录密码没变,原因就在这里。

pdbedit -L应该输出smbuser:1001:这样的行,冒号后面那一串是 SID 尾部数字。如果这条命令报Unable to open passdb database或者干脆没输出,说明密码库这一步就出问题了,此时去systemctl start smbd大概率拿到 255。所以我的做法是:在启动服务之前,先用testparmpdbedit -L各验一遍,两个都通过再去起服务,能省掉大量来回。

最后合起来验证:

testparm -s sudo systemctl restart smbd nmbd systemctl status smbd --no-pager -l

到这里如果 status 显示active (running),那就一切正常。如果显示 255,进入下一章的排查链路。

3. 定位 error255 的完整排查链路

3.1 第一现场:journalctl 与 /var/log/samba 日志怎么读

排 255,第一件事永远是看 journal,而不是去网上搜“samba error255 解决方法”然后一条条试。

systemctl status smbd --no-pager -l journalctl -u smbd -b --no-pager | tail -60

-b限定本次启动周期,--no-pager避免分页器挡住输出,tail -60是因为关键信息通常就在末尾几十行里。如果你想让 journal 把每条日志的说明和可能的建议都展开,用:

journalctl -xeu smbd

这里的-x会附带解释文本,-e跳到末尾。读完 journal 还不够,/var/log/samba/下的文件才是 smbd 自己的日志,尤其是log.smbd

ls -l /var/log/samba/ sudo tail -80 /var/log/samba/log.smbd

这里有个常见现象:/var/log/samba/里可能只有一个空的log.smbd,什么内容都没有,而 journal 里也只有那两行 systemd 的报错。这说明 smbd 在人还没来得及写日志的时候就已经退出了,属于“极早期失败”。这种情况十有八九是路径问题——log file指定的目录不可写,或者smbd -b里的LOGFILEBASE指向了别的地方。

smbd -b | grep -E 'CONFIGFILE|LOCKDIR|STATEDIR|PRIVATE_DIR|LOGFILEBASE|PIDDIR'

这条命令会把编译期固化进去的路径全列出来。把输出和ls -ld的实际目录状态逐一对照,谁不存在、谁权限不对,一眼就能看出来。我遇到过最离谱的一个案例:PIDDIR指向/var/run/samba,而/var/run是个 tmpfs,重启后被清空,开机自启的 smbd 因为建不了 PID 目录直接 255,手动systemctl start却能起来——因为手动启动时目录已经被上一次的某个操作创建过了。这种“开机自启失败、手动启动成功”的时序型 255,用journalctl -b对照两次的日志差异就能锁定。

3.2 第二现场:testparm 与前台调试模式

testparm -s是最基础的语法校验,但很多人只看它有没有报错,忽略了一个细节:它输出的内容里,如果有Unknown parameter警告,未必是致命问题,但如果有ERROR字样,就必须处理

testparm -s testparm -v | grep -iE 'error|unknown|ignored'

-v会输出所有参数的当前取值,包括默认值。我曾经靠这条命令发现有人把server min protocol设成了NT1,同时又在另一处写了冲突的client min protocol,两者在 4.11 里会触发初始化逻辑异常。这类冲突-s是不报的,只有-v展开才看得见。

真正定位极早期 255 的杀器是前台调试模式:

sudo systemctl stop smbd sudo smbd -i -d 3 -s /etc/samba/smb.conf

-i表示前台运行、不 fork 到后台,-d 3是调试级别 3。区别在于:通过 systemd 启动时,错误只留个退出码给你;前台跑的时候,错误信息直接打在终端上,包括它试图打开哪个文件失败、errno 是多少。我的经验是把-d调到 3 就够,调到 10 会刷屏,反而难找重点。实测下来,90% 的 255 在前台模式下会在 10 秒内打出根因。

如果前台模式输出的信息仍然很含糊,比如只显示smbd version 4.11.6 started然后直接退,那就上 strace:

sudo strace -f -tt -o /tmp/smbd.strace smbd -i -d 1 grep -nE 'EACCES|ENOENT|EPERM|ENOTDIR' /tmp/smbd.strace | head -40

strace会把所有系统调用记录下来,EACCES是权限不足,ENOENT是路径不存在,EPERM是操作被禁止。这三个只要出现,基本就是答案。这个方法有点重,但在“日志什么都不说”的极端情况下是唯一能挖到底的手段。

3.3 第三现场:接口绑定、端口占用与 AppArmor

前两现场都排查完还没结果,就要往系统和网络层面看。

ss -lntp | grep -E ':445|:139' ip -brief addr show

第一条看 445 和 139 端口有没有被别的进程占着。正常情况下这两个端口应该空闲,如果显示被某个陌生的 smbd、或者 Docker 的容器进程占着,那新起的 smbd 绑定失败会退出。我见过在虚拟化环境里,宿主机也跑了 Samba,NAT 模式下端口映射混乱导致的绑定失败。

第二条看本机实际的接口名。Ubuntu 20.04 的网卡名几乎不可能是eth0,桌面版通常是ens33enp0s3,笔记本上还可能是wlp3s0。如果你的smb.conf里写了:

interfaces = lo eth0 bind interfaces only = yes

那 smbd 会找不到eth0,绑定不上任何接口。修复方式有两种:把这行改成实际接口名,或者干脆删掉这两个参数。我通常建议内网环境直接删掉,因为默认行为就是监听所有接口,除非你有明确的多网卡隔离需求,否则这两个参数带来的只有麻烦。

AppArmor 是 Ubuntu 特有的一层,Samba 自带策略文件/etc/apparmor.d/usr.sbin.smbd。如果策略加载异常,smbd 访问某些路径时会被内核拦掉,表现就是 255 或者能启动但读不到文件。

aa-status | grep -i smbd sudo journalctl -k | grep -i apparmor | tail -20

aa-status会列出当前处于 enforce 状态的 profile。如果在journalctl -k里看到类似apparmor="DENIED" operation="open" profile="/usr/sbin/smbd"的记录,那问题就在这。处理方法是重新加载策略:

sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.smbd sudo systemctl restart smbd

如果重新加载还是被拦,说明你的共享目录不在策略允许的路径列表里。我个人更推荐的做法是把共享目录放在/srv,因为 Ubuntu 默认策略里/srv/**是允许的,而放/data/mnt/xxx这类自定义路径就常常要额外改策略。这是我在被 AppArmor 坑了两次之后固定下来的习惯。

4. 五类真实案例的逐条复现与修复

4.1 配置语法与废弃参数导致的启动即退

这类案例的特征是:改完配置立刻起不来,之前是好的。有一次同事在[global]里加了一行security = share,因为他照着 2013 年的一篇博客配游客共享。这条参数在 Samba 4.0 之后就被移除了,4.11 里 Samba 的处理方式比较特殊——它在解析阶段把它当成未知参数记一条警告,但在某些组合条件下会触发参数校验失败,直接返回 255。

复现很简单,在那个最小配置的[global]段里加一行:

security = share

然后sudo smbd -i -d 3,你会看到类似lp_load_ex: Ignoring unknown parameter "security"的提示,接着进程退出。修复就是删掉它,用现代写法实现游客访问:

[public] path = /srv/public guest ok = yes read only = yes force user = nobody

另一个高频踩坑是netbios name超长。比如把主机名改成了ubuntu-dev-server-01,一共 19 个字符,超过 15 字符上限。此时默认继承主机名的 netbios name 就不合法了。

hostname hostname | wc -c

修复办法是显式指定一个短名:

netbios name = UBSRV

同时值得一并检查的是workgroup。如果它设成了一个含空格或者非 ASCII 字符的名字,也可能在名称解析阶段出问题。我自己定下的规矩是:workgroup 和 netbios name 只用大写字母、数字和短横线,长度都控制在 15 以内

还有一类比较隐蔽的是include指令指向不存在的文件:

include = /etc/samba/conf.d/custom.conf

如果这个目录不存在,或者文件被删了,部分场景下 smbd 会直接放弃启动。排查时用grep -rn 'include' /etc/samba/smb.conf把所有 include 找出来,逐个确认文件存在。

4.2 目录、权限与服务账户不一致

这类是我遇到最多的。典型故事是这样的:为了图方便,把共享目录设在用户家目录下,或者用chmod -R 777一把梭,然后过几天发现问题。先看权限不对的版本:

sudo chown -R someuser:someuser /var/lib/samba/private

一旦这个目录的属主不是 root,/var/lib/samba/private下存放的secrets.tdbpassdb.tdb就可能读不了,smbd 启动时打不开密码库,直接 255。修复:

sudo chown -R root:root /var/lib/samba/private sudo chmod 0700 /var/lib/samba/private sudo systemctl restart smbd

这里 0700 是有讲究的,不是随手的值。/var/lib/samba/private里存放的是密码数据库的鉴权信息,权限必须严格限制为 root 独占读写执行,其他任何位都不能开放。同理/var/lib/samba/winbindd_privileged通常要求是 0750 且属组为winbindd_priv。这些值在 Ubuntu 的包安装脚本里本来会设好,一旦你手工动过目录或者用chmod -R覆盖过,就会被破坏。

第二个变体是共享目录的路径根本不存在。配置文件里写了path = /srv/share,但/srv/share没建。Samba 在启动时是否检查这个路径,取决于版本和具体配置项,但 4.11 在[share]段被实际加载时有概率直接失败。所以共享目录一定要先建好

sudo mkdir -p /srv/share ls -ld /srv/share

第三个变体更绕:目录存在、权限也放开了,但SELinux 或者文件系统层面的 ACL拦住了。Ubuntu 默认不用 SELinux,但如果你从 CentOS 那边迁移过来习惯性装了selinux-utils,就可能有策略残留。用getenforce确认一下是DisabledPermissive就不会有影响。至于 ACL,用getfacl /srv/share看一眼,如果输出里有一大堆# file:开头的细粒度规则,也要留意是不是有mask::---这种把所有权限都掐掉的设置。

关于共享目录放哪里,我的选择顺序是/srv优先,其次/home/samba,坚决不放/media/mnt下的挂载点。原因很实在:挂载点在开机早期可能还没挂上,而 smbd 又设了开机自启,两者抢时间,就会周期性出 255。

4.3 网络接口与 netbios name 冲突

前面提过interfaces+bind interfaces only的组合,这里给一个完整的复现和修复过程。假设你的机器接口是ens33,配置里写的是:

interfaces = lo eth0 bind interfaces only = yes

前台调试会看到类似Unable to find interface eth0然后退出。修复有两个方向。方向一是改成实际接口名:

ip -brief addr show | awk '{print $1}'

拿到真实名字后改成interfaces = lo ens33。方向二是直接删掉这两行。我强烈建议后者,除非你明确需要 Samba 只在一个接口上提供服务——比如一台机器同时接内网和外网,只允许内网访问共享。这种情况下正确写法还得配合hosts allow

interfaces = lo ens33 bind interfaces only = yes hosts allow = 192.168.1.0/24 127.0.0.1 hosts deny = 0.0.0.0/0

注意hosts deny = 0.0.0.0/0作为兜底,这样即使接口绑定出问题,也不会意外把共享暴露出去。这个组合我在多网卡服务器上用过多次,逻辑上是“先只监听指定接口,再在指定接口上只放行指定网段”,两层过滤。

另一个偶发场景是虚拟机克隆。用 VMware 或者 VirtualBox 克隆出来的 Ubuntu,主机名和网卡 MAC 都变了,但smb.conf里还留着旧机器的netbios nameinterfaces,开机后 nmbd 尝试注册一个已经被别的机器占用的名字,冲突之下可能连带影响 smbd 的启动流程。判断方法是看 nmbd 的日志:

sudo tail -50 /var/log/samba/log.nmbd

如果看到name conflict或者registering name ... failed,就改掉netbios name。这一步在克隆环境里我几乎是必做的。

4.4 TDB 数据库损坏与状态残留

这一类的触发条件通常是断电、强制关机、或者容器里直接kill -9掉 smbd。TDB 是 Samba 自己实现的一种键值数据库格式,它不像 MySQL 那样有完善的事务日志,写入过程中被打断就有概率留下损坏文件。表现是:

sudo smbd -i -d 3

输出里出现tdb(/var/lib/samba/private/passdb.tdb): tdb_open failed或者Corrupt database。确认损坏可以用 tdb 工具:

sudo tdbbackup -v /var/lib/samba/private/passdb.tdb sudo tdbdump /var/lib/samba/private/passdb.tdb | head

tdbbackup会尝试做一个备份并校验,如果它报错,基本就是坏了。修复思路是“先备份,再重建,最后恢复用户”:

sudo systemctl stop smbd nmbd winbind sudo mv /var/lib/samba/private/passdb.tdb /root/passdb.tdb.broken sudo systemctl start smbd sudo smbpasswd -a smbuser sudo pdbedit -L

把损坏文件移走之后,smbd 会在启动时自动创建一个全新的空passdb.tdb。代价是之前的所有 Samba 用户都要重新smbpasswd -a加一遍。所以如果你手里有用户清单,重建工作就是几条命令的事。这也是我为什么坚持在笔记里记录所有 Samba 用户名——真到重建那天,能省半小时。

secrets.tdb损坏的修复方式类似,但要注意它里面存的是机器账户密钥、域信任等信息,独立服务器场景下重建影响不大,域环境里就要谨慎,最好先从好的备份恢复。registry.tdb相对独立,删掉重建一般也不影响共享功能。

还有一个容易被忽视的状态残留是 PID 文件。如果 smbd 被强杀,/run/samba/smbd.pid可能残留,新进程启动时看到 PID 存在会尝试检查旧进程是否活着,逻辑出错也会退。清理方式:

sudo rm -f /run/samba/*.pid sudo systemctl restart smbd

注意:执行任何删除 TDB 或 PID 的操作前,一定先 stop 掉 smbd、nmbd、winbind 三个服务,否则运行中的进程会持有文件句柄,删了也不生效,甚至让状态更乱。

4.5 打印服务、容器与无关依赖的连带失败

Samba 默认会加载打印相关模块,如果你机器上没装 CUPS 或者cups服务状态异常,某些配置组合下 smbd 启动阶段会因为打印子系统初始化失败而退出。表现是日志里出现cups关键字。

systemctl status cups --no-pager dpkg -l | grep -i cups

如果你的共享里根本不需要打印功能,最干净的做法是在[global]里显式关掉:

load printers = no printing = bsd printcap name = /dev/null disable spoolss = yes

这四行我几乎加在每一份不需要打印的配置里,能省掉一大堆无谓的系统依赖检查。实测下来,服务启动速度也快了一点。

容器环境是另一个高发区。在 Docker 里跑 Samba,常见的 255 原因是/run/samba目录在容器重建后没被创建,以及容器的网络命名空间让interfaces参数失效。我的处理方式是在 entrypoint 或者 systemd 前置脚本里固定加一段:

mkdir -p /run/samba /var/log/samba /var/lib/samba/private chown root:root /var/lib/samba/private chmod 0700 /var/lib/samba/private

顺序是先建目录、再设属主、最后设权限。这里顺序错了(比如先 chmod 后 chown),权限位有可能被 chown 重置掉一部分,尤其是在挂载了宿主机目录的场景里。

顺便说一下和虚拟化相关的网络:VMware 的 NAT 模式下,虚拟机的地址是 192.168.x.x 的私有段,主机访问虚拟机的 Samba 需要做端口转发或者用桥接模式。这跟 255 本身没关系,但会让你在“服务已经起来”的情况下误以为是启动失败。判断方法很简单:systemctl status smbd如果是绿色 active,就别再折腾服务了,去看网络。

5. 常见问题速查表与避坑心得

5.1 error255 排查速查表

把上面所有分支整理成一张表,遇到问题按行匹配,能省掉大量翻日志的时间。

症状线索关键判据命令大概率根因修复动作
journal 只有两行,log.smbd 为空smbd -b | grep LOGFILEBASE日志目录不存在或不可写建目录并 chown root:root
前台模式报Unable to find interfaceip -brief addr showinterfaces 参数写了 eth0改实际网卡名或删该参数
tdb_open failed/Corrupttdbbackup -v <file>TDB 数据库损坏移走损坏文件后重建用户
开机自启失败、手动启动成功journalctl -b -u smbd/run/samba 时序或 tmpfs 清空加 ExecStartPre 建目录
Ignoring unknown parameter后退出testparm -s用了已废弃参数删除并按新语法改写
apparmor="DENIED"内核日志journalctl -k | grep apparmorAppArmor 拦路径重载策略或改到 /srv
端口绑定失败ss -lntp | grep ':445'445 被占用找出占用进程并停掉
pdbedit -L 报错或空输出pdbedit -L密码库不可用重建 passdb.tdb
克隆虚拟机后必现hostname长度netbios name 冲突或超长显式设为短名

这张表我贴在自己服务器的备忘里,两年下来覆盖了绝大部分情况。剩下的少数派,就靠strace或者干脆把配置降级到最小可用版本再逐步加回去定位。

5.2 我踩过的坑与固化下来的操作习惯

第一条习惯:改配置之前永远先备份,改完之后永远先testparm -s再重启服务。这条听起来像废话,但我至少三次因为跳过testparm直接systemctl restart,把一台好机器弄成了 255 状态,然后花更多时间去回滚。testparm花 1 秒,重启加排查花 20 分钟,账很好算。

第二条习惯:共享目录放/srv下,不用中文路径,不用带空格的目录名。我遇到过共享目录名带空格导致path解析异常的情况,虽然理论上引号能兜住,但没必要给自己找麻烦。AppArmor 那边也是/srv最省事。

第三条习惯:给每个共享配独立的系统组,用 setgid 目录而不是 777chmod 777是新手最容易犯的错,它意味着机器上任何用户都能读写共享内容,而且新建文件的属主不受控,后续排查权限问题时完全没有规律可循。用2775+force group的组合,权限模型清晰,出问题也容易定位。

第四条习惯:先看 journal,再看 smbd 自己的日志,最后才看配置文件。顺序反过来就会出现“改了十遍配置问题依旧”的情况,因为你根本没确认问题在配置层。日志是唯一权威的事实来源。

第五条习惯:在克隆或者迁移虚拟机之前,先systemctl stop smbd nmbd,让服务正常退出,避免状态文件写入一半被打断。这个动作花 2 秒,能避免前面说的 TDB 损坏那一整类问题。

最后再分享一个特别实用的调试技巧:当你不确定某个参数是不是罪魁祸首时,把smb.conf临时替换成只有[global]加一个简单共享的最小版本,跑一次smbd -i -d 3。如果最小版本能起来,就说明问题在你自己加的参数里;如果最小版本也起不来,那就是环境层面的问题,直接跳到第 3 章的环境排查。这个“二分法”能帮你把问题域一刀切开,比逐行注释掉配置要快得多。

还有一点关于密码同步的:如果你希望 Samba 密码和 Linux 系统密码保持一致,unix password sync = yes配合pam password change = yes这条链路是必要的,但它要求passwd program里的路径必须是真实的/usr/bin/passwd。我见过有人把这行改成了一个自定义脚本,脚本退出码非 0,结果smbpasswd操作失败,进而引发密码库写入异常最终演变成 255。所以这类联动配置,在没搞懂之前不要动它。

整套流程走下来,error255 其实并没有想象中那么玄。它的本质是一个“初始化未完成就退出”的信号,而 Ubuntu 20.04 上能让 smbd 初始化失败的因素就那么几类:路径没了、权限被改了、接口找不到、数据库坏了、参数废弃了。把这五条对应到具体的检查和修复命令上,剩下的就是耐心地按顺序排一遍。我自己现在的习惯是遇到 255 先跑一遍速查表的前三行,八成问题在五分钟内就能收工。

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

Sanity 仓库实战:playwright-cli 浏览器自动化命令行完全指南

Sanity 仓库实战&#xff1a;playwright-cli 浏览器自动化命令行完全指南 【免费下载链接】sanity Sanity Studio – Rapidly configure content workspaces powered by structured content 项目地址: https://gitcode.com/GitHub_Trending/sa/sanity 本篇技术指南以 .a…

作者头像 李华
网站建设 2026/9/17 8:13:02

5G NOMA用户配对MATLAB仿真全解析:SIC与配对算法

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

作者头像 李华
网站建设 2026/9/17 8:12:47

GLSL内置函数优化技巧与实战应用

1. GLSL内置函数概述GLSL&#xff08;OpenGL Shading Language&#xff09;作为图形编程的核心语言&#xff0c;其内置函数库是每位图形开发者必须掌握的利器。这些经过高度优化的函数涵盖了从数学运算到纹理采样的各个领域&#xff0c;直接决定了着色器的性能和表现力。在实际…

作者头像 李华
网站建设 2026/9/17 8:11:50

拓扑排序本质:从家谱树到依赖调度的建模思维

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

作者头像 李华
网站建设 2026/9/17 8:08:49

如何高效利用上万套源码资源提升开发效率

1. 项目背景与价值解析在软件开发领域&#xff0c;源码资源库的建设与维护一直是个经久不衰的话题。我从业十余年间&#xff0c;亲眼见证过无数开发者从零开始搭建项目时四处寻找参考代码的窘境&#xff0c;也参与过多个大型企业的内部代码资产管理系统建设。这个标题中提到的&…

作者头像 李华
网站建设 2026/9/17 8:08:15

Rust版本发布模型与工具链实战指南

1. Rust 版本发布模型解析Rust 语言的版本发布机制是其工程化设计的典范之作。作为一门系统级编程语言&#xff0c;Rust 在保持稳定性的同时&#xff0c;又需要不断引入创新特性&#xff0c;这种平衡通过精心设计的"火车模型"得以实现。1.1 三通道发布机制详解Rust 采…

作者头像 李华