mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 22:18:07 +08:00
fix: 解决 Node 运行环境状态异常问题 (#4197)
This commit is contained in:
parent
a33eabb4f0
commit
6ce35b723b
@ -203,3 +203,19 @@ func (b *BaseApi) OperateNodeModules(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags Runtime
|
||||
// @Summary Sync runtime status
|
||||
// @Description 同步运行环境状态
|
||||
// @Accept json
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /runtimes/sync [post]
|
||||
func (b *BaseApi) SyncStatus(c *gin.Context) {
|
||||
err := runtimeService.SyncRuntimeStatus()
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ type IRuntimeService interface {
|
||||
GetNodeModules(req request.NodeModuleReq) ([]response.NodeModule, error)
|
||||
OperateNodeModules(req request.NodeModuleOperateReq) error
|
||||
SyncForRestart() error
|
||||
SyncRuntimeStatus() error
|
||||
}
|
||||
|
||||
func NewRuntimeService() IRuntimeService {
|
||||
@ -586,3 +587,16 @@ func (r *RuntimeService) SyncForRestart() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RuntimeService) SyncRuntimeStatus() error {
|
||||
runtimes, err := runtimeRepo.List()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, runtime := range runtimes {
|
||||
if runtime.Type == constant.RuntimeNode {
|
||||
_ = SyncRuntimeContainerStatus(&runtime)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -181,33 +181,20 @@ func SyncRuntimeContainerStatus(runtime *model.Runtime) error {
|
||||
}
|
||||
container := containers[0]
|
||||
|
||||
interval := 10 * time.Second
|
||||
retries := 60
|
||||
for i := 0; i < retries; i++ {
|
||||
resp, err := cli.InspectContainer(container.ID)
|
||||
if err != nil {
|
||||
time.Sleep(interval)
|
||||
continue
|
||||
switch container.State {
|
||||
case "exited":
|
||||
runtime.Status = constant.RuntimeError
|
||||
case "running":
|
||||
runtime.Status = constant.RuntimeRunning
|
||||
case "paused":
|
||||
runtime.Status = constant.RuntimeStopped
|
||||
default:
|
||||
if runtime.Status != constant.RuntimeBuildIng {
|
||||
runtime.Status = constant.RuntimeStopped
|
||||
}
|
||||
if resp.State.Health != nil {
|
||||
status := strings.ToLower(resp.State.Health.Status)
|
||||
switch status {
|
||||
case "starting":
|
||||
runtime.Status = constant.RuntimeStarting
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
case "healthy":
|
||||
runtime.Status = constant.RuntimeRunning
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
return nil
|
||||
case "unhealthy":
|
||||
runtime.Status = constant.RuntimeUnhealthy
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
time.Sleep(interval)
|
||||
}
|
||||
return nil
|
||||
|
||||
return runtimeRepo.Save(runtime)
|
||||
}
|
||||
|
||||
func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) {
|
||||
|
@ -20,6 +20,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
groupRouter.POST("/del", baseApi.DeleteRuntime)
|
||||
groupRouter.POST("/update", baseApi.UpdateRuntime)
|
||||
groupRouter.GET("/:id", baseApi.GetRuntime)
|
||||
groupRouter.POST("/sync", baseApi.SyncStatus)
|
||||
|
||||
groupRouter.POST("/node/package", baseApi.GetNodePackageRunScript)
|
||||
groupRouter.POST("/operate", baseApi.OperateRuntime)
|
||||
|
@ -58,3 +58,7 @@ export const UpdatePHPExtensions = (req: Runtime.PHPExtensionsUpdate) => {
|
||||
export const DeletePHPExtensions = (req: Runtime.PHPExtensionsDelete) => {
|
||||
return http.post<any>(`/runtimes/php/extensions/del`, req);
|
||||
};
|
||||
|
||||
export const SyncRuntime = () => {
|
||||
return http.post(`/runtimes/sync`, {});
|
||||
};
|
||||
|
@ -2240,6 +2240,35 @@ const message = {
|
||||
javaFileter: 'Java Dangerous File Filtering',
|
||||
scannerFilter: 'Scanner filter',
|
||||
escapeFilter: 'escape filter',
|
||||
customRule: 'custom rule',
|
||||
httpMethod: 'HTTP method filter',
|
||||
fileExt: 'File upload limit',
|
||||
fileExtHelper: 'File extensions that are prohibited from uploading',
|
||||
deny: 'forbidden',
|
||||
allow: 'only allow',
|
||||
field: 'match object',
|
||||
pattern: 'matching condition',
|
||||
ruleContent: 'match content',
|
||||
contain: 'include',
|
||||
equal: 'equal',
|
||||
regex: 'regular expression',
|
||||
notEqual: 'Not equal to',
|
||||
customRuleHelper: 'Perform corresponding actions based on condition matching',
|
||||
actionAllow: 'Allow',
|
||||
blockIP: 'Block IP',
|
||||
code: 'return status code',
|
||||
noRes: 'Disconnect 444',
|
||||
badReq: 'Parameter error 400',
|
||||
forbidden: 'Access Forbidden 403',
|
||||
serverErr: 'Server error 500',
|
||||
resHtml: 'Response page',
|
||||
allowHelper: 'Allowing access will skip subsequent WAF rules, please use with caution',
|
||||
captcha: 'human-machine verification',
|
||||
fiveSeconds: '5 seconds verification',
|
||||
location: 'Region',
|
||||
redisConfig: 'Redis configuration',
|
||||
redisHelper: 'Enable Redis to persist temporarily blocked IPs',
|
||||
wafHelper: 'All websites will lose protection after closing',
|
||||
},
|
||||
monitor: {
|
||||
name: 'Website Monitor',
|
||||
|
@ -2094,6 +2094,35 @@ const message = {
|
||||
javaFileter: 'Java 危險檔案過濾',
|
||||
scannerFilter: '掃描器過濾',
|
||||
escapeFilter: '轉義過濾',
|
||||
customRule: '自訂規則',
|
||||
httpMethod: 'HTTP 方法過濾',
|
||||
fileExt: '檔案上傳限制',
|
||||
fileExtHelper: '禁止上傳的檔案副檔名',
|
||||
deny: '禁止',
|
||||
allow: '只允許',
|
||||
field: '匹配對象',
|
||||
pattern: '符合條件',
|
||||
ruleContent: '符合內容',
|
||||
contain: '包含',
|
||||
equal: '等於',
|
||||
regex: '正規表示式',
|
||||
notEqual: '不等於',
|
||||
customRuleHelper: '根據條件匹配執行對應動作',
|
||||
actionAllow: '允許',
|
||||
blockIP: '封鎖 IP',
|
||||
code: '返回狀態碼',
|
||||
noRes: '斷開連線 444',
|
||||
badReq: '參數錯誤 400',
|
||||
forbidden: '禁止訪問 403',
|
||||
serverErr: '伺服器錯誤 500',
|
||||
resHtml: '回應頁面',
|
||||
allowHelper: '允許訪問會跳過後續的 WAF 規則,請謹慎使用',
|
||||
captcha: '人機驗證',
|
||||
fiveSeconds: '5 秒驗證',
|
||||
location: '地區',
|
||||
redisConfig: 'Redis 配置',
|
||||
redisHelper: '開啟 Redis 可以將暫時拉黑的 IP 持久化',
|
||||
wafHelper: '關閉之後所有網站將失去防護',
|
||||
},
|
||||
monitor: {
|
||||
name: '網站監控',
|
||||
|
@ -2011,6 +2011,7 @@ const message = {
|
||||
},
|
||||
xpack: {
|
||||
name: '专业版',
|
||||
menu: '高级功能',
|
||||
waf: {
|
||||
name: 'WAF',
|
||||
blackWhite: '黑白名单',
|
||||
@ -2065,7 +2066,7 @@ const message = {
|
||||
cookieHelper: '禁止请求中携带恶意 Cookie',
|
||||
headerDefense: 'Header 规则',
|
||||
headerHelper: '禁止请求中携带恶意 Header',
|
||||
httpRule: 'HTTP 请求方法规则',
|
||||
httpRule: 'HTTP 规则',
|
||||
httpHelper: '限制网站的请求方法类型',
|
||||
geoRule: '地区访问限制',
|
||||
geoHelper: '限制某些地区访问你的网站',
|
||||
@ -2094,6 +2095,35 @@ const message = {
|
||||
javaFileter: 'Java 危险文件过滤',
|
||||
scannerFilter: '扫描器过滤',
|
||||
escapeFilter: '转义过滤',
|
||||
customRule: '自定义规则',
|
||||
httpMethod: 'HTTP 方法过滤',
|
||||
fileExt: '文件上传限制',
|
||||
fileExtHelper: '禁止上传的文件扩展名',
|
||||
deny: '禁止',
|
||||
allow: '仅允许',
|
||||
field: '匹配对象',
|
||||
pattern: '匹配条件',
|
||||
ruleContent: '匹配内容',
|
||||
contain: '包含',
|
||||
equal: '等于',
|
||||
regex: '正则表达式',
|
||||
notEqual: '不等于',
|
||||
customRuleHelper: '根据条件匹配执行相应动作',
|
||||
actionAllow: '允许',
|
||||
blockIP: '封禁 IP',
|
||||
code: '返回状态码',
|
||||
noRes: '断开连接 444',
|
||||
badReq: '参数错误 400',
|
||||
forbidden: '禁止访问 403',
|
||||
serverErr: '服务器错误 500',
|
||||
resHtml: '响应页面',
|
||||
allowHelper: '允许访问会跳过后续的 WAF 规则,请谨慎使用',
|
||||
captcha: '人机验证',
|
||||
fiveSeconds: '5 秒验证',
|
||||
location: '地区',
|
||||
redisConfig: 'Redis 配置',
|
||||
redisHelper: '开启 Redis 可以将临时拉黑的 IP 持久化',
|
||||
wafHelper: '关闭之后所有网站将失去防护',
|
||||
},
|
||||
monitor: {
|
||||
name: '网站监控',
|
||||
|
@ -90,7 +90,7 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
import { OperateRuntime, SearchRuntimes } from '@/api/modules/runtime';
|
||||
import { OperateRuntime, SearchRuntimes, SyncRuntime } from '@/api/modules/runtime';
|
||||
import { dateFormat } from '@/utils/util';
|
||||
import OperateNode from '@/views/website/runtime/node/operate/index.vue';
|
||||
import Status from '@/components/status/index.vue';
|
||||
@ -192,6 +192,10 @@ const search = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const sync = () => {
|
||||
SyncRuntime();
|
||||
};
|
||||
|
||||
const openModules = (row: Runtime.Runtime) => {
|
||||
moduleRef.value.acceptParams({ id: row.id, packageManager: row.params['PACKAGE_MANAGER'] });
|
||||
};
|
||||
@ -243,10 +247,12 @@ const toFolder = (folder: string) => {
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
sync();
|
||||
search();
|
||||
timer = setInterval(() => {
|
||||
search();
|
||||
}, 10000 * 3);
|
||||
sync();
|
||||
}, 1000 * 10);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user