Systemd 服务

在 Linux 服务器上,systemd 是管理服务的标准方式。将 Gin 应用配置为 systemd 服务,可以实现开机自启、自动重启等功能。

服务配置文件

创建 /etc/systemd/system/myapp.service

[Unit]
Description=Gin Web Application
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/main
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=myapp
Environment=GIN_MODE=release
Environment=PORT=8080

[Install]
WantedBy=multi-user.target

环境变量文件

使用环境变量文件管理配置:

/opt/myapp/.env

GIN_MODE=release
PORT=8080
DB_HOST=localhost
DB_PORT=3306
DB_USER=myuser
DB_PASSWORD=mypassword
DB_NAME=myapp

服务配置

[Service]
EnvironmentFile=/opt/myapp/.env
ExecStart=/opt/myapp/main

服务管理命令

# 重新加载配置
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start myapp

# 停止服务
sudo systemctl stop myapp

# 重启服务
sudo systemctl restart myapp

# 查看状态
sudo systemctl status myapp

# 开机自启
sudo systemctl enable myapp

# 取消开机自启
sudo systemctl disable myapp

# 查看日志
sudo journalctl -u myapp -f

完整配置示例

[Unit]
Description=My Gin Application
Documentation=https://example.com/docs
After=network.target network-online.target
Wants=network-online.target

[Service]
Type=notify
User=app
Group=app
WorkingDirectory=/opt/myapp

ExecStart=/opt/myapp/main
ExecReload=/bin/kill -HUP $MAINPID

Restart=on-failure
RestartSec=5s

LimitNOFILE=65536
LimitNPROC=4096

PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
ReadWritePaths=/opt/myapp/logs

StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

Environment=GIN_MODE=release
EnvironmentFile=/opt/myapp/config.env

TimeoutStopSec=30
TimeoutStartSec=10

[Install]
WantedBy=multi-user.target

通知支持

让 systemd 知道应用已启动:

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/coreos/go-systemd/daemon"
)

func main() {
    r := gin.Default()
    
    r.GET("/", func(c *gin.Context) {
        c.String(200, "Hello")
    })
    
    go func() {
        if _, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
            log.Printf("Failed to notify systemd: %v", err)
        }
    }()
    
    r.Run(":8080")
}

服务配置使用 Type=notify

[Service]
Type=notify
ExecStart=/opt/myapp/main

日志管理

配置日志轮转:

/etc/logrotate.d/myapp

/var/log/myapp/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 app app
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

资源限制

[Service]
LimitNOFILE=65536
LimitNPROC=4096
LimitMEMLOCK=infinity
MemoryMax=1G
CPUQuota=100%

安全加固

[Service]
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
ReadOnlyPaths=/
ReadWritePaths=/opt/myapp/logs /opt/myapp/data
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE

多实例部署

/etc/systemd/system/myapp@.service

[Unit]
Description=My Gin Application - Instance %i
After=network.target

[Service]
Type=simple
User=app
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/main -port %i
Restart=always

[Install]
WantedBy=multi-user.target

启动多个实例:

sudo systemctl start myapp@8080
sudo systemctl start myapp@8081
sudo systemctl start myapp@8082

小结

systemd 是 Linux 上管理 Gin 应用的标准方式。配置服务后可以实现自动重启、开机自启。使用 EnvironmentFile 管理配置,使用 journalctl 查看日志。生产环境建议配置资源限制和安全加固。