✨ 支持自定义客户端端口
This commit is contained in:
parent
da36ed9d1b
commit
0460af5c48
@ -4,7 +4,7 @@ consola.info('debug日志:', process.env.DEBUG === '1' ? '开启' : '关闭')
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
httpPort: 8082,
|
httpPort: 8082,
|
||||||
clientDefaultPort: 22022,
|
defaultClientPort: 22022,
|
||||||
uploadDir: path.join(process.cwd(),'app/db'),
|
uploadDir: path.join(process.cwd(),'app/db'),
|
||||||
staticDir: path.join(process.cwd(),'app/static'),
|
staticDir: path.join(process.cwd(),'app/static'),
|
||||||
sftpCacheDir: path.join(process.cwd(),'app/socket/sftp-cache'),
|
sftpCacheDir: path.join(process.cwd(),'app/socket/sftp-cache'),
|
||||||
|
@ -25,7 +25,7 @@ async function addHost({
|
|||||||
let {
|
let {
|
||||||
body: {
|
body: {
|
||||||
name, host, index, expired, expiredNotify, group, consoleUrl, remark,
|
name, host, index, expired, expiredNotify, group, consoleUrl, remark,
|
||||||
port: newPort, username, authType, password, privateKey, credential, command, tempKey
|
port: newPort, clientPort, username, authType, password, privateKey, credential, command, tempKey
|
||||||
}
|
}
|
||||||
} = request
|
} = request
|
||||||
// console.log(request)
|
// console.log(request)
|
||||||
@ -33,7 +33,7 @@ async function addHost({
|
|||||||
let hostList = await readHostList()
|
let hostList = await readHostList()
|
||||||
let record = {
|
let record = {
|
||||||
name, host, index, expired, expiredNotify, group, consoleUrl, remark,
|
name, host, index, expired, expiredNotify, group, consoleUrl, remark,
|
||||||
port: newPort, username, authType, password, privateKey, credential, command
|
port: newPort, clientPort, username, authType, password, privateKey, credential, command
|
||||||
}
|
}
|
||||||
if (record[authType]) {
|
if (record[authType]) {
|
||||||
const clearTempKey = await RSADecryptSync(tempKey)
|
const clearTempKey = await RSADecryptSync(tempKey)
|
||||||
@ -54,7 +54,7 @@ async function updateHost({ res, request }) {
|
|||||||
hosts,
|
hosts,
|
||||||
id,
|
id,
|
||||||
host: newHost, name: newName, index, oldHost, expired, expiredNotify, group, consoleUrl, remark,
|
host: newHost, name: newName, index, oldHost, expired, expiredNotify, group, consoleUrl, remark,
|
||||||
port, username, authType, password, privateKey, credential, command, tempKey
|
port, clientPort, username, authType, password, privateKey, credential, command, tempKey
|
||||||
}
|
}
|
||||||
} = request
|
} = request
|
||||||
let isBatch = Array.isArray(hosts)
|
let isBatch = Array.isArray(hosts)
|
||||||
@ -80,18 +80,22 @@ async function updateHost({ res, request }) {
|
|||||||
record[authType] = await AESEncryptSync(clearSSHKey)
|
record[authType] = await AESEncryptSync(clearSSHKey)
|
||||||
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
// console.log(`${ authType }__commonKey加密存储: `, record[authType])
|
||||||
}
|
}
|
||||||
|
delete oldRecord.monitorData
|
||||||
|
delete record.monitorData
|
||||||
newHostList.push(Object.assign(oldRecord, record))
|
newHostList.push(Object.assign(oldRecord, record))
|
||||||
}
|
}
|
||||||
await writeHostList(newHostList)
|
await writeHostList(newHostList)
|
||||||
return res.success({ msg: '批量修改成功' })
|
return res.success({ msg: '批量修改成功' })
|
||||||
}
|
}
|
||||||
if (!newHost || !newName || !oldHost) return res.fail({ msg: '参数错误' })
|
if (!newHost || !newName || !oldHost) return res.fail({ msg: '参数错误' })
|
||||||
|
|
||||||
let hostList = await readHostList()
|
let hostList = await readHostList()
|
||||||
|
if (!hostList.some(({ host }) => host === oldHost)) return res.fail({ msg: `原实例[${ oldHost }]不存在,请尝试添加实例` })
|
||||||
|
|
||||||
let record = {
|
let record = {
|
||||||
name: newName, host: newHost, index, expired, expiredNotify, group, consoleUrl, remark,
|
name: newName, host: newHost, index, expired, expiredNotify, group, consoleUrl, remark,
|
||||||
port, username, authType, password, privateKey, credential, command
|
port, clientPort, username, authType, password, privateKey, credential, command
|
||||||
}
|
}
|
||||||
if (!hostList.some(({ host }) => host === oldHost)) return res.fail({ msg: `原实例[${ oldHost }]不存在,请尝试添加实例` })
|
|
||||||
|
|
||||||
let idx = hostList.findIndex(({ _id }) => _id === id)
|
let idx = hostList.findIndex(({ _id }) => _id === id)
|
||||||
const oldRecord = hostList[idx]
|
const oldRecord = hostList[idx]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const { Server: ServerIO } = require('socket.io')
|
const { Server: ServerIO } = require('socket.io')
|
||||||
const { io: ClientIO } = require('socket.io-client')
|
const { io: ClientIO } = require('socket.io-client')
|
||||||
const { readHostList } = require('../utils/storage')
|
const { readHostList } = require('../utils/storage')
|
||||||
const { clientDefaultPort } = require('../config')
|
const { defaultClientPort } = require('../config')
|
||||||
const { verifyAuthSync } = require('../utils/verify-auth')
|
const { verifyAuthSync } = require('../utils/verify-auth')
|
||||||
const { isAllowedIp } = require('../utils/tools')
|
const { isAllowedIp } = require('../utils/tools')
|
||||||
|
|
||||||
@ -16,8 +16,10 @@ async function getClientsInfo(clientSockets) {
|
|||||||
})
|
})
|
||||||
hostList
|
hostList
|
||||||
.map(({ host, name, clientPort }) => {
|
.map(({ host, name, clientPort }) => {
|
||||||
if (clientSockets.some(item => item.host === host)) return { name, isIo: true } // 已经建立io连接(无论是否连接成功)的host不再重复建立连接,因为存在多次(reconnectionAttempts)的重试机制
|
// 已经建立io连接(无论是否连接成功)的host不再重复建立连接,因为存在多次(reconnectionAttempts)的重试机制
|
||||||
let clientSocket = ClientIO(`http://${ host }:${ clientPort || clientDefaultPort }`, {
|
if (clientSockets.some(item => `${ item.host }:${ item.clientPort || defaultClientPort }` === `${ host }:${ clientPort || defaultClientPort }`)) return { name, isIo: true }
|
||||||
|
// console.log(name, 'clientPort:', clientPort)
|
||||||
|
let clientSocket = ClientIO(`http://${ host }:${ clientPort || defaultClientPort }`, {
|
||||||
path: '/client/os-info',
|
path: '/client/os-info',
|
||||||
forceNew: true,
|
forceNew: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
@ -25,34 +27,35 @@ async function getClientsInfo(clientSockets) {
|
|||||||
reconnectionAttempts: 1000
|
reconnectionAttempts: 1000
|
||||||
})
|
})
|
||||||
// 将与客户端连接的socket实例保存起来,web端断开时关闭这些连接
|
// 将与客户端连接的socket实例保存起来,web端断开时关闭这些连接
|
||||||
clientSockets.push({ host, name, clientSocket })
|
clientSockets.push({ host, name, clientPort, clientSocket })
|
||||||
return {
|
return {
|
||||||
host,
|
host,
|
||||||
name,
|
name,
|
||||||
|
clientPort,
|
||||||
clientSocket
|
clientSocket
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.forEach((item) => {
|
.forEach((item) => {
|
||||||
if (item.isIo) return // console.log('已经建立io连接的host不再重复建立连接', item.name)
|
if (item.isIo) return // console.log('已经建立io连接的host不再重复建立连接', item.name)
|
||||||
const { host, name, clientSocket } = item
|
const { host, name, clientPort, clientSocket } = item
|
||||||
// clientsData[host] = { connect: false }
|
// eslint-disable-next-line no-unused-vars
|
||||||
clientSocket
|
clientSocket
|
||||||
.on('connect', () => {
|
.on('connect', () => {
|
||||||
consola.success('client connect success:', host, name)
|
consola.success('client connect success:', host, name)
|
||||||
clientSocket.on('client_data', (osData) => {
|
clientSocket.on('client_data', (osData) => {
|
||||||
clientsData[host] = { connect: true, ...osData }
|
clientsData[`${ host }:${ clientPort || defaultClientPort }`] = { connect: true, ...osData }
|
||||||
})
|
})
|
||||||
clientSocket.on('client_error', (error) => {
|
clientSocket.on('client_error', (error) => {
|
||||||
clientsData[host] = { connect: true, error: `client_error: ${ error }` }
|
clientsData[`${ host }:${ clientPort || defaultClientPort }`] = { connect: true, error: `client_error: ${ error }` }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('connect_error', (error) => { // 连接失败
|
.on('connect_error', (error) => { // 连接失败
|
||||||
// consola.error('client connect fail:', host, name, error.message)
|
// consola.error('client connect fail:', host, name, error.message)
|
||||||
clientsData[host] = { connect: false, error: `client_connect_error: ${ error }` }
|
clientsData[`${ host }:${ clientPort || defaultClientPort }`] = { connect: false, error: `client_connect_error: ${ error }` }
|
||||||
})
|
})
|
||||||
.on('disconnect', (error) => { // 一方主动断开连接
|
.on('disconnect', (error) => { // 一方主动断开连接
|
||||||
// consola.info('client connect disconnect:', host, name)
|
// consola.info('client connect disconnect:', host, name)
|
||||||
clientsData[host] = { connect: false, error: `client_disconnect: ${ error }` }
|
clientsData[`${ host }:${ clientPort || defaultClientPort }`] = { connect: false, error: `client_disconnect: ${ error }` }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
3
web/src/config/index.js
Normal file
3
web/src/config/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default {
|
||||||
|
defaultClientPort: 22022
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
import { io } from 'socket.io-client'
|
import { io } from 'socket.io-client'
|
||||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||||
import $api from '@/api'
|
import $api from '@/api'
|
||||||
|
import config from '@/config'
|
||||||
// import ping from '@/utils/ping'
|
// import ping from '@/utils/ping'
|
||||||
|
|
||||||
|
const { defaultClientPort } = config
|
||||||
|
|
||||||
const useStore = defineStore({
|
const useStore = defineStore({
|
||||||
id: 'global',
|
id: 'global',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@ -42,7 +45,7 @@ const useStore = defineStore({
|
|||||||
await this.getHostList()
|
await this.getHostList()
|
||||||
await this.getSSHList()
|
await this.getSSHList()
|
||||||
await this.getScriptList()
|
await this.getScriptList()
|
||||||
this.wsHostStatus()
|
this.wsClientsStatus()
|
||||||
},
|
},
|
||||||
async getHostList() {
|
async getHostList() {
|
||||||
let { data: newHostList } = await $api.getHostList()
|
let { data: newHostList } = await $api.getHostList()
|
||||||
@ -80,7 +83,7 @@ const useStore = defineStore({
|
|||||||
// })
|
// })
|
||||||
// }, 2000)
|
// }, 2000)
|
||||||
// },
|
// },
|
||||||
async wsHostStatus() {
|
async wsClientsStatus() {
|
||||||
// if (this.HostStatusSocket) this.HostStatusSocket.close()
|
// if (this.HostStatusSocket) this.HostStatusSocket.close()
|
||||||
let socketInstance = io(this.serviceURI, {
|
let socketInstance = io(this.serviceURI, {
|
||||||
path: '/clients',
|
path: '/clients',
|
||||||
@ -96,8 +99,8 @@ const useStore = defineStore({
|
|||||||
socketInstance.on('clients_data', (data) => {
|
socketInstance.on('clients_data', (data) => {
|
||||||
// console.log(data)
|
// console.log(data)
|
||||||
this.hostList.forEach(item => {
|
this.hostList.forEach(item => {
|
||||||
const { host } = item
|
const { host, clientPort } = item
|
||||||
return Object.assign(item, { monitorData: Object.freeze(data[host]) })
|
return Object.assign(item, { monitorData: Object.freeze(data[`${ host }:${ clientPort || defaultClientPort }`]) })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
socketInstance.on('token_verify_fail', (message) => {
|
socketInstance.on('token_verify_fail', (message) => {
|
||||||
|
@ -127,7 +127,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="hostForm.privateKey"
|
v-model="hostForm.privateKey"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:rows="5"
|
:rows="3"
|
||||||
clearable
|
clearable
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
style="margin-top: 5px;"
|
style="margin-top: 5px;"
|
||||||
@ -183,7 +183,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="hostForm.command"
|
v-model="hostForm.command"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:rows="5"
|
:rows="3"
|
||||||
clearable
|
clearable
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder="连接服务器后自动执行的指令(例如: sudo -i)"
|
placeholder="连接服务器后自动执行的指令(例如: sudo -i)"
|
||||||
@ -218,6 +218,14 @@
|
|||||||
@keyup.enter="handleSave"
|
@keyup.enter="handleSave"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item key="clientPort" label="客户端端口" prop="clientPort">
|
||||||
|
<el-input
|
||||||
|
v-model.trim.number="hostForm.clientPort"
|
||||||
|
clearable
|
||||||
|
placeholder="客户端上报信息端口(默认22022)"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="!isBatchModify"
|
v-if="!isBatchModify"
|
||||||
key="index"
|
key="index"
|
||||||
@ -291,6 +299,7 @@ const formField = {
|
|||||||
password: '',
|
password: '',
|
||||||
privateKey: '',
|
privateKey: '',
|
||||||
credential: '', // credentials -> _id
|
credential: '', // credentials -> _id
|
||||||
|
clientPort: '22022',
|
||||||
index: 0,
|
index: 0,
|
||||||
expired: null,
|
expired: null,
|
||||||
expiredNotify: false,
|
expiredNotify: false,
|
||||||
@ -313,6 +322,7 @@ const rules = computed(() => {
|
|||||||
name: { required: !isBatchModify.value, message: '输入实例别名', trigger: 'change' },
|
name: { required: !isBatchModify.value, message: '输入实例别名', trigger: 'change' },
|
||||||
host: { required: !isBatchModify.value, message: '输入IP/域名', trigger: 'change' },
|
host: { required: !isBatchModify.value, message: '输入IP/域名', trigger: 'change' },
|
||||||
port: { required: !isBatchModify.value, type: 'number', message: '输入ssh端口', trigger: 'change' },
|
port: { required: !isBatchModify.value, type: 'number', message: '输入ssh端口', trigger: 'change' },
|
||||||
|
clientPort: { required: false, type: 'number', message: '输入ssh端口', trigger: 'change' },
|
||||||
index: { required: !isBatchModify.value, type: 'number', message: '输入数字', trigger: 'change' },
|
index: { required: !isBatchModify.value, type: 'number', message: '输入数字', trigger: 'change' },
|
||||||
// password: [{ required: hostForm.authType === 'password', trigger: 'change' },],
|
// password: [{ required: hostForm.authType === 'password', trigger: 'change' },],
|
||||||
// privateKey: [{ required: hostForm.authType === 'privateKey', trigger: 'change' },],
|
// privateKey: [{ required: hostForm.authType === 'privateKey', trigger: 'change' },],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user