mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-04 00:10:25 +08:00
feat: 新增linux进程操作
This commit is contained in:
@@ -51,8 +51,8 @@
|
||||
|
||||
<el-row type="flex" justify="center">
|
||||
<slot name="btns" :submitDisabled="submitDisabled" :data="form" :submit="submit">
|
||||
<el-button @click="reset" size="mini">重 置</el-button>
|
||||
<el-button type="primary" @click="submit" size="mini">保 存</el-button>
|
||||
<el-button @click="reset" size="small">重 置</el-button>
|
||||
<el-button type="primary" @click="submit" size="small">保 存</el-button>
|
||||
</slot>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<dynamic-form ref="df" :form-info="formInfo" :form-data="formData" @submitSuccess="submitSuccess">
|
||||
<template #btns="props">
|
||||
<slot name="btns">
|
||||
<el-button :disabled="props.submitDisabled" type="primary" @click="props.submit" size="mini">保 存</el-button>
|
||||
<el-button :disabled="props.submitDisabled" @click="close()" size="mini">取 消</el-button>
|
||||
<el-button :disabled="props.submitDisabled" type="primary" @click="props.submit" size="small">保 存</el-button>
|
||||
<el-button :disabled="props.submitDisabled" @click="close()" size="small">取 消</el-button>
|
||||
</slot>
|
||||
</template>
|
||||
</dynamic-form>
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
:min="0"
|
||||
:max="9999"
|
||||
@change="setLocalThemeConfig"
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 90px"
|
||||
>
|
||||
</el-input-number>
|
||||
@@ -236,7 +236,7 @@
|
||||
<div class="layout-breadcrumb-seting-bar-flex-value">
|
||||
<el-input
|
||||
v-model="getThemeConfig.wartermarkText"
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 90px"
|
||||
@input="onWartermarkTextInput($event)"
|
||||
></el-input>
|
||||
@@ -251,7 +251,7 @@
|
||||
<el-select
|
||||
v-model="getThemeConfig.tagsStyle"
|
||||
placeholder="请选择"
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 90px"
|
||||
@change="setLocalThemeConfig"
|
||||
>
|
||||
@@ -268,7 +268,7 @@
|
||||
<el-select
|
||||
v-model="getThemeConfig.animation"
|
||||
placeholder="请选择"
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 90px"
|
||||
@change="setLocalThemeConfig"
|
||||
>
|
||||
@@ -284,7 +284,7 @@
|
||||
<el-select
|
||||
v-model="getThemeConfig.columnsAsideStyle"
|
||||
placeholder="请选择"
|
||||
size="mini"
|
||||
size="small"
|
||||
style="width: 90px"
|
||||
@change="setLocalThemeConfig"
|
||||
>
|
||||
|
||||
@@ -171,7 +171,6 @@ import { codemirror } from '@/components/codemirror';
|
||||
import { getSession } from '@/common/utils/storage';
|
||||
import enums from './enums';
|
||||
import config from '@/common/config';
|
||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FileManage',
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" :loading="btnLoading" @click="btnOk" size="mini">确 定</el-button>
|
||||
<el-button @click="cancel()" size="mini">取 消</el-button>
|
||||
<el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
|
||||
<el-button @click="cancel()">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -53,17 +53,12 @@
|
||||
{{ $filters.dateFormat(scope.row.createTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="creator" label="创建者" min-width="55"></el-table-column>
|
||||
<!-- <el-table-column prop="updateTime" label="更新时间" min-width="160">
|
||||
<template #default="scope">
|
||||
{{ $filters.dateFormat(scope.row.updateTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="modifier" label="修改者" :min-width="55"></el-table-column> -->
|
||||
<el-table-column prop="creator" label="创建者" min-width="60"></el-table-column>
|
||||
<el-table-column label="操作" min-width="260" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button type="success" @click="serviceManager(scope.row)" plain size="small">脚本</el-button>
|
||||
<el-button v-auth="'machine:terminal'" type="primary" @click="showTerminal(scope.row)" plain size="small">终端</el-button>
|
||||
<el-button @click="showProcess(scope.row)" plain size="small">进程</el-button>
|
||||
<el-button :disabled="!scope.row.hasCli" type="danger" @click="closeCli(scope.row)" plain size="small">关闭连接</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -91,6 +86,8 @@
|
||||
<monitor ref="monitorDialogRef" :machineId="monitorDialog.machineId" />
|
||||
</el-dialog> -->
|
||||
|
||||
<process-list v-model:visible="processDialog.visible" v-model:machineId="processDialog.machineId" />
|
||||
|
||||
<service-manage :title="serviceDialog.title" v-model:visible="serviceDialog.visible" v-model:machineId="serviceDialog.machineId" />
|
||||
|
||||
<file-manage :title="fileDialog.title" v-model:visible="fileDialog.visible" v-model:machineId="fileDialog.machineId" />
|
||||
@@ -107,11 +104,13 @@ import { projectApi } from '../project/api.ts';
|
||||
import ServiceManage from './ServiceManage.vue';
|
||||
import FileManage from './FileManage.vue';
|
||||
import MachineEdit from './MachineEdit.vue';
|
||||
import ProcessList from './ProcessList.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MachineList',
|
||||
components: {
|
||||
ServiceManage,
|
||||
ProcessList,
|
||||
FileManage,
|
||||
MachineEdit,
|
||||
},
|
||||
@@ -142,6 +141,10 @@ export default defineComponent({
|
||||
machineId: 0,
|
||||
title: '',
|
||||
},
|
||||
processDialog: {
|
||||
visible: false,
|
||||
machineId: 0,
|
||||
},
|
||||
fileDialog: {
|
||||
visible: false,
|
||||
machineId: 0,
|
||||
@@ -256,6 +259,11 @@ export default defineComponent({
|
||||
state.data = res;
|
||||
};
|
||||
|
||||
const showProcess = (row: any) => {
|
||||
state.processDialog.machineId = row.id;
|
||||
state.processDialog.visible = true;
|
||||
};
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
choose,
|
||||
@@ -266,6 +274,7 @@ export default defineComponent({
|
||||
deleteMachine,
|
||||
closeCli,
|
||||
serviceManager,
|
||||
showProcess,
|
||||
submitSuccess,
|
||||
fileManage,
|
||||
search,
|
||||
|
||||
203
mayfly_go_web/src/views/ops/machine/ProcessList.vue
Normal file
203
mayfly_go_web/src/views/ops/machine/ProcessList.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<div class="file-manage">
|
||||
<el-dialog title="进程信息" v-model="dialogVisible" :destroy-on-close="true" :show-close="true" :before-close="handleClose" width="65%">
|
||||
<div class="toolbar">
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<el-input size="small" placeholder="进程名" v-model="params.name" plain clearable></el-input>
|
||||
</el-col>
|
||||
<el-col :span="4" class="ml5">
|
||||
<el-select @change="getProcess" size="small" v-model="params.sortType" placeholder="请选择排序类型">
|
||||
<el-option key="cpu" label="cpu降序" value="1"> </el-option>
|
||||
<el-option key="cpu" label="mem降序" value="2"> </el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="4" class="ml5">
|
||||
<el-select @change="getProcess" size="small" v-model="params.count" placeholder="请选择进程个数">
|
||||
<el-option key="10" label="10" value="10"> </el-option>
|
||||
<el-option key="15" label="15" value="15"> </el-option>
|
||||
<el-option key="20" label="20" value="20"> </el-option>
|
||||
<el-option key="25" label="25" value="25"> </el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-button class="ml5" @click="getProcess" type="primary" icon="tickets" size="small" plain>刷新</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<el-table :data="processList" size="small" style="width: 100%" empty-text="获取进程中...">
|
||||
<el-table-column prop="user" label="USER" :min-width="50"> </el-table-column>
|
||||
<el-table-column prop="pid" label="PID" :min-width="50" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="cpu" label="%CPU" :min-width="40"> </el-table-column>
|
||||
<el-table-column prop="mem" label="%MEM" :min-width="42"> </el-table-column>
|
||||
<el-table-column prop="vsz" label="vsz" :min-width="55">
|
||||
<template #header>
|
||||
VSZ
|
||||
<el-tooltip class="box-item" effect="dark" content="虚拟内存" placement="top">
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="rss" :min-width="52">
|
||||
<template #header>
|
||||
RSS
|
||||
<el-tooltip class="box-item" effect="dark" content="固定内存" placement="top">
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stat" :min-width="50">
|
||||
<template #header>
|
||||
STAT
|
||||
<el-tooltip class="box-item" effect="dark" content="进程状态" placement="top">
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="start" :min-width="50">
|
||||
<template #header>
|
||||
START
|
||||
<el-tooltip class="box-item" effect="dark" content="启动时间" placement="top">
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="time" :min-width="50">
|
||||
<template #header>
|
||||
TIME
|
||||
<el-tooltip class="box-item" effect="dark" content="该进程实际使用CPU运作的时间" placement="top">
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="command" label="command" :min-width="120" show-overflow-tooltip> </el-table-column>
|
||||
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-popconfirm title="确定终止该进程?" @confirm="confirmKillProcess(scope.row.pid)">
|
||||
<template #reference>
|
||||
<el-button v-auth="'machine:killprocess'" type="danger" icon="delete" size="small" plain>终止</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<!-- <el-button @click="addFiles(scope.row)" type="danger" icon="delete" size="small" plain>终止</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, toRefs, reactive, watch, defineComponent } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { machineApi } from './api';
|
||||
import enums from './enums';
|
||||
export default defineComponent({
|
||||
name: 'ProcessList',
|
||||
components: {},
|
||||
props: {
|
||||
visible: { type: Boolean },
|
||||
machineId: { type: Number },
|
||||
title: { type: String },
|
||||
},
|
||||
setup(props: any, context) {
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
params: {
|
||||
name: '',
|
||||
sortType: '1',
|
||||
count: '10',
|
||||
id: 0,
|
||||
},
|
||||
processList: [],
|
||||
});
|
||||
|
||||
watch(props, (newValue) => {
|
||||
if (props.machineId) {
|
||||
state.params.id = props.machineId;
|
||||
getProcess();
|
||||
}
|
||||
state.dialogVisible = newValue.visible;
|
||||
});
|
||||
|
||||
const getProcess = async () => {
|
||||
const res = await machineApi.process.request(state.params);
|
||||
// 解析字符串
|
||||
// USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
// root 1 0.0 0.0 125632 3352 ? Ss 2019 154:04 /usr/lib/systemd/systemd --system --deserialize 22
|
||||
const psStrings = res.split('\n');
|
||||
const ps = [];
|
||||
for (let i = 1; i < psStrings.length; i++) {
|
||||
const psStr = psStrings[i];
|
||||
const process = psStr.split(/\s+/);
|
||||
if (process.length < 2) {
|
||||
continue;
|
||||
}
|
||||
let command = process[10];
|
||||
// 搜索进程时由于使用grep命令,可能会多个bash或grep进程
|
||||
if (state.params.name) {
|
||||
if (command == 'bash' || command == 'grep') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// 获取command,由于command中也有可能存在空格被切割,故重新拼接
|
||||
for (let j = 10; j < process.length - 1; j++) {
|
||||
command += ' ' + process[j + 1];
|
||||
}
|
||||
ps.push({
|
||||
user: process[0],
|
||||
pid: process[1],
|
||||
cpu: process[2],
|
||||
mem: process[3],
|
||||
vsz: kb2Mb(process[4]),
|
||||
rss: kb2Mb(process[5]),
|
||||
stat: process[7],
|
||||
start: process[8],
|
||||
time: process[9],
|
||||
command,
|
||||
});
|
||||
}
|
||||
state.processList = ps as any;
|
||||
};
|
||||
|
||||
const confirmKillProcess = async (pid: any) => {
|
||||
await machineApi.killProcess.request({
|
||||
pid,
|
||||
id: state.params.id,
|
||||
});
|
||||
ElMessage.success('kill success');
|
||||
state.params.name = '';
|
||||
getProcess();
|
||||
};
|
||||
|
||||
const kb2Mb = (kb: string) => {
|
||||
return (parseInt(kb) / 1024).toFixed(2) + 'M';
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭取消按钮触发的事件
|
||||
*/
|
||||
const handleClose = () => {
|
||||
context.emit('update:visible', false);
|
||||
context.emit('update:machineId', null);
|
||||
context.emit('cancel');
|
||||
state.params = {
|
||||
name: '',
|
||||
sortType: '1',
|
||||
count: '10',
|
||||
id: 0,
|
||||
};
|
||||
state.processList = [];
|
||||
};
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
getProcess,
|
||||
confirmKillProcess,
|
||||
enums,
|
||||
handleClose,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@@ -40,11 +40,11 @@
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="btnOk"
|
||||
size="mini"
|
||||
size="small"
|
||||
:disabled="submitDisabled"
|
||||
>保 存</el-button
|
||||
>
|
||||
<el-button @click="cancel()" :disabled="submitDisabled" size="mini">关 闭</el-button>
|
||||
<el-button @click="cancel()" :disabled="submitDisabled" size="small">关 闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -5,6 +5,9 @@ export const machineApi = {
|
||||
list: Api.create("/machines", 'get'),
|
||||
info: Api.create("/machines/{id}/sysinfo", 'get'),
|
||||
stats: Api.create("/machines/{id}/stats", 'get'),
|
||||
process: Api.create("/machines/{id}/process", 'get'),
|
||||
// 终止进程
|
||||
killProcess: Api.create("/machines/{id}/process", 'delete'),
|
||||
closeCli: Api.create("/machines/{id}/close-cli", 'delete'),
|
||||
// 保存按钮
|
||||
saveMachine: Api.create("/machines", 'post'),
|
||||
|
||||
Reference in New Issue
Block a user