systemd服务启动超时默认阈值为90秒,即TimeoutStartSec=90;可通过service文件配置该值或设为0禁用,修改后需执行systemctl daemon-reload生效。

systemd 服务启动超时的默认阈值是多少
systemd 默认对每个服务设置 TimeoutStartSec=90,即从 ExecStart 启动到进入 active (running) 状态,必须在 90 秒内完成,否则标记为失败并终止进程。这个值对数据库、Java 应用、或带初始化逻辑的服务来说常常不够。
常见错误现象:systemctl status myapp.service 显示 failed,日志里有 Timed out waiting for process to start 或 Killed;journalctl -u myapp.service 最后几行往往停在启动命令输出之后、无后续状态变更。
- 可通过
systemctl show myapp.service | grep TimeoutStartSec查看当前生效值 - 修改方式是在 service 文件中添加
TimeoutStartSec=300(单位秒),或设为0表示禁用超时(不推荐生产环境) - 注意:修改后需运行
systemctl daemon-reload才生效,否则systemctl restart不会读取新配置
服务卡在 pre-start 阶段的典型原因
很多服务依赖其他资源就绪才真正启动,比如等待网络接口 up、磁盘挂载完成、或另一个服务 ready。如果没显式声明依赖,systemd 可能并发启动,导致 ExecStart 运行时目标资源尚未可用,进程阻塞在 connect()、open() 或 init 脚本里 sleep 等待逻辑上。
典型表现是日志里没有 Started myapp.service,但能看到 Starting myapp.service... 后长时间无响应,ps aux | grep myapp 可能查不到进程,或只看到 shell 解释器卡在某条命令上。
- 检查
Wants=/After=是否覆盖全部前置依赖,例如网络服务要加After=network-online.target并启用systemctl enable systemd-networkd-wait-online.service - 磁盘依赖应使用
RequiresMountsFor=/data而非简单写After=local-fs.target,后者不保证特定路径已挂载 - 避免在
ExecStartPre中调用可能阻塞的命令(如未加-w的curl、未设 timeout 的nc),这类脚本超时也会触发整体启动失败
Java / Python 类服务启动慢却不报错的陷阱
这类服务常通过 wrapper 脚本启动,ExecStart 启动的是一个 shell 进程,而真正业务进程 fork 在后台。systemd 默认按主进程生命周期判断服务状态,若主进程立即退出(比如脚本里用了 & 或 nohup),它会认为服务已“启动完成”,后续子进程崩溃也不会被感知;反之,若主进程一直不退出但也没发 readiness 信号,systemd 会在 TimeoutStartSec 后杀掉整个 cgroup。
常见错误配置:ExecStart=/opt/app/start.sh & —— 这会导致 systemd 认为主进程瞬间结束,状态变为 inactive,但实际 Java 进程还在跑;或者 ExecStart=java -jar app.jar 没加 Type=simple,而 JVM 启动耗时长,systemd 等不到它“ready”就超时。
- 推荐用
Type=simple(默认)配合前台运行的 Java 命令,确保 JVM 是主进程;若必须后台化,改用Type=forking并正确设置PIDFile= - Python Flask/FastAPI 服务建议加
gunicorn --preload或用waitress-serve,避免首次请求才加载模块拖慢启动 - 所有 wrapper 脚本务必去掉
set -e外的静默错误处理,让失败直接暴露在 stdout/stderr,便于 journalctl 捕获
文件描述符、内存或 SELinux 导致的隐性超时
服务启动过程中若因资源不足无法分配 fd、mmap 失败,或被 SELinux 拦截 open/bind/connect,往往不会打出明确错误,而是卡在系统调用上,最终被 systemd 超时杀死。这类问题在容器外裸机部署时更隐蔽,因为 ulimit 和 SELinux 策略常被忽略。
典型线索:strace -p $(pidof myapp) 显示卡在 openat(AT_FDCWD, "/etc/ssl/certs/ca-certificates.crt", O_RDONLY|O_CLOEXEC) 或 connect(AF_INET, {...}, 16);dmesg | tail 出现 avc: denied;cat /proc/$(pidof myapp)/limits 发现 Max open files 只有 1024。
- 在 service 文件中用
LimitNOFILE=65536和MemoryLimit=2G显式限制并预留余量 - SELinux 下先临时设为 permissive 模式验证是否为此类问题:
sudo setenforce 0,再重启服务;确认后用ausearch -m avc -ts recent | audit2why生成策略 - 避免在
ExecStartPre中执行耗时的证书更新、密钥生成等操作,这些应由部署流程完成,而非每次启动都做
真正难排查的不是超时本身,而是那些不写日志、不返回错误码、只安静卡住的系统级阻塞——它们往往藏在 systemd 的 cgroup 边界之外,需要结合 strace、dmesg 和 /proc/*/stack 综合判断。









