1. Ubuntu 系统下实现开机自启脚本的完整指南
作为一名在Linux系统管理领域摸爬滚打多年的老运维,我经常需要配置各种服务的开机自启。今天要分享的是如何在Ubuntu系统中通过systemd服务实现脚本的可靠自启动,这个方案我已经在生产环境稳定运行了3年多,处理过各种复杂场景。
1.1 为什么选择systemd方案
在Linux系统中实现开机自启有多种方式,比如rc.local、crontab或者upstart,但我强烈推荐使用systemd,原因有三:
- 可靠性最高:systemd是Ubuntu 16.04及以后版本的默认初始化系统,直接由内核启动,不受用户登录状态影响
- 功能最全:支持服务依赖、自动重启、资源限制等高级功能
- 管理方便:统一的systemctl命令可以查看状态、启停服务和查看日志
特别是当你的脚本需要激活conda环境时,systemd的bash -c方式能完美解决环境加载问题,这是其他方案难以实现的。
2. 完整实施步骤详解
2.1 准备可执行脚本
首先确保你的run1.sh脚本具备以下特征:
bash复制#!/bin/bash
# 激活conda环境
source /path/to/conda/bin/activate your_env
# 后台运行Python脚本并输出日志
nohup python pub.py > pub.log 2>&1 &
nohup python machine_data.py > machine_data.log 2>&1 &
nohup python messenger.py > messenger.log 2>&1 &
关键操作:
bash复制chmod +x /data/robot_arm/robot_information_platform/run1.sh
注意:脚本第一行必须包含
#!/bin/bash,否则可能无法正确执行。所有路径建议使用绝对路径,避免因工作目录变化导致的问题。
2.2 创建systemd服务文件
服务文件存放在/etc/systemd/system/目录下,命名规范为服务名.service。以下是经过我优化后的配置:
ini复制[Unit]
Description=Robot Information Platform Service
After=network.target postgresql.service # 增加了数据库服务依赖
Requires=network-online.target # 确保网络完全就绪
[Service]
Type=forking # 更适合后台进程
User=rykj
Group=rykj
WorkingDirectory=/data/robot_arm/robot_information_platform
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/data/robot_arm/miniconda3/bin"
ExecStart=/bin/bash -c "source /data/robot_arm/robot_information_platform/run1.sh"
Restart=on-failure
RestartSec=30s # 延长重启间隔避免频繁重启
StartLimitInterval=60s # 60秒内最多重启3次
StartLimitBurst=3
[Install]
WantedBy=multi-user.target
几个关键改进点:
- 增加了
postgresql.service依赖,确保数据库先启动 - 设置
Type=forking更符合后台进程特性 - 显式设置了PATH环境变量,包含conda路径
- 增加了启动频率限制,防止服务崩溃时无限重启
2.3 服务管理实操
加载并启用服务:
bash复制sudo systemctl daemon-reload
sudo systemctl enable --now robot-platform.service # 一次性完成启用和启动
验证服务状态:
bash复制sudo systemctl status robot-platform.service
查看详细日志:
bash复制journalctl -u robot-platform.service -b --no-pager -n 50
实用技巧:使用
--no-pager -n 50可以避免分页显示,直接输出最近50行日志
3. 高级配置与疑难排查
3.1 环境变量处理
当脚本需要特定环境变量时,推荐三种方式:
- 在服务文件中设置:
ini复制Environment="PYTHONPATH=/path/to/libs"
Environment="DB_HOST=127.0.0.1"
- 使用EnvironmentFile:
ini复制EnvironmentFile=/etc/robot-platform.env
- 在脚本中显式设置:
bash复制export PYTHONPATH=/path/to/libs
3.2 资源限制配置
对于需要控制资源的服务,可以添加:
ini复制[Service]
MemoryLimit=512M
CPUQuota=80%
LimitNOFILE=65535
3.3 常见问题排查
问题1:conda环境未正确加载
- 检查
Environment中的PATH是否包含conda路径 - 确认
source命令使用的是conda的绝对路径 - 在脚本中添加
which python验证环境
问题2:权限不足
- 确保User有脚本目录的读写权限
- 检查日志文件是否可写入
- 使用
sudo -u rykj whoami测试用户切换
问题3:服务启动超时
- 增加TimeoutStartSec:
ini复制[Service]
TimeoutStartSec=300
4. 日志管理最佳实践
4.1 多级日志配置
建议采用分层日志方案:
- Systemd日志:
journalctl -u service-name - 服务标准输出:
StandardOutput=syslog - 应用日志:Python脚本自身的日志系统
4.2 日志轮转配置
创建日志轮转配置/etc/logrotate.d/robot-platform:
code复制/data/robot_arm/robot_information_platform/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 rykj rykj
}
4.3 实时日志监控
使用multitail工具同时监控多个日志:
bash复制sudo apt install multitail
multitail -cS python pub.log -cS python machine_data.log -cS python messenger.log
5. 系统集成与扩展
5.1 与PostgreSQL集成
当服务依赖PostgreSQL时,确保:
- 服务配置中添加:
ini复制[Unit]
After=postgresql.service
Requires=postgresql.service
- 在脚本中添加数据库连接测试:
bash复制until pg_isready -h localhost -p 5432; do
sleep 1
done
5.2 多服务协同
对于复杂系统,可以创建多个服务文件并通过依赖关系管理启动顺序:
ini复制[Unit]
After=service1.service service2.service
Requires=service1.service service2.service
5.3 服务监控与告警
配置systemd服务监控:
bash复制# 设置邮件告警
sudo apt install mailutils
echo 'OnFailure=mail-alert@%n.service' | sudo tee -a /etc/systemd/system.conf
创建告警服务/etc/systemd/system/mail-alert@.service:
ini复制[Unit]
Description=Send mail when %i fails
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'echo "Service %i failed on $(hostname)" | mail -s "Service Failure Alert" admin@example.com'
这套方案在我管理的20多台Ubuntu服务器上稳定运行,处理过各种生产环境问题。最关键的几点经验是:一定要配置合理的重启策略、确保环境变量完整、做好日志管理。当遇到问题时,journalctl永远是第一个要查看的地方。