199 lines
4.8 KiB
Bash
199 lines
4.8 KiB
Bash
#!/bin/bash
|
||
|
||
# 自动以 root 权限运行
|
||
if [ "$EUID" -ne 0 ]; then
|
||
echo "需要 root 权限,正在提权..."
|
||
exec sudo bash "$0" "$@"
|
||
fi
|
||
|
||
# 配置区
|
||
APP_NAME="lj360_camera"
|
||
WORK_DIR="/home/ztl/LJ360"
|
||
PYTHON_SCRIPT="web.py"
|
||
USER="ztl"
|
||
|
||
SYSTEMD_SERVICE_FILE="/etc/systemd/system/${APP_NAME}.service"
|
||
SCRIPT_PATH="$WORK_DIR/bash/camera_manager.sh"
|
||
|
||
# 日志文件
|
||
LOG_FILE="$WORK_DIR/${APP_NAME}_keepalive.log"
|
||
# logrotate 配置文件路径
|
||
LOGROTATE_CONF="/etc/logrotate.d/${APP_NAME}"
|
||
|
||
# 1. 配置 logrotate (限制日志大小为 10K)
|
||
setup_logrotate() {
|
||
cat > "$LOGROTATE_CONF" <<EOF
|
||
$LOG_FILE {
|
||
size 10k
|
||
rotate 3
|
||
compress
|
||
delaycompress
|
||
missingok
|
||
notifempty
|
||
copytruncate
|
||
create 644 $USER $USER
|
||
}
|
||
EOF
|
||
echo "✅ 日志轮替规则已配置 (限制 10k)"
|
||
}
|
||
|
||
# 2. 启动主程序(带保活循环)
|
||
start_app() {
|
||
# 确保 logrotate 配置存在
|
||
setup_logrotate
|
||
|
||
cd "$WORK_DIR" || exit 1
|
||
echo "$(date): 启动 $APP_NAME 应用..." >> "$LOG_FILE"
|
||
while true; do
|
||
if sudo -u ztl python3 "$PYTHON_SCRIPT"; then
|
||
echo "$(date): 程序正常退出,即将重启..." >> "$LOG_FILE"
|
||
else
|
||
echo "$(date): 程序异常退出(代码 $?),5秒后重启..." >> "$LOG_FILE"
|
||
fi
|
||
|
||
# 强制运行 logrotate 检查大小
|
||
# 注意:虽然 logrotate 通常由 cron 每天运行,但这里手动调用以确保实时性
|
||
logrotate -f "$LOGROTATE_CONF" 2>/dev/null
|
||
|
||
sleep 5
|
||
done
|
||
}
|
||
|
||
# 3. 创建 systemd 服务文件
|
||
create_systemd_service() {
|
||
cat > "$SYSTEMD_SERVICE_FILE" <<EOF
|
||
[Unit]
|
||
Description=LJ360 Four-Camera BirdView System
|
||
After=multi-user.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=$USER
|
||
Group=$USER
|
||
WorkingDirectory=$WORK_DIR
|
||
ExecStart=/bin/bash $SCRIPT_PATH run
|
||
Restart=always
|
||
RestartSec=5
|
||
StandardOutput=append:$LOG_FILE
|
||
StandardError=append:$LOG_FILE
|
||
Environment=HOME=/home/ztl
|
||
Environment=DISPLAY=:0
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
chmod 644 "$SYSTEMD_SERVICE_FILE"
|
||
systemctl daemon-reload
|
||
echo "✅ systemd 服务已创建: $APP_NAME"
|
||
}
|
||
|
||
# 4. 启用开机自启
|
||
enable_autostart() {
|
||
# 确保 ztl 用户有串口和摄像头权限
|
||
usermod -aG dialout ztl 2>/dev/null
|
||
usermod -aG video ztl 2>/dev/null
|
||
|
||
# 确保日志文件归属正确
|
||
touch "$LOG_FILE"
|
||
chown ztl:ztl "$LOG_FILE"
|
||
|
||
create_systemd_service
|
||
systemctl enable "$APP_NAME".service
|
||
systemctl start "$APP_NAME".service
|
||
echo "✅ 已启用开机自启,并以 ztl 用户启动服务"
|
||
}
|
||
|
||
# 5. 禁用开机自启
|
||
disable_autostart() {
|
||
systemctl stop "$APP_NAME".service 2>/dev/null
|
||
systemctl disable "$APP_NAME".service 2>/dev/null
|
||
rm -f "$SYSTEMD_SERVICE_FILE"
|
||
rm -f "$LOGROTATE_CONF" # 同时删除 logrotate 配置
|
||
systemctl daemon-reload
|
||
echo "✅ 已禁用开机自启,并移除服务"
|
||
}
|
||
|
||
# 6. 显示状态
|
||
show_status() {
|
||
if systemctl is-active --quiet "$APP_NAME".service; then
|
||
echo "🟢 服务正在运行(开机自启已启用)"
|
||
systemctl status "$APP_NAME".service --no-pager
|
||
elif [ -f "$SYSTEMD_SERVICE_FILE" ]; then
|
||
echo "🟠 服务已安装但未运行"
|
||
else
|
||
echo "🔴 服务未安装(开机自启已关闭)"
|
||
fi
|
||
}
|
||
|
||
# 7. 主菜单
|
||
show_menu() {
|
||
echo "========================================"
|
||
echo " LJ360 摄像头系统管理工具"
|
||
echo "========================================"
|
||
show_status
|
||
echo ""
|
||
echo "请选择操作:"
|
||
echo " 1) 启用开机自启并启动服务(ztl 用户)"
|
||
echo " 2) 禁用开机自启并停止服务"
|
||
echo " 3) 仅手动运行一次(不保活)"
|
||
echo " 4) 查看日志"
|
||
echo " 0) 退出"
|
||
echo -n "请输入编号 (0-4): "
|
||
}
|
||
|
||
# 处理命令行参数(用于 systemd 调用)
|
||
if [ "$1" = "run" ]; then
|
||
start_app
|
||
exit 0
|
||
fi
|
||
|
||
if [ "$1" = "enable_autostart" ]; then
|
||
enable_autostart
|
||
exit 0
|
||
fi
|
||
|
||
if [ "$1" = "disable_autostart" ]; then
|
||
disable_autostart
|
||
exit 0
|
||
fi
|
||
|
||
if [ "$1" = "status" ]; then
|
||
show_status
|
||
exit 0
|
||
fi
|
||
|
||
|
||
# 交互式主程序
|
||
while true; do
|
||
show_menu
|
||
read -r choice
|
||
|
||
case $choice in
|
||
1)
|
||
enable_autostart
|
||
;;
|
||
2)
|
||
disable_autostart
|
||
;;
|
||
3)
|
||
echo "🚀 手动运行一次(Ctrl+C 可退出)..."
|
||
cd "$WORK_DIR" && sudo -u ztl python3 "$PYTHON_SCRIPT"
|
||
;;
|
||
4)
|
||
echo "📄 最近日志(最后 20 行):"
|
||
tail -n 20 "$LOG_FILE"
|
||
echo -n "按回车返回菜单..."
|
||
read -r
|
||
;;
|
||
0)
|
||
echo "退出。"
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "❌ 无效选项,请输入 0-4"
|
||
sleep 1
|
||
;;
|
||
esac
|
||
echo ""
|
||
done |