1
This commit is contained in:
BIN
backend/db.sqlite3
Normal file
BIN
backend/db.sqlite3
Normal file
Binary file not shown.
72
backend/dvadmin3_build/README.md
Normal file
72
backend/dvadmin3_build/README.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# dvadmin3-build
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
一款适用于**django-vue3-admin** 编译打包exe、macOS的dmg文件等打包工具。支持加密代码、一键启动项目,无需考虑环境。
|
||||||
|
|
||||||
|
**dvadmin3-build** 是一个方便的工具,用于将**django-vue3-admin**项目编译打包为可执行文件(如exe)或macOS的dmg文件等。它提供了以下好处:
|
||||||
|
|
||||||
|
- 方便的部署:使用**dvadmin3-build**,您无需担心环境依赖和配置问题。您可以将整个项目打包为一个可执行文件或者安装包,方便快速部署在任何支持的操作系统上。
|
||||||
|
|
||||||
|
- 代码加密:**dvadmin3-build** 支持代码加密,可以将您的项目源代码加密为二进制格式,增加代码的安全性和保护知识产权。
|
||||||
|
|
||||||
|
- 一键启动项目:打包后的可执行文件或安装包可以通过简单的双击来启动项目,无需手动设置和配置环境,减少了部署和启动的复杂性。
|
||||||
|
|
||||||
|
- 跨平台支持:**dvadmin3-build** 可以将**django-vue3-admin**项目打包为适用于多个操作系统的可执行文件或安装包,包括Windows、macOS、Ubuntu、中标麒麟等操作系统中。
|
||||||
|
|
||||||
|
- 易于使用:**dvadmin3-build** 提供了简单易懂的命令行界面,使得打包过程更加简便和高效。只需一个简单的命令,即可完成项目的打包。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 功能支持项
|
||||||
|
|
||||||
|
- [ ] 支持平台
|
||||||
|
- [x] Windows
|
||||||
|
- [x] MacOS
|
||||||
|
- [ ] Ubuntu
|
||||||
|
- [ ] 中标麒麟
|
||||||
|
- [ ] 支持功能
|
||||||
|
- [x] 一键启动 dvadmin3
|
||||||
|
- [x] 托盘最小化
|
||||||
|
- [ ] dvadmin 初始化
|
||||||
|
- [ ] 数据库配置
|
||||||
|
- [ ] 端口配置
|
||||||
|
- [ ] 支持celery异步模块
|
||||||
|
- [ ] 进程守护
|
||||||
|
|
||||||
|
## 功能及使用方法
|
||||||
|
|
||||||
|
### 安装依赖
|
||||||
|
pip install dvadmin3_build-1.0.0-py3-none-any.whl
|
||||||
|
|
||||||
|
### 前端编译
|
||||||
|
yarn run build:local
|
||||||
|
|
||||||
|
### 后端
|
||||||
|
#### settings.py 中添加模块
|
||||||
|
~~~
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
...
|
||||||
|
"dvadmin3_build"
|
||||||
|
]
|
||||||
|
|
||||||
|
HIDDEN_IMPORTS = [
|
||||||
|
'xxxx' # 添加 app 中自己的模块,用于编译
|
||||||
|
]
|
||||||
|
~~~
|
||||||
|
|
||||||
|
#### 迁移与初始化(项目已迁移过的不再需要)
|
||||||
|
~~~
|
||||||
|
python manage.py makemigrations
|
||||||
|
python manage.py migrate
|
||||||
|
python manage.py init
|
||||||
|
python manage.py init_data
|
||||||
|
~~~
|
||||||
|
#### 编译
|
||||||
|
~~~
|
||||||
|
# 编译后位于 dist 目录
|
||||||
|
python manage.py build
|
||||||
|
# windows 打包需要安装 InstallForgeSetup.exe,使用 dvadmin3_InstallForge.ifp 模板(dvadmin3_build/windows_build_tools 目录下)
|
||||||
|
# InstallForge 打包教程:https://www.pythonguis.com/tutorials/packaging-pyqt6-applications-windows-pyinstaller/#setup
|
||||||
|
~~~
|
||||||
0
backend/dvadmin3_build/__init__.py
Normal file
0
backend/dvadmin3_build/__init__.py
Normal file
21
backend/dvadmin3_build/builddmg.sh
Normal file
21
backend/dvadmin3_build/builddmg.sh
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# 获取传入的全局参数
|
||||||
|
dist_folder=$1
|
||||||
|
icon_path=$2
|
||||||
|
|
||||||
|
# 清空dmg文件夹。
|
||||||
|
rm -rf "$dist_folder/DVAServer"
|
||||||
|
rm -rf "$dist_folder/main"
|
||||||
|
# 如果DMG已经存在,则删除它。
|
||||||
|
test -f "$dist_folder/DVAServer.dmg" && rm "$dist_folder/DVAServer.dmg"
|
||||||
|
create-dmg \
|
||||||
|
--volname "DVAServer" \
|
||||||
|
--volicon $icon_path \
|
||||||
|
--window-pos 200 120 \
|
||||||
|
--window-size 600 300 \
|
||||||
|
--icon-size 100 \
|
||||||
|
--icon "DVAServer.app" 175 120 \
|
||||||
|
--hide-extension "DVAServer.app" \
|
||||||
|
--app-drop-link 425 120 \
|
||||||
|
"$dist_folder/DVAServer.dmg" \
|
||||||
|
"$dist_folder/"
|
||||||
49
backend/dvadmin3_build/dvadmin_main.py
Normal file
49
backend/dvadmin3_build/dvadmin_main.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Form implementation generated from reading ui file 'dvadmin_main.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt6 UI code generator 6.4.2
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_DvadminManager(object):
|
||||||
|
def setupUi(self, DvadminManager):
|
||||||
|
DvadminManager.setObjectName("DvadminManager")
|
||||||
|
DvadminManager.resize(400, 300)
|
||||||
|
DvadminManager.setMinimumSize(QtCore.QSize(400, 300))
|
||||||
|
DvadminManager.setMaximumSize(QtCore.QSize(400, 300))
|
||||||
|
self.label = QtWidgets.QLabel(parent=DvadminManager)
|
||||||
|
self.label.setGeometry(QtCore.QRect(10, 13, 60, 21))
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.status_label = QtWidgets.QLabel(parent=DvadminManager)
|
||||||
|
self.status_label.setGeometry(QtCore.QRect(80, 12, 60, 21))
|
||||||
|
self.status_label.setObjectName("status_label")
|
||||||
|
self.start_button = QtWidgets.QPushButton(parent=DvadminManager)
|
||||||
|
self.start_button.setGeometry(QtCore.QRect(210, 10, 81, 26))
|
||||||
|
self.start_button.setObjectName("start_button")
|
||||||
|
self.stop_button = QtWidgets.QPushButton(parent=DvadminManager)
|
||||||
|
self.stop_button.setGeometry(QtCore.QRect(310, 9, 81, 26))
|
||||||
|
self.stop_button.setObjectName("stop_button")
|
||||||
|
self.line = QtWidgets.QFrame(parent=DvadminManager)
|
||||||
|
self.line.setGeometry(QtCore.QRect(0, 40, 401, 16))
|
||||||
|
self.line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||||
|
self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||||
|
self.line.setObjectName("line")
|
||||||
|
self.log_label = QtWidgets.QTextEdit(parent=DvadminManager)
|
||||||
|
self.log_label.setGeometry(QtCore.QRect(-1, 47, 411, 261))
|
||||||
|
self.log_label.setObjectName("log_label")
|
||||||
|
|
||||||
|
self.retranslateUi(DvadminManager)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(DvadminManager)
|
||||||
|
|
||||||
|
def retranslateUi(self, DvadminManager):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
DvadminManager.setWindowTitle(_translate("DvadminManager", "服务管理器"))
|
||||||
|
self.label.setText(_translate("DvadminManager", "运行状态:"))
|
||||||
|
self.status_label.setText(_translate("DvadminManager", "未启动"))
|
||||||
|
self.start_button.setText(_translate("DvadminManager", "启动服务"))
|
||||||
|
self.stop_button.setText(_translate("DvadminManager", "结束服务"))
|
||||||
|
self.log_label.setHtml(_translate("DvadminManager", ""))
|
||||||
113
backend/dvadmin3_build/dvadmin_main.ui
Normal file
113
backend/dvadmin3_build/dvadmin_main.ui
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DvadminManager</class>
|
||||||
|
<widget class="QDialog" name="DvadminManager">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>服务管理器</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>13</y>
|
||||||
|
<width>60</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>运行状态:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="status_label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>80</x>
|
||||||
|
<y>12</y>
|
||||||
|
<width>60</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>未启动</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="start_button">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>210</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>81</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>启动服务</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="stop_button">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>310</x>
|
||||||
|
<y>9</y>
|
||||||
|
<width>81</width>
|
||||||
|
<height>26</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>结束服务</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>401</width>
|
||||||
|
<height>16</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTextEdit" name="log_label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>-1</x>
|
||||||
|
<y>47</y>
|
||||||
|
<width>411</width>
|
||||||
|
<height>261</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
0
backend/dvadmin3_build/extra-hooks/__init__.py
Normal file
0
backend/dvadmin3_build/extra-hooks/__init__.py
Normal file
8
backend/dvadmin3_build/extra-hooks/hooks-uvicorn.py
Normal file
8
backend/dvadmin3_build/extra-hooks/hooks-uvicorn.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# extra-hooks/hooks-uvicorn.py
|
||||||
|
from PyInstaller.utils.hooks import get_package_paths, collect_submodules
|
||||||
|
|
||||||
|
datas = [
|
||||||
|
(get_package_paths('uvicorn')[1], 'uvicorn'),
|
||||||
|
]
|
||||||
|
|
||||||
|
hiddenimports = collect_submodules('whitenoise')
|
||||||
41
backend/dvadmin3_build/file_version_info.txt
Normal file
41
backend/dvadmin3_build/file_version_info.txt
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# UTF-8
|
||||||
|
#
|
||||||
|
# For more details about fixed file info 'ffi' see:
|
||||||
|
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
|
||||||
|
VSVersionInfo(
|
||||||
|
ffi=FixedFileInfo(
|
||||||
|
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
|
||||||
|
# Set not needed items to zero 0.
|
||||||
|
filevers=(1, 0, 0, 0),
|
||||||
|
prodvers=(1, 0, 0, 0),
|
||||||
|
# Contains a bitmask that specifies the valid bits 'flags'r
|
||||||
|
mask=0x3f,
|
||||||
|
# Contains a bitmask that specifies the Boolean attributes of the file.
|
||||||
|
flags=0x0,
|
||||||
|
# The operating system for which this file was designed.
|
||||||
|
# 0x4 - NT and there is no need to change it.
|
||||||
|
OS=0x40004,
|
||||||
|
# The general type of file.
|
||||||
|
# 0x1 - the file is an application.
|
||||||
|
fileType=0x1,
|
||||||
|
# The function of the file.
|
||||||
|
# 0x0 - the function is not defined for this fileType
|
||||||
|
subtype=0x0,
|
||||||
|
# Creation date and time stamp.
|
||||||
|
date=(0, 0)
|
||||||
|
),
|
||||||
|
kids=[
|
||||||
|
StringFileInfo(
|
||||||
|
[
|
||||||
|
StringTable(
|
||||||
|
'080404b0',
|
||||||
|
[StringStruct('CompanyName', '北京信码新创科技有限公司'),
|
||||||
|
StringStruct('FileDescription', '边缘Agent'),
|
||||||
|
StringStruct('FileVersion', '1.0.0.0'),
|
||||||
|
StringStruct('LegalCopyright', 'Copyright (C) 2021-2025 北京信码新创科技有限公司 All Rights Reserved'),
|
||||||
|
StringStruct('ProductName', '边缘Agent'),
|
||||||
|
StringStruct('ProductVersion', '1.0.0.0')])
|
||||||
|
]),
|
||||||
|
VarFileInfo([VarStruct('Translation', [2052, 1200])])
|
||||||
|
]
|
||||||
|
)
|
||||||
0
backend/dvadmin3_build/management/__init__.py
Normal file
0
backend/dvadmin3_build/management/__init__.py
Normal file
57
backend/dvadmin3_build/management/commands/build.py
Normal file
57
backend/dvadmin3_build/management/commands/build.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from application.settings import BASE_DIR
|
||||||
|
|
||||||
|
from application import settings
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""
|
||||||
|
生产初始化菜单: python manage.py build
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
print(args, options)
|
||||||
|
base_path = Path(__file__).resolve().parent.parent
|
||||||
|
# main.spec 路径
|
||||||
|
main_spec_path = os.path.join(base_path.parent, 'main.spec')
|
||||||
|
|
||||||
|
# 执行编译
|
||||||
|
import subprocess
|
||||||
|
# 执行命令
|
||||||
|
HIDDEN_IMPORTS = ','.join(getattr(settings, 'HIDDEN_IMPORTS', []))
|
||||||
|
command = f'export BASE_DIR="{BASE_DIR}" && export HIDDEN_IMPORTS="{HIDDEN_IMPORTS}" && rm -rf {os.path.join(BASE_DIR, "dist")} && pyinstaller -y --clean {main_spec_path}'
|
||||||
|
if os.sys.platform.startswith('win'):
|
||||||
|
# Windows操作系统
|
||||||
|
# command = f'setx BASE_DIR "{BASE_DIR}" && set HIDDEN_IMPORTS "{HIDDEN_IMPORTS}" && del {os.path.join(BASE_DIR, "dist")} && pyinstaller -y --clean {main_spec_path}'
|
||||||
|
command = f'setx BASE_DIR "{BASE_DIR}" && setx HIDDEN_IMPORTS "{HIDDEN_IMPORTS}" && pyinstaller -y --clean {main_spec_path}'
|
||||||
|
print(command)
|
||||||
|
print("当前环境是 Windows")
|
||||||
|
elif os.sys.platform.startswith('linux'):
|
||||||
|
# Linux操作系统
|
||||||
|
print("当前环境是 Linux")
|
||||||
|
command += f' && rm -rf {os.path.join(BASE_DIR, "build")}'
|
||||||
|
elif os.sys.platform.startswith('darwin'):
|
||||||
|
# macOS操作系统
|
||||||
|
print("当前环境是 macOS")
|
||||||
|
build_dmg_path = os.path.join(base_path.parent, 'builddmg.sh')
|
||||||
|
# 判断logo 是否存在
|
||||||
|
logo_path = os.path.join(BASE_DIR, 'static', 'logo.icns')
|
||||||
|
if not os.path.exists(logo_path):
|
||||||
|
# 文件不存在的处理逻辑
|
||||||
|
logo_path = os.path.join(base_path.parent, 'static', 'logo.icns')
|
||||||
|
command += f' && chmod +x {build_dmg_path} && {build_dmg_path} {os.path.join(BASE_DIR, "dist")} {logo_path}'
|
||||||
|
command += f' && rm -rf {os.path.join(BASE_DIR, "build")}'
|
||||||
|
print(command)
|
||||||
|
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||||
|
for line in process.stdout:
|
||||||
|
print(line.replace('\n', ''))
|
||||||
|
# # 等待进程结束
|
||||||
|
process.wait()
|
||||||
304
backend/dvadmin3_build/server.py
Normal file
304
backend/dvadmin3_build/server.py
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import webbrowser
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from PyQt6.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal, Qt
|
||||||
|
from PyQt6.QtNetwork import QLocalServer
|
||||||
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QSystemTrayIcon, QMenu, QMessageBox
|
||||||
|
from PyQt6.QtGui import QIcon, QTextCharFormat, QColor, QTextCursor
|
||||||
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# # 编译ui
|
||||||
|
# pyuic6 dvadmin_main.ui -o dvadmin_main.py
|
||||||
|
# 由于编译问题,把dvadmin_main.py代码复制到本脚本中
|
||||||
|
class Ui_DvadminManager(object):
|
||||||
|
def setupUi(self, DvadminManager):
|
||||||
|
DvadminManager.setObjectName("DvadminManager")
|
||||||
|
DvadminManager.resize(400, 300)
|
||||||
|
DvadminManager.setMinimumSize(QtCore.QSize(400, 300))
|
||||||
|
DvadminManager.setMaximumSize(QtCore.QSize(400, 300))
|
||||||
|
self.label = QtWidgets.QLabel(parent=DvadminManager)
|
||||||
|
self.label.setGeometry(QtCore.QRect(10, 13, 60, 21))
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.status_label = QtWidgets.QLabel(parent=DvadminManager)
|
||||||
|
self.status_label.setGeometry(QtCore.QRect(80, 12, 60, 21))
|
||||||
|
self.status_label.setObjectName("status_label")
|
||||||
|
self.start_button = QtWidgets.QPushButton(parent=DvadminManager)
|
||||||
|
self.start_button.setGeometry(QtCore.QRect(210, 10, 81, 26))
|
||||||
|
self.start_button.setObjectName("start_button")
|
||||||
|
self.stop_button = QtWidgets.QPushButton(parent=DvadminManager)
|
||||||
|
self.stop_button.setGeometry(QtCore.QRect(310, 9, 81, 26))
|
||||||
|
self.stop_button.setObjectName("stop_button")
|
||||||
|
self.line = QtWidgets.QFrame(parent=DvadminManager)
|
||||||
|
self.line.setGeometry(QtCore.QRect(0, 40, 401, 16))
|
||||||
|
self.line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
||||||
|
self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
||||||
|
self.line.setObjectName("line")
|
||||||
|
self.log_label = QtWidgets.QTextEdit(parent=DvadminManager)
|
||||||
|
self.log_label.setGeometry(QtCore.QRect(-1, 47, 411, 261))
|
||||||
|
self.log_label.setObjectName("log_label")
|
||||||
|
|
||||||
|
self.retranslateUi(DvadminManager)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(DvadminManager)
|
||||||
|
|
||||||
|
def retranslateUi(self, DvadminManager):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
DvadminManager.setWindowTitle(_translate("DvadminManager", "服务管理器"))
|
||||||
|
self.label.setText(_translate("DvadminManager", "运行状态:"))
|
||||||
|
self.status_label.setText(_translate("DvadminManager", "未启动"))
|
||||||
|
self.start_button.setText(_translate("DvadminManager", "启动服务"))
|
||||||
|
self.stop_button.setText(_translate("DvadminManager", "结束服务"))
|
||||||
|
self.log_label.setHtml(_translate("DvadminManager", ""))
|
||||||
|
|
||||||
|
|
||||||
|
class SelectWorkerSignals(QObject):
|
||||||
|
result = pyqtSignal(str)
|
||||||
|
stop = pyqtSignal(bool)
|
||||||
|
|
||||||
|
|
||||||
|
list_process = []
|
||||||
|
|
||||||
|
|
||||||
|
class ServerWorkerSignals(QObject):
|
||||||
|
result = pyqtSignal(str)
|
||||||
|
|
||||||
|
|
||||||
|
class SelectWorker(QRunnable):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.signals = SelectWorkerSignals()
|
||||||
|
self.is_run = True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# 模拟异步操作
|
||||||
|
import time
|
||||||
|
import psutil
|
||||||
|
while self.is_run:
|
||||||
|
# 遍历进程列表,结束即关闭服务
|
||||||
|
# 获取所有正在运行的进程列表
|
||||||
|
processes = psutil.process_iter()
|
||||||
|
new_list_process = []
|
||||||
|
for process in processes:
|
||||||
|
# 如果进程名称包含"uvicorn",则进行监控
|
||||||
|
if process.pid in list_process:
|
||||||
|
new_list_process.append(process.pid)
|
||||||
|
if list_process and not new_list_process:
|
||||||
|
self.signals.result.emit("异步,进程不存在!")
|
||||||
|
# 等待1秒
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def handle_stop_result(self, result):
|
||||||
|
"""
|
||||||
|
异步获取进程结果后执行
|
||||||
|
"""
|
||||||
|
self.is_run = result
|
||||||
|
|
||||||
|
|
||||||
|
class ServerWorker(QRunnable):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.signals = ServerWorkerSignals()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# 启动dvadmin服务
|
||||||
|
import os
|
||||||
|
print("启动dvadmin服务")
|
||||||
|
# import main
|
||||||
|
# main.run()
|
||||||
|
# 定义要执行的命令
|
||||||
|
command = f"./main"
|
||||||
|
if os.sys.platform.startswith('win'):
|
||||||
|
# Windows操作系统
|
||||||
|
print("当前环境是Windows", Path(__file__).resolve().parent)
|
||||||
|
print("当前环境是Windows", Path(__file__).resolve())
|
||||||
|
command = f"{Path(__file__).resolve().parent.parent}/main.exe"
|
||||||
|
elif os.sys.platform.startswith('linux'):
|
||||||
|
# Linux操作系统
|
||||||
|
print("当前环境是Linux")
|
||||||
|
elif os.sys.platform.startswith('darwin'):
|
||||||
|
# macOS操作系统
|
||||||
|
print("当前环境是macOS")
|
||||||
|
command = f"{Path(__file__).resolve().parent.parent}/MacOS/main"
|
||||||
|
else:
|
||||||
|
# 其他操作系统
|
||||||
|
print("当前环境是其他操作系统")
|
||||||
|
self.signals.result.emit(json.dumps({"code": 2001, "msg": command}))
|
||||||
|
global list_process
|
||||||
|
# 使用subprocess.Popen执行命令
|
||||||
|
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
||||||
|
self.signals.result.emit(json.dumps({"code": 2000, "msg": "服务启动成功..."}))
|
||||||
|
# 持续获取输出结果
|
||||||
|
pid = process.pid
|
||||||
|
list_process.append(pid)
|
||||||
|
for line in process.stdout:
|
||||||
|
match = re.search(r'Started server process \[(\d+)\]', line)
|
||||||
|
# 判断是否匹配成功
|
||||||
|
if match:
|
||||||
|
# 获取匹配到的数字
|
||||||
|
number = match.group(1)
|
||||||
|
list_process.append(number)
|
||||||
|
list_process = list(set(list_process))
|
||||||
|
self.signals.result.emit(json.dumps({"code": 2001, "msg": line.replace('\n', '')}))
|
||||||
|
# 等待进程结束
|
||||||
|
process.wait()
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow, Ui_DvadminManager):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setupUi(self)
|
||||||
|
# 开始、结束按钮
|
||||||
|
self.start_button.clicked.connect(self.start_service)
|
||||||
|
self.stop_button.clicked.connect(self.stop_service)
|
||||||
|
# 托盘按钮及事件
|
||||||
|
self.tray_icon = QSystemTrayIcon(QIcon(os.path.join(Path(__file__).resolve().parent, 'static','logo.icns')), self)
|
||||||
|
self.tray_icon.activated.connect(self.tray_icon_activated)
|
||||||
|
self.tray_menu = QMenu(self)
|
||||||
|
self.tray_menu.addAction(self.start_button.text(), self.start_service)
|
||||||
|
self.tray_menu.addAction(self.stop_button.text(), self.stop_service)
|
||||||
|
self.tray_menu.addSeparator()
|
||||||
|
self.tray_menu.addAction("退出", QApplication.quit)
|
||||||
|
self.tray_icon.setContextMenu(self.tray_menu)
|
||||||
|
self.tray_icon.show()
|
||||||
|
|
||||||
|
self.log_label.setReadOnly(True)
|
||||||
|
|
||||||
|
# 信号
|
||||||
|
self.select_worker = SelectWorker()
|
||||||
|
self.select_worker.signals.result.connect(self.handle_select_result)
|
||||||
|
self.select_worker.signals.stop.connect(self.select_worker.handle_stop_result)
|
||||||
|
self.server_worker = ServerWorker()
|
||||||
|
self.server_worker.signals.result.connect(self.handle_server_servers)
|
||||||
|
# 异步
|
||||||
|
self.select_threadpool = QThreadPool()
|
||||||
|
self.server_threadpool = QThreadPool()
|
||||||
|
|
||||||
|
def handle_select_result(self, result):
|
||||||
|
"""
|
||||||
|
异步获取进程结果后执行
|
||||||
|
"""
|
||||||
|
self.append_to_log('服务进程异常,服务已停止...', color='red')
|
||||||
|
global list_process
|
||||||
|
list_process = []
|
||||||
|
self.status_label.setText("已停止")
|
||||||
|
self.status_label.setStyleSheet("color: red;")
|
||||||
|
|
||||||
|
def handle_server_servers(self, result):
|
||||||
|
"""
|
||||||
|
启动服务
|
||||||
|
"""
|
||||||
|
json_result = json.loads(result)
|
||||||
|
if json_result.get('code') == 2000:
|
||||||
|
self.append_to_log(json_result.get('msg'), color='green')
|
||||||
|
# 启动成功打开浏览器
|
||||||
|
url = "http://127.0.0.1:8000/web/"
|
||||||
|
def open_browser_after_delay(url, delay):
|
||||||
|
time.sleep(delay)
|
||||||
|
webbrowser.open(url)
|
||||||
|
|
||||||
|
threading.Thread(target=open_browser_after_delay, args=(url, 3)).start()
|
||||||
|
self.status_label.setText("运行中")
|
||||||
|
self.status_label.setStyleSheet("color: green;")
|
||||||
|
elif json_result.get('code') == 2001:
|
||||||
|
self.append_to_log(json_result.get('msg'))
|
||||||
|
else:
|
||||||
|
self.append_to_log(json_result.get('msg'), color='red')
|
||||||
|
self.status_label.setText("已停止")
|
||||||
|
self.status_label.setStyleSheet("color: red;")
|
||||||
|
|
||||||
|
def append_to_log(self, message, color=None):
|
||||||
|
"""
|
||||||
|
添加日志颜色
|
||||||
|
"""
|
||||||
|
cursor = self.log_label.textCursor()
|
||||||
|
format = QTextCharFormat()
|
||||||
|
if color:
|
||||||
|
if color == "green":
|
||||||
|
format.setForeground(QColor("green"))
|
||||||
|
elif color == "red":
|
||||||
|
format.setForeground(QColor("red"))
|
||||||
|
cursor.movePosition(QTextCursor.MoveOperation.End)
|
||||||
|
cursor.insertText(message, format)
|
||||||
|
cursor.insertBlock()
|
||||||
|
self.log_label.setTextCursor(cursor)
|
||||||
|
self.log_label.ensureCursorVisible()
|
||||||
|
self.log_label.verticalScrollBar().setValue(self.log_label.verticalScrollBar().maximum())
|
||||||
|
|
||||||
|
def start_service(self):
|
||||||
|
global list_process
|
||||||
|
if not list_process:
|
||||||
|
# 启动服务,执行启动脚本
|
||||||
|
self.server_threadpool.clear()
|
||||||
|
self.select_threadpool.clear()
|
||||||
|
self.select_worker.signals.stop.emit(True)
|
||||||
|
self.select_threadpool.startOnReservedThread(self.select_worker.run)
|
||||||
|
self.server_threadpool.startOnReservedThread(self.server_worker.run)
|
||||||
|
self.status_label.setText("正在启动中")
|
||||||
|
self.status_label.setStyleSheet("color: green;")
|
||||||
|
else:
|
||||||
|
self.append_to_log("服务已启动...")
|
||||||
|
|
||||||
|
def stop_service(self):
|
||||||
|
"""
|
||||||
|
停止服务
|
||||||
|
"""
|
||||||
|
global list_process
|
||||||
|
if list_process:
|
||||||
|
for pid in list_process:
|
||||||
|
try:
|
||||||
|
os.kill(int(pid), signal.SIGTERM)
|
||||||
|
except Exception as e:
|
||||||
|
print('Exception', e)
|
||||||
|
pass
|
||||||
|
list_process = []
|
||||||
|
self.select_worker.signals.stop.emit(False)
|
||||||
|
self.select_threadpool.clear()
|
||||||
|
self.server_threadpool.clear()
|
||||||
|
self.status_label.setText("已停止")
|
||||||
|
self.status_label.setStyleSheet("color: red;")
|
||||||
|
self.service_running = False
|
||||||
|
self.append_to_log("服务已停止...", color='red')
|
||||||
|
|
||||||
|
def tray_icon_activated(self, reason):
|
||||||
|
"""
|
||||||
|
托盘激活
|
||||||
|
"""
|
||||||
|
if reason == QSystemTrayIcon.ActivationReason.Trigger:
|
||||||
|
self.showNormal()
|
||||||
|
self.activateWindow()
|
||||||
|
|
||||||
|
def showEvent(self, event):
|
||||||
|
# 自定义的显示事件处理
|
||||||
|
if self.status_label.text() != '已停止':
|
||||||
|
self.select_worker.signals.stop.emit(True)
|
||||||
|
self.select_threadpool.startOnReservedThread(self.select_worker.run)
|
||||||
|
return super().showEvent(event)
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
event.ignore()
|
||||||
|
self.hide()
|
||||||
|
self.select_worker.signals.stop.emit(False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
server = QLocalServer()
|
||||||
|
if server.listen('DVAServer'):
|
||||||
|
app.setQuitOnLastWindowClosed(False)
|
||||||
|
app.setWindowIcon(QIcon(os.path.join(Path(__file__).resolve().parent, 'static','logo.icns')))
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
sys.exit(app.exec())
|
||||||
|
else:
|
||||||
|
message_box = QMessageBox(QMessageBox.Icon.Information, 'Information', '应用程序已在运行')
|
||||||
|
message_box.exec()
|
||||||
|
sys.exit(0) # 如果已有实例在运行,则退出应用程序
|
||||||
28
backend/dvadmin3_build/setup.py
Normal file
28
backend/dvadmin3_build/setup.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import setuptools
|
||||||
|
|
||||||
|
with open("README.md", "r") as fh:
|
||||||
|
long_description = fh.read()
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
name="dvadmin3-build",
|
||||||
|
version="1.0.0",
|
||||||
|
author="DVAdmin",
|
||||||
|
author_email="liqiang@django-vue-admin.com",
|
||||||
|
description="一款适用于django-vue3-admin 编译打包exe、macOS的dmg文件等打包工具。支持加密代码、一键启动项目,无需考虑环境。",
|
||||||
|
long_description=long_description,
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
url="https://gitee.com/huge-dream/dvadmin-build",
|
||||||
|
packages=setuptools.find_packages(),
|
||||||
|
python_requires='>=3.7, <4',
|
||||||
|
install_requires=[
|
||||||
|
"pyinstaller>=6.8.0",
|
||||||
|
"PyQt6>=6.4.2",
|
||||||
|
"psutil==6.0.0",
|
||||||
|
],
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"License :: OSI Approved :: MIT License",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
],
|
||||||
|
include_package_data=True
|
||||||
|
)
|
||||||
BIN
backend/dvadmin3_build/static/logo.icns
Normal file
BIN
backend/dvadmin3_build/static/logo.icns
Normal file
Binary file not shown.
BIN
backend/dvadmin3_build/windows_build_tools/InstallForgeSetup.exe
Normal file
BIN
backend/dvadmin3_build/windows_build_tools/InstallForgeSetup.exe
Normal file
Binary file not shown.
Binary file not shown.
52
redis-8.2.1/README.md
Normal file
52
redis-8.2.1/README.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
### [English](https://github.com/redis-windows/redis-windows/blob/main/README.md) | [简体中文](https://github.com/redis-windows/redis-windows/blob/main/README.zh_CN.md)
|
||||||
|
|
||||||
|
# Redis Windows Version
|
||||||
|
### With the powerful automated building capability of GitHub Actions, we can compile the latest version of Redis for Windows system in real-time.
|
||||||
|
The entire compilation process is completely transparent and open, with the compilation script located in the [.github/workflows/](https://github.com/redis-windows/redis-windows/tree/main/.github/workflows) directory and the compilation logs available on the [Actions](https://github.com/redis-windows/redis-windows/actions) page. In addition, we have added a hash calculation step when the compilation is completed, and the result is printed in the log. This is unmodifiable and recorded in the release page. You can verify the hash value of the downloaded file against the log and release page.
|
||||||
|
Our project is absolutely pure and without any hidden features, and can withstand the scrutiny of all experts. If you have any good ideas, please feel free to communicate with us.
|
||||||
|
|
||||||
|
## We provide three operation modes:
|
||||||
|
1. Run the start.bat script in the project to start directly with one click.
|
||||||
|
2. Use the command line.
|
||||||
|
3. Support running as a system service.
|
||||||
|
|
||||||
|
### Command line startup:
|
||||||
|
cmd startup:
|
||||||
|
```shell
|
||||||
|
redis-server.exe redis.conf
|
||||||
|
```
|
||||||
|
powershell startup:
|
||||||
|
```shell
|
||||||
|
./redis-server.exe redis.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service installation:
|
||||||
|
Can achieve automatic startup on boot. Please run it as an administrator and change RedisService.exe to the actual directory where it is stored.
|
||||||
|
```shell
|
||||||
|
sc.exe create Redis binpath=C:\Software\Redis\RedisService.exe start= auto
|
||||||
|
```
|
||||||
|
Start service
|
||||||
|
```shell
|
||||||
|
net start Redis
|
||||||
|
```
|
||||||
|
Out of Service
|
||||||
|
```shell
|
||||||
|
net stop Redis
|
||||||
|
```
|
||||||
|
Uninstall service
|
||||||
|
```shell
|
||||||
|
sc.exe delete Redis
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
Project Home: https://github.com/redis-windows/redis-windows
|
||||||
|
|
||||||
|
## Acknowledgement:
|
||||||
|
[](https://www.zhihu.com/question/424272611/answer/2611312760)
|
||||||
|
[](https://www.jetbrains.com/?from=redis-windows)
|
||||||
|
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
We suggest that you use it for local development and follow Redis official guidance to deploy it on Linux for production environment. This project doesn't bear any responsibility for any losses caused by using it and is only for learning and exchange purposes.
|
||||||
59
redis-8.2.1/README.zh_CN.md
Normal file
59
redis-8.2.1/README.zh_CN.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
### [English](https://github.com/redis-windows/redis-windows/blob/main/README.md) | [简体中文](https://github.com/redis-windows/redis-windows/blob/main/README.zh_CN.md)
|
||||||
|
|
||||||
|
# Redis Windows版本
|
||||||
|
|
||||||
|
### 借助GitHub Actions强大的自动化构建能力,为我们实时编译适用于Windows系统的Redis最新版本
|
||||||
|
|
||||||
|
整个编译过程完全公开透明, 编译脚本在[.github/workflows/](https://github.com/redis-windows/redis-windows/tree/main/.github/workflows) 目录中,编译日志可在 [Actions](https://github.com/redis-windows/redis-windows/actions)页面查看。此外,我们在编译结束,新增了哈希值计算环节,计算结果打印在日志中,这是任何人不可修改的,并写入发布页面。您可以核对下载到本地的文件的哈希值,是否与日志和发布页面的一致。本项目绝对纯洁无私货,经得起各位大佬审查。如您有好的想法,也欢迎交流。
|
||||||
|
|
||||||
|
|
||||||
|
### 提供三种运行模式
|
||||||
|
|
||||||
|
直接运行项目中的 start.bat 脚本,一键启动
|
||||||
|
|
||||||
|
或者使用命令行
|
||||||
|
|
||||||
|
还支持以系统服务运行
|
||||||
|
|
||||||
|
|
||||||
|
## 命令行启动
|
||||||
|
cmd 启动
|
||||||
|
```shell
|
||||||
|
redis-server.exe redis.conf
|
||||||
|
```
|
||||||
|
powershell 启动
|
||||||
|
```shell
|
||||||
|
./redis-server.exe redis.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
## 安装服务
|
||||||
|
可实现开机自启动
|
||||||
|
请以管理员身份运行,并将RedisService.exe改为您实际存放的路径
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sc.exe create Redis binpath=C:\Software\Redis\RedisService.exe start= auto
|
||||||
|
```
|
||||||
|
启动服务
|
||||||
|
```shell
|
||||||
|
net start Redis
|
||||||
|
```
|
||||||
|
停止服务
|
||||||
|
```shell
|
||||||
|
net stop Redis
|
||||||
|
```
|
||||||
|
卸载服务
|
||||||
|
```shell
|
||||||
|
sc.exe delete Redis
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
项目主页: https://github.com/redis-windows/redis-windows
|
||||||
|
|
||||||
|
### 鸣谢
|
||||||
|
[](https://www.zhihu.com/question/424272611/answer/2611312760)
|
||||||
|
[](https://www.jetbrains.com/?from=redis-windows)
|
||||||
|
|
||||||
|
### 免责声明
|
||||||
|
建议您在本地开发环节使用,生产环境请按照Redis官方指导,在Linux中部署。本项目不承担由此给您带来的任何损失,仅供学习交流。
|
||||||
BIN
redis-8.2.1/RedisService.exe
Normal file
BIN
redis-8.2.1/RedisService.exe
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygcrypto-3.dll
Normal file
BIN
redis-8.2.1/cygcrypto-3.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cyggcc_s-seh-1.dll
Normal file
BIN
redis-8.2.1/cyggcc_s-seh-1.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygiconv-2.dll
Normal file
BIN
redis-8.2.1/cygiconv-2.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygintl-8.dll
Normal file
BIN
redis-8.2.1/cygintl-8.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygssl-3.dll
Normal file
BIN
redis-8.2.1/cygssl-3.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygstdc++-6.dll
Normal file
BIN
redis-8.2.1/cygstdc++-6.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygwin1.dll
Normal file
BIN
redis-8.2.1/cygwin1.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/cygz.dll
Normal file
BIN
redis-8.2.1/cygz.dll
Normal file
Binary file not shown.
BIN
redis-8.2.1/dump.rdb
Normal file
BIN
redis-8.2.1/dump.rdb
Normal file
Binary file not shown.
BIN
redis-8.2.1/redis-benchmark.exe
Normal file
BIN
redis-8.2.1/redis-benchmark.exe
Normal file
Binary file not shown.
BIN
redis-8.2.1/redis-check-aof.exe
Normal file
BIN
redis-8.2.1/redis-check-aof.exe
Normal file
Binary file not shown.
BIN
redis-8.2.1/redis-check-rdb.exe
Normal file
BIN
redis-8.2.1/redis-check-rdb.exe
Normal file
Binary file not shown.
BIN
redis-8.2.1/redis-cli.exe
Normal file
BIN
redis-8.2.1/redis-cli.exe
Normal file
Binary file not shown.
376
redis-8.2.1/redis-full.conf
Normal file
376
redis-8.2.1/redis-full.conf
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
include redis.conf
|
||||||
|
|
||||||
|
loadmodule ./modules/redisbloom/redisbloom.so
|
||||||
|
loadmodule ./modules/redisearch/redisearch.so
|
||||||
|
loadmodule ./modules/redisjson/rejson.so
|
||||||
|
loadmodule ./modules/redistimeseries/redistimeseries.so
|
||||||
|
|
||||||
|
############################## QUERY ENGINE CONFIG ############################
|
||||||
|
|
||||||
|
# Keep numeric ranges in numeric tree parent nodes of leafs for `x` generations.
|
||||||
|
# numeric, valid range: [0, 2], default: 0
|
||||||
|
#
|
||||||
|
# search-_numeric-ranges-parents 0
|
||||||
|
|
||||||
|
# The number of iterations to run while performing background indexing
|
||||||
|
# before we call usleep(1) (sleep for 1 micro-second) and make sure that we
|
||||||
|
# allow redis to process other commands.
|
||||||
|
# numeric, valid range: [1, UINT32_MAX], default: 100
|
||||||
|
#
|
||||||
|
# search-bg-index-sleep-gap 100
|
||||||
|
|
||||||
|
# The default dialect used in search queries.
|
||||||
|
# numeric, valid range: [1, 4], default: 1
|
||||||
|
#
|
||||||
|
# search-default-dialect 1
|
||||||
|
|
||||||
|
# the fork gc will only start to clean when the number of not cleaned document
|
||||||
|
# will exceed this threshold.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 100
|
||||||
|
#
|
||||||
|
# search-fork-gc-clean-threshold 100
|
||||||
|
|
||||||
|
# interval (in seconds) in which to retry running the forkgc after failure.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 5
|
||||||
|
#
|
||||||
|
# search-fork-gc-retry-interval 5
|
||||||
|
|
||||||
|
# interval (in seconds) in which to run the fork gc (relevant only when fork
|
||||||
|
# gc is used).
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 30
|
||||||
|
#
|
||||||
|
# search-fork-gc-run-interval 30
|
||||||
|
|
||||||
|
# the amount of seconds for the fork GC to sleep before exiting.
|
||||||
|
# numeric, valid range: [0, LLONG_MAX], default: 0
|
||||||
|
#
|
||||||
|
# search-fork-gc-sleep-before-exit 0
|
||||||
|
|
||||||
|
# Scan this many documents at a time during every GC iteration.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 100
|
||||||
|
#
|
||||||
|
# search-gc-scan-size 100
|
||||||
|
|
||||||
|
# Max number of cursors for a given index that can be opened inside of a shard.
|
||||||
|
# numeric, valid range: [0, LLONG_MAX], default: 128
|
||||||
|
#
|
||||||
|
# search-index-cursor-limit 128
|
||||||
|
|
||||||
|
# Maximum number of results from ft.aggregate command.
|
||||||
|
# numeric, valid range: [0, (1ULL << 31)], default: 1ULL << 31
|
||||||
|
#
|
||||||
|
# search-max-aggregate-results 2147483648
|
||||||
|
|
||||||
|
# Maximum prefix expansions to be used in a query.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 200
|
||||||
|
#
|
||||||
|
# search-max-prefix-expansions 200
|
||||||
|
|
||||||
|
# Maximum runtime document table size (for this process).
|
||||||
|
# numeric, valid range: [1, 100000000], default: 1000000
|
||||||
|
#
|
||||||
|
# search-max-doctablesize 1000000
|
||||||
|
|
||||||
|
# max idle time allowed to be set for cursor, setting it high might cause
|
||||||
|
# high memory consumption.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 300000
|
||||||
|
#
|
||||||
|
# search-cursor-max-idle 300000
|
||||||
|
|
||||||
|
# Maximum number of results from ft.search command.
|
||||||
|
# numeric, valid range: [0, 1ULL << 31], default: 1000000
|
||||||
|
#
|
||||||
|
# search-max-search-results 1000000
|
||||||
|
|
||||||
|
# Number of worker threads to use for background tasks when the server is
|
||||||
|
# in an operation event.
|
||||||
|
# numeric, valid range: [1, 16], default: 4
|
||||||
|
#
|
||||||
|
# search-min-operation-workers 4
|
||||||
|
|
||||||
|
# Minimum length of term to be considered for phonetic matching.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 3
|
||||||
|
#
|
||||||
|
# search-min-phonetic-term-len 3
|
||||||
|
|
||||||
|
# the minimum prefix for expansions (`*`).
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 2
|
||||||
|
#
|
||||||
|
# search-min-prefix 2
|
||||||
|
|
||||||
|
# the minimum word length to stem.
|
||||||
|
# numeric, valid range: [2, UINT32_MAX], default: 4
|
||||||
|
#
|
||||||
|
# search-min-stem-len 4
|
||||||
|
|
||||||
|
# Delta used to increase positional offsets between array
|
||||||
|
# slots for multi text values.
|
||||||
|
# Can control the level of separation between phrases in different
|
||||||
|
# array slots (related to the SLOP parameter of ft.search command)"
|
||||||
|
# numeric, valid range: [1, UINT32_MAX], default: 100
|
||||||
|
#
|
||||||
|
# search-multi-text-slop 100
|
||||||
|
|
||||||
|
# Used for setting the buffer limit threshold for vector similarity tiered
|
||||||
|
# HNSW index, so that if we are using WORKERS for indexing, and the
|
||||||
|
# number of vectors waiting in the buffer to be indexed exceeds this limit,
|
||||||
|
# we insert new vectors directly into HNSW.
|
||||||
|
# numeric, valid range: [0, LLONG_MAX], default: 1024
|
||||||
|
#
|
||||||
|
# search-tiered-hnsw-buffer-limit 1024
|
||||||
|
|
||||||
|
# Query timeout.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 500
|
||||||
|
#
|
||||||
|
# search-timeout 500
|
||||||
|
|
||||||
|
# minimum number of iterators in a union from which the iterator will
|
||||||
|
# will switch to heap-based implementation.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 20
|
||||||
|
# switch to heap based implementation.
|
||||||
|
#
|
||||||
|
# search-union-iterator-heap 20
|
||||||
|
|
||||||
|
# The maximum memory resize for vector similarity indexes (in bytes).
|
||||||
|
# numeric, valid range: [0, UINT32_MAX], default: 0
|
||||||
|
#
|
||||||
|
# search-vss-max-resize 0
|
||||||
|
|
||||||
|
# Number of worker threads to use for query processing and background tasks.
|
||||||
|
# numeric, valid range: [0, 16], default: 0
|
||||||
|
# This configuration also affects the number of connections per shard.
|
||||||
|
#
|
||||||
|
# search-workers 0
|
||||||
|
|
||||||
|
# The number of high priority tasks to be executed at any given time by the
|
||||||
|
# worker thread pool, before executing low priority tasks. After this number
|
||||||
|
# of high priority tasks are being executed, the worker thread pool will
|
||||||
|
# execute high and low priority tasks alternately.
|
||||||
|
# numeric, valid range: [0, LLONG_MAX], default: 1
|
||||||
|
#
|
||||||
|
# search-workers-priority-bias-threshold 1
|
||||||
|
|
||||||
|
# Load extension scoring/expansion module. Immutable.
|
||||||
|
# string, default: ""
|
||||||
|
#
|
||||||
|
# search-ext-load ""
|
||||||
|
|
||||||
|
# Path to Chinese dictionary configuration file (for Chinese tokenization). Immutable.
|
||||||
|
# string, default: ""
|
||||||
|
#
|
||||||
|
# search-friso-ini ""
|
||||||
|
|
||||||
|
# Action to perform when search timeout is exceeded (choose RETURN or FAIL).
|
||||||
|
# enum, valid values: ["return", "fail"], default: "fail"
|
||||||
|
#
|
||||||
|
# search-on-timeout fail
|
||||||
|
|
||||||
|
# Determine whether some index resources are free on a second thread.
|
||||||
|
# bool, default: yes
|
||||||
|
#
|
||||||
|
# search-_free-resource-on-thread yes
|
||||||
|
|
||||||
|
# Enable legacy compression of double to float.
|
||||||
|
# bool, default: no
|
||||||
|
#
|
||||||
|
# search-_numeric-compress no
|
||||||
|
|
||||||
|
# Disable print of time for ft.profile. For testing only.
|
||||||
|
# bool, default: yes
|
||||||
|
#
|
||||||
|
# search-_print-profile-clock yes
|
||||||
|
|
||||||
|
# Intersection iterator orders the children iterators by their relative estimated
|
||||||
|
# number of results in ascending order, so that if we see first iterators with
|
||||||
|
# a lower count of results we will skip a larger number of results, which
|
||||||
|
# translates into faster iteration. If this flag is set, we use this
|
||||||
|
# optimization in a way where union iterators are being factorize by the number
|
||||||
|
# of their own children, so that we sort by the number of children times the
|
||||||
|
# overall estimated number of results instead.
|
||||||
|
# bool, default: no
|
||||||
|
#
|
||||||
|
# search-_prioritize-intersect-union-children no
|
||||||
|
|
||||||
|
# Set to run without memory pools.
|
||||||
|
# bool, default: no
|
||||||
|
#
|
||||||
|
# search-no-mem-pools no
|
||||||
|
|
||||||
|
# Disable garbage collection (for this process).
|
||||||
|
# bool, default: no
|
||||||
|
#
|
||||||
|
# search-no-gc no
|
||||||
|
|
||||||
|
# Enable commands filter which optimize indexing on partial hash updates.
|
||||||
|
# bool, default: no
|
||||||
|
#
|
||||||
|
# search-partial-indexed-docs no
|
||||||
|
|
||||||
|
# Disable compression for DocID inverted index. Boost CPU performance.
|
||||||
|
# bool, default: no
|
||||||
|
#
|
||||||
|
# search-raw-docid-encoding no
|
||||||
|
|
||||||
|
# Number of search threads in the coordinator thread pool.
|
||||||
|
# numeric, valid range: [1, LLONG_MAX], default: 20
|
||||||
|
#
|
||||||
|
# search-threads 20
|
||||||
|
|
||||||
|
# Timeout for topology validation (in milliseconds). After this timeout,
|
||||||
|
# any pending requests will be processed, even if the topology is not fully connected.
|
||||||
|
# numeric, valid range: [0, LLONG_MAX], default: 30000
|
||||||
|
#
|
||||||
|
# search-topology-validation-timeout 30000
|
||||||
|
|
||||||
|
|
||||||
|
############################## TIME SERIES CONFIG #############################
|
||||||
|
|
||||||
|
# The maximal number of per-shard threads for cross-key queries when using cluster mode
|
||||||
|
# (TS.MRANGE, TS.MREVRANGE, TS.MGET, and TS.QUERYINDEX).
|
||||||
|
# Note: increasing this value may either increase or decrease the performance.
|
||||||
|
# integer, valid range: [1..16], default: 3
|
||||||
|
# This is a load-time configuration parameter.
|
||||||
|
#
|
||||||
|
# ts-num-threads 3
|
||||||
|
|
||||||
|
|
||||||
|
# Default compaction rules for newly created key with TS.ADD, TS.INCRBY, and TS.DECRBY.
|
||||||
|
# Has no effect on keys created with TS.CREATE.
|
||||||
|
# This default value is applied to each new time series upon its creation.
|
||||||
|
# string, see documentation for rules format, default: no compaction rules
|
||||||
|
#
|
||||||
|
# ts-compaction-policy ""
|
||||||
|
|
||||||
|
# Default chunk encoding for automatically-created compacted time series.
|
||||||
|
# This default value is applied to each new compacted time series automatically
|
||||||
|
# created when ts-compaction-policy is specified.
|
||||||
|
# valid values: COMPRESSED, UNCOMPRESSED, default: COMPRESSED
|
||||||
|
#
|
||||||
|
# ts-encoding COMPRESSED
|
||||||
|
|
||||||
|
|
||||||
|
# Default retention period, in milliseconds. 0 means no expiration.
|
||||||
|
# This default value is applied to each new time series upon its creation.
|
||||||
|
# If ts-compaction-policy is specified - it is overridden for created
|
||||||
|
# compactions as specified in ts-compaction-policy.
|
||||||
|
# integer, valid range: [0 .. LLONG_MAX], default: 0
|
||||||
|
#
|
||||||
|
# ts-retention-policy 0
|
||||||
|
|
||||||
|
# Default policy for handling insertion (TS.ADD and TS.MADD) of multiple
|
||||||
|
# samples with identical timestamps.
|
||||||
|
# This default value is applied to each new time series upon its creation.
|
||||||
|
# string, valid values: BLOCK, FIRST, LAST, MIN, MAX, SUM, default: BLOCK
|
||||||
|
#
|
||||||
|
# ts-duplicate-policy BLOCK
|
||||||
|
|
||||||
|
# Default initial allocation size, in bytes, for the data part of each new chunk
|
||||||
|
# This default value is applied to each new time series upon its creation.
|
||||||
|
# integer, valid range: [48 .. 1048576]; must be a multiple of 8, default: 4096
|
||||||
|
#
|
||||||
|
# ts-chunk-size-bytes 4096
|
||||||
|
|
||||||
|
# Default values for newly created time series.
|
||||||
|
# Many sensors report data periodically. Often, the difference between the measured
|
||||||
|
# value and the previous measured value is negligible and related to random noise
|
||||||
|
# or to measurement accuracy limitations. In such situations it may be preferable
|
||||||
|
# not to add the new measurement to the time series.
|
||||||
|
# A new sample is considered a duplicate and is ignored if the following conditions are met:
|
||||||
|
# - The time series is not a compaction;
|
||||||
|
# - The time series' DUPLICATE_POLICY IS LAST;
|
||||||
|
# - The sample is added in-order (timestamp >= max_timestamp);
|
||||||
|
# - The difference of the current timestamp from the previous timestamp
|
||||||
|
# (timestamp - max_timestamp) is less than or equal to ts-ignore-max-time-diff
|
||||||
|
# - The absolute value difference of the current value from the value at the previous maximum timestamp
|
||||||
|
# (abs(value - value_at_max_timestamp) is less than or equal to ts-ignore-max-val-diff.
|
||||||
|
# where max_timestamp is the timestamp of the sample with the largest timestamp in the time series,
|
||||||
|
# and value_at_max_timestamp is the value at max_timestamp.
|
||||||
|
# ts-ignore-max-time-diff: integer, valid range: [0 .. LLONG_MAX], default: 0
|
||||||
|
# ts-ignore-max-val-diff: double, Valid range: [0 .. DBL_MAX], default: 0
|
||||||
|
#
|
||||||
|
# ts-ignore-max-time-diff 0
|
||||||
|
# ts-ignore-max-val-diff 0
|
||||||
|
|
||||||
|
|
||||||
|
########################### BLOOM FILTERS CONFIG ##############################
|
||||||
|
|
||||||
|
# Defaults values for new Bloom filters created with BF.ADD, BF.MADD, BF.INSERT, and BF.RESERVE
|
||||||
|
# These defaults are applied to each new Bloom filter upon its creation.
|
||||||
|
|
||||||
|
# Error ratio
|
||||||
|
# The desired probability for false positives.
|
||||||
|
# For a false positive rate of 0.1% (1 in 1000) - the value should be 0.001.
|
||||||
|
# double, Valid range: (0 .. 1), value greater than 0.25 is treated as 0.25, default: 0.01
|
||||||
|
#
|
||||||
|
# bf-error-rate 0.01
|
||||||
|
|
||||||
|
# Initial capacity
|
||||||
|
# The number of entries intended to be added to the filter.
|
||||||
|
# integer, valid range: [1 .. 1GB], default: 100
|
||||||
|
#
|
||||||
|
# bf-initial-size 100
|
||||||
|
|
||||||
|
# Expansion factor
|
||||||
|
# When capacity is reached, an additional sub-filter is created.
|
||||||
|
# The size of the new sub-filter is the size of the last sub-filter multiplied
|
||||||
|
# by expansion.
|
||||||
|
# integer, [0 .. 32768]. 0 is equivalent to NONSCALING. default: 2
|
||||||
|
#
|
||||||
|
# bf-expansion-factor 2
|
||||||
|
|
||||||
|
|
||||||
|
########################### CUCKOO FILTERS CONFIG #############################
|
||||||
|
|
||||||
|
# Defaults values for new Cuckoo filters created with
|
||||||
|
# CF.ADD, CF.ADDNX, CF.INSERT, CF.INSERTNX, and CF.RESERVE
|
||||||
|
# These defaults are applied to each new Cuckoo filter upon its creation.
|
||||||
|
|
||||||
|
# Initial capacity
|
||||||
|
# A filter will likely not fill up to 100% of its capacity.
|
||||||
|
# Make sure to reserve extra capacity if you want to avoid expansions.
|
||||||
|
# value is rounded to the next 2^n integer.
|
||||||
|
# integer, valid range: [2*cf-bucket-size .. 1GB], default: 1024
|
||||||
|
#
|
||||||
|
# cf-initial-size 1024
|
||||||
|
|
||||||
|
# Number of items in each bucket
|
||||||
|
# The minimal false positive rate is 2/255 ~ 0.78% when bucket size of 1 is used.
|
||||||
|
# Larger buckets increase the error rate linearly, but improve the fill rate.
|
||||||
|
# integer, valid range: [1 .. 255], default: 2
|
||||||
|
#
|
||||||
|
# cf-bucket-size 2
|
||||||
|
|
||||||
|
# Maximum iterations
|
||||||
|
# Number of attempts to swap items between buckets before declaring filter
|
||||||
|
# as full and creating an additional filter.
|
||||||
|
# A lower value improves performance. A higher value improves fill rate.
|
||||||
|
# integer, Valid range: [1 .. 65535], default: 20
|
||||||
|
#
|
||||||
|
# cf-max-iterations 20
|
||||||
|
|
||||||
|
# Expansion factor
|
||||||
|
# When a new filter is created, its size is the size of the current filter
|
||||||
|
# multiplied by this factor.
|
||||||
|
# integer, Valid range: [0 .. 32768], 0 is equivalent to NONSCALING, default: 1
|
||||||
|
#
|
||||||
|
# cf-expansion-factor 1
|
||||||
|
|
||||||
|
# Maximum expansions
|
||||||
|
# integer, Valid range: [1 .. 65536], default: 32
|
||||||
|
#
|
||||||
|
# cf-max-expansions 32
|
||||||
|
|
||||||
|
|
||||||
|
################################## SECURITY ###################################
|
||||||
|
#
|
||||||
|
# The following is a list of command categories and their meanings:
|
||||||
|
#
|
||||||
|
# * search - Query engine related.
|
||||||
|
# * json - Data type: JSON related.
|
||||||
|
# * timeseries - Data type: time series related.
|
||||||
|
# * bloom - Data type: Bloom filter related.
|
||||||
|
# * cuckoo - Data type: cuckoo filter related.
|
||||||
|
# * topk - Data type: top-k related.
|
||||||
|
# * cms - Data type: count-min sketch related.
|
||||||
|
# * tdigest - Data type: t-digest related.
|
||||||
|
|
||||||
BIN
redis-8.2.1/redis-sentinel.exe
Normal file
BIN
redis-8.2.1/redis-sentinel.exe
Normal file
Binary file not shown.
BIN
redis-8.2.1/redis-server.exe
Normal file
BIN
redis-8.2.1/redis-server.exe
Normal file
Binary file not shown.
2361
redis-8.2.1/redis.conf
Normal file
2361
redis-8.2.1/redis.conf
Normal file
File diff suppressed because it is too large
Load Diff
1
redis-8.2.1/redis_6379.pid
Normal file
1
redis-8.2.1/redis_6379.pid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1656
|
||||||
361
redis-8.2.1/sentinel.conf
Normal file
361
redis-8.2.1/sentinel.conf
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
# Example sentinel.conf
|
||||||
|
|
||||||
|
# By default protected mode is disabled in sentinel mode. Sentinel is reachable
|
||||||
|
# from interfaces different than localhost. Make sure the sentinel instance is
|
||||||
|
# protected from the outside world via firewalling or other means.
|
||||||
|
protected-mode no
|
||||||
|
|
||||||
|
# port <sentinel-port>
|
||||||
|
# The port that this sentinel instance will run on
|
||||||
|
port 26379
|
||||||
|
|
||||||
|
# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it.
|
||||||
|
# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when
|
||||||
|
# daemonized.
|
||||||
|
daemonize no
|
||||||
|
|
||||||
|
# When running daemonized, Redis Sentinel writes a pid file in
|
||||||
|
# /var/run/redis-sentinel.pid by default. You can specify a custom pid file
|
||||||
|
# location here.
|
||||||
|
pidfile /var/run/redis-sentinel.pid
|
||||||
|
|
||||||
|
# Specify the server verbosity level.
|
||||||
|
# This can be one of:
|
||||||
|
# debug (a lot of information, useful for development/testing)
|
||||||
|
# verbose (many rarely useful info, but not a mess like the debug level)
|
||||||
|
# notice (moderately verbose, what you want in production probably)
|
||||||
|
# warning (only very important / critical messages are logged)
|
||||||
|
# nothing (nothing is logged)
|
||||||
|
loglevel notice
|
||||||
|
|
||||||
|
# Specify the log file name. Also the empty string can be used to force
|
||||||
|
# Sentinel to log on the standard output. Note that if you use standard
|
||||||
|
# output for logging but daemonize, logs will be sent to /dev/null
|
||||||
|
logfile ""
|
||||||
|
|
||||||
|
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
|
||||||
|
# and optionally update the other syslog parameters to suit your needs.
|
||||||
|
# syslog-enabled no
|
||||||
|
|
||||||
|
# Specify the syslog identity.
|
||||||
|
# syslog-ident sentinel
|
||||||
|
|
||||||
|
# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
|
||||||
|
# syslog-facility local0
|
||||||
|
|
||||||
|
# sentinel announce-ip <ip>
|
||||||
|
# sentinel announce-port <port>
|
||||||
|
#
|
||||||
|
# The above two configuration directives are useful in environments where,
|
||||||
|
# because of NAT, Sentinel is reachable from outside via a non-local address.
|
||||||
|
#
|
||||||
|
# When announce-ip is provided, the Sentinel will claim the specified IP address
|
||||||
|
# in HELLO messages used to gossip its presence, instead of auto-detecting the
|
||||||
|
# local address as it usually does.
|
||||||
|
#
|
||||||
|
# Similarly when announce-port is provided and is valid and non-zero, Sentinel
|
||||||
|
# will announce the specified TCP port.
|
||||||
|
#
|
||||||
|
# The two options don't need to be used together, if only announce-ip is
|
||||||
|
# provided, the Sentinel will announce the specified IP and the server port
|
||||||
|
# as specified by the "port" option. If only announce-port is provided, the
|
||||||
|
# Sentinel will announce the auto-detected local IP and the specified port.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# sentinel announce-ip 1.2.3.4
|
||||||
|
|
||||||
|
# dir <working-directory>
|
||||||
|
# Every long running process should have a well-defined working directory.
|
||||||
|
# For Redis Sentinel to chdir to /tmp at startup is the simplest thing
|
||||||
|
# for the process to don't interfere with administrative tasks such as
|
||||||
|
# unmounting filesystems.
|
||||||
|
dir /tmp
|
||||||
|
|
||||||
|
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
|
||||||
|
#
|
||||||
|
# Tells Sentinel to monitor this master, and to consider it in O_DOWN
|
||||||
|
# (Objectively Down) state only if at least <quorum> sentinels agree.
|
||||||
|
#
|
||||||
|
# Note that whatever is the ODOWN quorum, a Sentinel will require to
|
||||||
|
# be elected by the majority of the known Sentinels in order to
|
||||||
|
# start a failover, so no failover can be performed in minority.
|
||||||
|
#
|
||||||
|
# Replicas are auto-discovered, so you don't need to specify replicas in
|
||||||
|
# any way. Sentinel itself will rewrite this configuration file adding
|
||||||
|
# the replicas using additional configuration options.
|
||||||
|
# Also note that the configuration file is rewritten when a
|
||||||
|
# replica is promoted to master.
|
||||||
|
#
|
||||||
|
# Note: master name should not include special characters or spaces.
|
||||||
|
# The valid charset is A-z 0-9 and the three characters ".-_".
|
||||||
|
sentinel monitor mymaster 127.0.0.1 6379 2
|
||||||
|
|
||||||
|
# sentinel auth-pass <master-name> <password>
|
||||||
|
#
|
||||||
|
# Set the password to use to authenticate with the master and replicas.
|
||||||
|
# Useful if there is a password set in the Redis instances to monitor.
|
||||||
|
#
|
||||||
|
# Note that the master password is also used for replicas, so it is not
|
||||||
|
# possible to set a different password in masters and replicas instances
|
||||||
|
# if you want to be able to monitor these instances with Sentinel.
|
||||||
|
#
|
||||||
|
# However you can have Redis instances without the authentication enabled
|
||||||
|
# mixed with Redis instances requiring the authentication (as long as the
|
||||||
|
# password set is the same for all the instances requiring the password) as
|
||||||
|
# the AUTH command will have no effect in Redis instances with authentication
|
||||||
|
# switched off.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
|
||||||
|
|
||||||
|
# sentinel auth-user <master-name> <username>
|
||||||
|
#
|
||||||
|
# This is useful in order to authenticate to instances having ACL capabilities,
|
||||||
|
# that is, running Redis 6.0 or greater. When just auth-pass is provided the
|
||||||
|
# Sentinel instance will authenticate to Redis using the old "AUTH <pass>"
|
||||||
|
# method. When also an username is provided, it will use "AUTH <user> <pass>".
|
||||||
|
# In the Redis servers side, the ACL to provide just minimal access to
|
||||||
|
# Sentinel instances, should be configured along the following lines:
|
||||||
|
#
|
||||||
|
# user sentinel-user >somepassword +client +subscribe +publish \
|
||||||
|
# +ping +info +multi +slaveof +config +client +exec on
|
||||||
|
|
||||||
|
# sentinel down-after-milliseconds <master-name> <milliseconds>
|
||||||
|
#
|
||||||
|
# Number of milliseconds the master (or any attached replica or sentinel) should
|
||||||
|
# be unreachable (as in, not acceptable reply to PING, continuously, for the
|
||||||
|
# specified period) in order to consider it in S_DOWN state (Subjectively
|
||||||
|
# Down).
|
||||||
|
#
|
||||||
|
# Default is 30 seconds.
|
||||||
|
sentinel down-after-milliseconds mymaster 30000
|
||||||
|
|
||||||
|
# IMPORTANT NOTE: starting with Redis 6.2 ACL capability is supported for
|
||||||
|
# Sentinel mode, please refer to the Redis website https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/
|
||||||
|
# for more details.
|
||||||
|
|
||||||
|
# Sentinel's ACL users are defined in the following format:
|
||||||
|
#
|
||||||
|
# user <username> ... acl rules ...
|
||||||
|
#
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# user worker +@admin +@connection ~* on >ffa9203c493aa99
|
||||||
|
#
|
||||||
|
# For more information about ACL configuration please refer to the Redis
|
||||||
|
# website at https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/ and redis server configuration
|
||||||
|
# template redis.conf.
|
||||||
|
|
||||||
|
# ACL LOG
|
||||||
|
#
|
||||||
|
# The ACL Log tracks failed commands and authentication events associated
|
||||||
|
# with ACLs. The ACL Log is useful to troubleshoot failed commands blocked
|
||||||
|
# by ACLs. The ACL Log is stored in memory. You can reclaim memory with
|
||||||
|
# ACL LOG RESET. Define the maximum entry length of the ACL Log below.
|
||||||
|
acllog-max-len 128
|
||||||
|
|
||||||
|
# Using an external ACL file
|
||||||
|
#
|
||||||
|
# Instead of configuring users here in this file, it is possible to use
|
||||||
|
# a stand-alone file just listing users. The two methods cannot be mixed:
|
||||||
|
# if you configure users here and at the same time you activate the external
|
||||||
|
# ACL file, the server will refuse to start.
|
||||||
|
#
|
||||||
|
# The format of the external ACL user file is exactly the same as the
|
||||||
|
# format that is used inside redis.conf to describe users.
|
||||||
|
#
|
||||||
|
# aclfile /etc/redis/sentinel-users.acl
|
||||||
|
|
||||||
|
# requirepass <password>
|
||||||
|
#
|
||||||
|
# You can configure Sentinel itself to require a password, however when doing
|
||||||
|
# so Sentinel will try to authenticate with the same password to all the
|
||||||
|
# other Sentinels. So you need to configure all your Sentinels in a given
|
||||||
|
# group with the same "requirepass" password. Check the following documentation
|
||||||
|
# for more info: https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/
|
||||||
|
#
|
||||||
|
# IMPORTANT NOTE: starting with Redis 6.2 "requirepass" is a compatibility
|
||||||
|
# layer on top of the ACL system. The option effect will be just setting
|
||||||
|
# the password for the default user. Clients will still authenticate using
|
||||||
|
# AUTH <password> as usually, or more explicitly with AUTH default <password>
|
||||||
|
# if they follow the new protocol: both will work.
|
||||||
|
#
|
||||||
|
# New config files are advised to use separate authentication control for
|
||||||
|
# incoming connections (via ACL), and for outgoing connections (via
|
||||||
|
# sentinel-user and sentinel-pass)
|
||||||
|
#
|
||||||
|
# The requirepass is not compatible with aclfile option and the ACL LOAD
|
||||||
|
# command, these will cause requirepass to be ignored.
|
||||||
|
|
||||||
|
# sentinel sentinel-user <username>
|
||||||
|
#
|
||||||
|
# You can configure Sentinel to authenticate with other Sentinels with specific
|
||||||
|
# user name.
|
||||||
|
|
||||||
|
# sentinel sentinel-pass <password>
|
||||||
|
#
|
||||||
|
# The password for Sentinel to authenticate with other Sentinels. If sentinel-user
|
||||||
|
# is not configured, Sentinel will use 'default' user with sentinel-pass to authenticate.
|
||||||
|
|
||||||
|
# sentinel parallel-syncs <master-name> <numreplicas>
|
||||||
|
#
|
||||||
|
# How many replicas we can reconfigure to point to the new replica simultaneously
|
||||||
|
# during the failover. Use a low number if you use the replicas to serve query
|
||||||
|
# to avoid that all the replicas will be unreachable at about the same
|
||||||
|
# time while performing the synchronization with the master.
|
||||||
|
sentinel parallel-syncs mymaster 1
|
||||||
|
|
||||||
|
# sentinel failover-timeout <master-name> <milliseconds>
|
||||||
|
#
|
||||||
|
# Specifies the failover timeout in milliseconds. It is used in many ways:
|
||||||
|
#
|
||||||
|
# - The time needed to re-start a failover after a previous failover was
|
||||||
|
# already tried against the same master by a given Sentinel, is two
|
||||||
|
# times the failover timeout.
|
||||||
|
#
|
||||||
|
# - The time needed for a replica replicating to a wrong master according
|
||||||
|
# to a Sentinel current configuration, to be forced to replicate
|
||||||
|
# with the right master, is exactly the failover timeout (counting since
|
||||||
|
# the moment a Sentinel detected the misconfiguration).
|
||||||
|
#
|
||||||
|
# - The time needed to cancel a failover that is already in progress but
|
||||||
|
# did not produced any configuration change (SLAVEOF NO ONE yet not
|
||||||
|
# acknowledged by the promoted replica).
|
||||||
|
#
|
||||||
|
# - The maximum time a failover in progress waits for all the replicas to be
|
||||||
|
# reconfigured as replicas of the new master. However even after this time
|
||||||
|
# the replicas will be reconfigured by the Sentinels anyway, but not with
|
||||||
|
# the exact parallel-syncs progression as specified.
|
||||||
|
#
|
||||||
|
# Default is 3 minutes.
|
||||||
|
sentinel failover-timeout mymaster 180000
|
||||||
|
|
||||||
|
# SCRIPTS EXECUTION
|
||||||
|
#
|
||||||
|
# sentinel notification-script and sentinel reconfig-script are used in order
|
||||||
|
# to configure scripts that are called to notify the system administrator
|
||||||
|
# or to reconfigure clients after a failover. The scripts are executed
|
||||||
|
# with the following rules for error handling:
|
||||||
|
#
|
||||||
|
# If script exits with "1" the execution is retried later (up to a maximum
|
||||||
|
# number of times currently set to 10).
|
||||||
|
#
|
||||||
|
# If script exits with "2" (or an higher value) the script execution is
|
||||||
|
# not retried.
|
||||||
|
#
|
||||||
|
# If script terminates because it receives a signal the behavior is the same
|
||||||
|
# as exit code 1.
|
||||||
|
#
|
||||||
|
# A script has a maximum running time of 60 seconds. After this limit is
|
||||||
|
# reached the script is terminated with a SIGKILL and the execution retried.
|
||||||
|
|
||||||
|
# NOTIFICATION SCRIPT
|
||||||
|
#
|
||||||
|
# sentinel notification-script <master-name> <script-path>
|
||||||
|
#
|
||||||
|
# Call the specified notification script for any sentinel event that is
|
||||||
|
# generated in the WARNING level (for instance -sdown, -odown, and so forth).
|
||||||
|
# This script should notify the system administrator via email, SMS, or any
|
||||||
|
# other messaging system, that there is something wrong with the monitored
|
||||||
|
# Redis systems.
|
||||||
|
#
|
||||||
|
# The script is called with just two arguments: the first is the event type
|
||||||
|
# and the second the event description.
|
||||||
|
#
|
||||||
|
# The script must exist and be executable in order for sentinel to start if
|
||||||
|
# this option is provided.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# sentinel notification-script mymaster /var/redis/notify.sh
|
||||||
|
|
||||||
|
# CLIENTS RECONFIGURATION SCRIPT
|
||||||
|
#
|
||||||
|
# sentinel client-reconfig-script <master-name> <script-path>
|
||||||
|
#
|
||||||
|
# When the master changed because of a failover a script can be called in
|
||||||
|
# order to perform application-specific tasks to notify the clients that the
|
||||||
|
# configuration has changed and the master is at a different address.
|
||||||
|
#
|
||||||
|
# The following arguments are passed to the script:
|
||||||
|
#
|
||||||
|
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
|
||||||
|
#
|
||||||
|
# <state> is currently always "start"
|
||||||
|
# <role> is either "leader" or "observer"
|
||||||
|
#
|
||||||
|
# The arguments from-ip, from-port, to-ip, to-port are used to communicate
|
||||||
|
# the old address of the master and the new address of the elected replica
|
||||||
|
# (now a master).
|
||||||
|
#
|
||||||
|
# This script should be resistant to multiple invocations.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
|
||||||
|
|
||||||
|
# SECURITY
|
||||||
|
#
|
||||||
|
# By default SENTINEL SET will not be able to change the notification-script
|
||||||
|
# and client-reconfig-script at runtime. This avoids a trivial security issue
|
||||||
|
# where clients can set the script to anything and trigger a failover in order
|
||||||
|
# to get the program executed.
|
||||||
|
|
||||||
|
sentinel deny-scripts-reconfig yes
|
||||||
|
|
||||||
|
# REDIS COMMANDS RENAMING (DEPRECATED)
|
||||||
|
#
|
||||||
|
# WARNING: avoid using this option if possible, instead use ACLs.
|
||||||
|
#
|
||||||
|
# Sometimes the Redis server has certain commands, that are needed for Sentinel
|
||||||
|
# to work correctly, renamed to unguessable strings. This is often the case
|
||||||
|
# of CONFIG and SLAVEOF in the context of providers that provide Redis as
|
||||||
|
# a service, and don't want the customers to reconfigure the instances outside
|
||||||
|
# of the administration console.
|
||||||
|
#
|
||||||
|
# In such case it is possible to tell Sentinel to use different command names
|
||||||
|
# instead of the normal ones. For example if the master "mymaster", and the
|
||||||
|
# associated replicas, have "CONFIG" all renamed to "GUESSME", I could use:
|
||||||
|
#
|
||||||
|
# SENTINEL rename-command mymaster CONFIG GUESSME
|
||||||
|
#
|
||||||
|
# After such configuration is set, every time Sentinel would use CONFIG it will
|
||||||
|
# use GUESSME instead. Note that there is no actual need to respect the command
|
||||||
|
# case, so writing "config guessme" is the same in the example above.
|
||||||
|
#
|
||||||
|
# SENTINEL SET can also be used in order to perform this configuration at runtime.
|
||||||
|
#
|
||||||
|
# In order to set a command back to its original name (undo the renaming), it
|
||||||
|
# is possible to just rename a command to itself:
|
||||||
|
#
|
||||||
|
# SENTINEL rename-command mymaster CONFIG CONFIG
|
||||||
|
|
||||||
|
# HOSTNAMES SUPPORT
|
||||||
|
#
|
||||||
|
# Normally Sentinel uses only IP addresses and requires SENTINEL MONITOR
|
||||||
|
# to specify an IP address. Also, it requires the Redis replica-announce-ip
|
||||||
|
# keyword to specify only IP addresses.
|
||||||
|
#
|
||||||
|
# You may enable hostnames support by enabling resolve-hostnames. Note
|
||||||
|
# that you must make sure your DNS is configured properly and that DNS
|
||||||
|
# resolution does not introduce very long delays.
|
||||||
|
#
|
||||||
|
SENTINEL resolve-hostnames no
|
||||||
|
|
||||||
|
# When resolve-hostnames is enabled, Sentinel still uses IP addresses
|
||||||
|
# when exposing instances to users, configuration files, etc. If you want
|
||||||
|
# to retain the hostnames when announced, enable announce-hostnames below.
|
||||||
|
#
|
||||||
|
SENTINEL announce-hostnames no
|
||||||
|
|
||||||
|
# When master_reboot_down_after_period is set to 0, Sentinel does not fail over
|
||||||
|
# when receiving a -LOADING response from a master. This was the only supported
|
||||||
|
# behavior before version 7.0.
|
||||||
|
#
|
||||||
|
# Otherwise, Sentinel will use this value as the time (in ms) it is willing to
|
||||||
|
# accept a -LOADING response after a master has been rebooted, before failing
|
||||||
|
# over.
|
||||||
|
|
||||||
|
SENTINEL master-reboot-down-after-period mymaster 0
|
||||||
Reference in New Issue
Block a user