下面的脚本是生产可用,可靠的sh脚本,用于监控 .NET 应用程序并自动重启。
假如你打包发布到Linux的程序名称为MyAspDemo;
推荐打包模式为框架依赖:需要在Linux上安装对应的donet版本;
1.在Linux下新建一个文件,如:
mkdir dotnet-monitor.sh
如上新建了一个名为 dotnet-monitor.sh的脚本文件,打开脚本文件,添加如下内容:
#!/bin/bash
# 配置
APP_NAME="MyAspDemo" # 应用名称
APP_DIR="/opt/services/publish" # 应用所在目录
APP_DLL="MyAspDemo.Api.dll" # 主程序集
DOTNET_CMD="dotnet" # dotnet 命令
LOG_FILE="/var/log/dotnet-monitor.log" # 日志文件
CHECK_INTERVAL=30 # 检查间隔(秒)
MAX_RESTARTS=5 # 最大重启次数(防崩溃循环)
RESTART_COOLDOWN=60 # 重启冷却时间(秒)
# 函数:记录日志
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 函数:检查应用是否在运行
is_running() {
pgrep -f "dotnet.*$APP_DLL" > /dev/null
}
# 函数:启动应用
start_app() {
log "启动应用: $APP_NAME"
cd "$APP_DIR" || { log "无法进入目录: $APP_DIR"; return 1; }
nohup $DOTNET_CMD "$APP_DLL" > /dev/null 2>&1 &
sleep 5 # 等待进程启动
if is_running; then
log "应用已启动"
return 0
else
log "启动失败"
return 1
fi
}
# 函数:停止应用
stop_app() {
log "停止应用: $APP_NAME"
pkill -f "dotnet.*$APP_DLL"
sleep 3
}
# 主循环
restart_count=0
last_restart=$(date +%s)
log "启动,监控: $APP_NAME"
while true; do
if ! is_running; then
log "应用未运行,尝试重启..."
# 检查是否在冷却期内(防频繁重启)
current_time=$(date +%s)
time_since_last=$((current_time - last_restart))
if [ $restart_count -ge $MAX_RESTARTS ] && [ $time_since_last -lt $RESTART_COOLDOWN ]; then
log "重启次数过多,进入冷却期..."
sleep $RESTART_COOLDOWN
restart_count=0
last_restart=$(date +%s)
else
stop_app
if start_app; then
restart_count=$((restart_count + 1))
last_restart=$(date +%s)
else
log "启动失败,等待下次检查..."
fi
fi
else
log "应用正在运行"
fi
sleep $CHECK_INTERVAL
done
2.为刚刚创建的脚本文件添加执行权限:
sudo chmod +x /opt/dotnet-monitor.sh
3.创建systemd service文件,如下:
vi /etc/systemd/system/dotnet-monitor.service
添加如下内容:
[Unit]
Description=DotNet Monitor
After=network.target
[Service]
Type=simple
User=www-admin //自定义名称
WorkingDirectory=/opt
ExecStart=/opt/service/dotnet-monitor.sh //脚本所在目录
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
4.启动服务:
sudo systemctl daemon-reexec
sudo systemctl enable dotnet-monitor.service
sudo systemctl start dotnet-monitor.service
ok
补充:使用过程中,出现了一个问题,我的.NET程序里面有一处地方需要访问第三方的接口,接口是https://域名方式的,然后手动运行没有问题,自启动后,就访问失败,后来考虑可能是自启动环境和手动运行环境的问题;做了些更改,就可以了。
补充如下:
1.保存本地的运行环境:
env > /opt/dotnet-env.conf
2.在service文件里面添加:
# 环境文件
EnvironmentFile=/opt/selfBuildAI/dotnet-env.conf
然后重启服务。
后来发现,其实不需要用sh,只需要使用service也能完成守护的作用,service文件改为:
[Unit]
Description=NET Application
After=network.target
Wants=network.target
[Service]
User=root
#你的程序所在目录
WorkingDirectory=/opt/yourAPP
# 执行命令(换为你自己的app程序名称)
ExecStart=/usr/bin/dotnet YourAPP.Api.dll
# 从用户环境加载环境变量(关键!)
Environment=PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/share/dotnet
Environment=HOME=/opt/selfBuildAI/services
Environment=DOTNET_ROOT=/usr/share/dotnet
Environment=ASPNETCORE_ENVIRONMENT=Production
# 环境文件(你保存的环境文件的路径)
EnvironmentFile=/opt/dotnet-env.conf
# 标准输出重定向到 journal
StandardOutput=journal
StandardError=journal
# 自动重启
Restart=always
RestartSec=20
[Install]
WantedBy=multi-user.target
重启服务后,达到同样的效果。使用sudo systemctl status + service文件名称可以查看服务的运行情况。

457

被折叠的 条评论
为什么被折叠?



