🐛 修复同主机名使用id连接终端

This commit is contained in:
chaos-zhu 2024-10-11 23:28:16 +08:00
parent 4c7a214c55
commit 3de5537448
6 changed files with 55 additions and 55 deletions

View File

@ -1,4 +1,4 @@
## [2.3.0](https://github.com/chaos-zhu/easynode/releases) (2024-10-xx) ## [2.2.5](https://github.com/chaos-zhu/easynode/releases) (2024-10-xx)
### Features ### Features

View File

@ -15,7 +15,7 @@ async function getSSHList({ res }) {
const addSSH = async ({ res, request }) => { const addSSH = async ({ res, request }) => {
let { body: { name, authType, password, privateKey, tempKey } } = request let { body: { name, authType, password, privateKey, tempKey } } = request
let record = { name, authType, password, privateKey } let record = { name, authType, password, privateKey }
if(!name || !record[authType]) return res.fail({ data: false, msg: '参数错误' }) if (!name || !record[authType]) return res.fail({ data: false, msg: '参数错误' })
let sshRecord = await readSSHRecord() let sshRecord = await readSSHRecord()
if (sshRecord.some(item => item.name === name)) return res.fail({ data: false, msg: '已存在同名凭证' }) if (sshRecord.some(item => item.name === name)) return res.fail({ data: false, msg: '已存在同名凭证' })
@ -35,11 +35,11 @@ const addSSH = async ({ res, request }) => {
const updateSSH = async ({ res, request }) => { const updateSSH = async ({ res, request }) => {
let { body: { id, name, authType, password, privateKey, date, tempKey } } = request let { body: { id, name, authType, password, privateKey, date, tempKey } } = request
let record = { name, authType, password, privateKey, date } let record = { name, authType, password, privateKey, date }
if(!id || !name) return res.fail({ data: false, msg: '请输入凭据名称' }) if (!id || !name) return res.fail({ data: false, msg: '请输入凭据名称' })
let sshRecord = await readSSHRecord() let sshRecord = await readSSHRecord()
let idx = sshRecord.findIndex(item => item._id === id) let idx = sshRecord.findIndex(item => item._id === id)
if (sshRecord.some(item => item.name === name && item.date !== date)) return res.fail({ data: false, msg: '已存在同名凭证' }) if (sshRecord.some(item => item.name === name && item.date !== date)) return res.fail({ data: false, msg: '已存在同名凭证' })
if(idx === -1) res.fail({ data: false, msg: '请输入凭据名称' }) if (idx === -1) res.fail({ data: false, msg: '请输入凭据名称' })
const oldRecord = sshRecord[idx] const oldRecord = sshRecord[idx]
// 判断原记录是否存在当前更新记录的认证方式 // 判断原记录是否存在当前更新记录的认证方式
if (!oldRecord[authType] && !record[authType]) return res.fail({ data: false, msg: `请输入${ authType === 'password' ? '密码' : '密钥' }` }) if (!oldRecord[authType] && !record[authType]) return res.fail({ data: false, msg: `请输入${ authType === 'password' ? '密码' : '密钥' }` })
@ -64,7 +64,7 @@ const removeSSH = async ({ res, request }) => {
let { params: { id } } = request let { params: { id } } = request
let sshRecord = await readSSHRecord() let sshRecord = await readSSHRecord()
let idx = sshRecord.findIndex(item => item._id === id) let idx = sshRecord.findIndex(item => item._id === id)
if(idx === -1) return res.fail({ msg: '凭证不存在' }) if (idx === -1) return res.fail({ msg: '凭证不存在' })
sshRecord.splice(idx, 1) sshRecord.splice(idx, 1)
// 将删除的凭证id从host中删除 // 将删除的凭证id从host中删除
let hostList = await readHostList() let hostList = await readHostList()
@ -79,14 +79,14 @@ const removeSSH = async ({ res, request }) => {
} }
const getCommand = async ({ res, request }) => { const getCommand = async ({ res, request }) => {
let { host } = request.query let { hostId } = request.query
if(!host) return res.fail({ data: false, msg: '参数错误' }) if (!hostId) return res.fail({ data: false, msg: '参数错误' })
let hostInfo = await readHostList() let hostInfo = await readHostList()
let record = hostInfo?.find(item => item.host === host) let record = hostInfo?.find(item => item._id === hostId)
consola.info('查询登录后执行的指令:', host) consola.info('查询登录后执行的指令:', hostId)
if(!record) return res.fail({ data: false, msg: 'host not found' }) // host不存在 if (!record) return res.fail({ data: false, msg: 'host not found' }) // host不存在
const { command } = record const { command } = record
if(!command) return res.success({ data: false }) // command不存在 if (!command) return res.success({ data: false }) // command不存在
res.success({ data: command }) // 存在 res.success({ data: command }) // 存在
} }

View File

@ -25,36 +25,36 @@ function createInteractiveShell(socket, sshClient) {
}) })
} }
function execShell(sshClient, command = '', callback) { // function execShell(sshClient, command = '', callback) {
if (!command) return // if (!command) return
let result = '' // let result = ''
sshClient.exec(`source ~/.bashrc && ${ command }`, (err, stream) => { // sshClient.exec(`source ~/.bashrc && ${ command }`, (err, stream) => {
if (err) return callback(err.toString()) // if (err) return callback(err.toString())
stream // stream
.on('data', (data) => { // .on('data', (data) => {
result += data.toString() // result += data.toString()
}) // })
.stderr // .stderr
.on('data', (data) => { // .on('data', (data) => {
result += data.toString() // result += data.toString()
}) // })
.on('close', () => { // .on('close', () => {
consola.info('一次性指令执行完成:', command) // consola.info('一次性指令执行完成:', command)
callback(result) // callback(result)
}) // })
.on('error', (error) => { // .on('error', (error) => {
console.log('Error:', error.toString()) // console.log('Error:', error.toString())
}) // })
}) // })
} // }
async function createTerminal(ip, socket, sshClient) { async function createTerminal(hostId, socket, sshClient) {
// eslint-disable-next-line no-async-promise-executor // eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
const hostList = await readHostList() const hostList = await readHostList()
const targetHostInfo = hostList.find(item => item.host === ip) || {} const targetHostInfo = hostList.find(item => item._id === hostId) || {}
let { authType, host, port, username, name } = targetHostInfo let { authType, host, port, username, name } = targetHostInfo
if (!host) return socket.emit('create_fail', `查找${ ip }】凭证信息失败`) if (!host) return socket.emit('create_fail', `查找hostId【${ hostId }】凭证信息失败`)
let authInfo = { host, port, username } let authInfo = { host, port, username }
// 统一使用commonKey解密 // 统一使用commonKey解密
try { try {
@ -122,7 +122,7 @@ module.exports = (httpServer) => {
} }
consola.success('terminal websocket 已连接') consola.success('terminal websocket 已连接')
let sshClient = null let sshClient = null
socket.on('create', async ({ host: ip, token }) => { socket.on('create', async ({ hostId, token }) => {
const { code } = await verifyAuthSync(token, requestIP) const { code } = await verifyAuthSync(token, requestIP)
if (code !== 1) { if (code !== 1) {
socket.emit('token_verify_fail') socket.emit('token_verify_fail')
@ -149,7 +149,7 @@ module.exports = (httpServer) => {
socket.on('resize', resizeShell) socket.on('resize', resizeShell)
// 重连 // 重连
socket.on('reconnect_terminal', async () => { socket.on('reconnect_terminal', async () => {
consola.info('重连终端: ', ip) consola.info('重连终端: ', hostId)
socket.off('input', listenerInput) // 取消监听,重新注册监听,操作新的stream socket.off('input', listenerInput) // 取消监听,重新注册监听,操作新的stream
socket.off('resize', resizeShell) socket.off('resize', resizeShell)
sshClient?.end() sshClient?.end()
@ -159,13 +159,13 @@ module.exports = (httpServer) => {
setTimeout(async () => { setTimeout(async () => {
// 初始化新的SSH客户端对象 // 初始化新的SSH客户端对象
sshClient = new SSHClient() sshClient = new SSHClient()
stream = await createTerminal(ip, socket, sshClient) stream = await createTerminal(hostId, socket, sshClient)
socket.emit('reconnect_terminal_success') socket.emit('reconnect_terminal_success')
socket.on('input', listenerInput) socket.on('input', listenerInput)
socket.on('resize', resizeShell) socket.on('resize', resizeShell)
}, 3000) }, 3000)
}) })
stream = await createTerminal(ip, socket, sshClient) stream = await createTerminal(hostId, socket, sshClient)
}) })
socket.on('disconnect', (reason) => { socket.on('disconnect', (reason) => {

View File

@ -22,8 +22,8 @@ export default {
// existSSH(host) { // existSSH(host) {
// return axios({ url: '/exist-ssh', method: 'post', data: { host } }) // return axios({ url: '/exist-ssh', method: 'post', data: { host } })
// }, // },
getCommand(host) { getCommand(hostId) {
return axios({ url: '/command', method: 'get', params: { host } }) return axios({ url: '/command', method: 'get', params: { hostId } })
}, },
getHostList() { getHostList() {
return axios({ url: '/host-list', method: 'get' }) return axios({ url: '/host-list', method: 'get' })

View File

@ -69,7 +69,7 @@ const theme = computed(() => props.theme)
const fontSize = computed(() => props.fontSize) const fontSize = computed(() => props.fontSize)
const background = computed(() => props.background) const background = computed(() => props.background)
const hostObj = computed(() => props.hostObj) const hostObj = computed(() => props.hostObj)
const host = computed(() => hostObj.value.host) const hostId = computed(() => hostObj.value.id)
let menuCollapse = computed(() => $store.menuCollapse) let menuCollapse = computed(() => $store.menuCollapse)
watch(menuCollapse, () => { watch(menuCollapse, () => {
@ -114,7 +114,7 @@ watch(curStatus, () => {
}) })
const getCommand = async () => { const getCommand = async () => {
let { data } = await $api.getCommand(host.value) let { data } = await $api.getCommand(hostId.value)
if (data) command.value = data if (data) command.value = data
} }
@ -125,9 +125,9 @@ const connectIO = () => {
reconnectionAttempts: 1 reconnectionAttempts: 1
}) })
socket.value.on('connect', () => { socket.value.on('connect', () => {
console.log('/terminal socket已连接', host.value) console.log('/terminal socket已连接', hostId.value)
socketConnected.value = true socketConnected.value = true
socket.value.emit('create', { host: host.value, token: token.value }) socket.value.emit('create', { hostId: hostId.value, token: token.value })
socket.value.on('connect_terminal_success', () => { socket.value.on('connect_terminal_success', () => {
if (hasRegisterEvent.value) return // , . socket if (hasRegisterEvent.value) return // , . socket
hasRegisterEvent.value = true hasRegisterEvent.value = true
@ -159,7 +159,7 @@ const connectIO = () => {
socket.value.on('connect_close', () => { socket.value.on('connect_close', () => {
if (curStatus.value === CONNECT_FAIL) return // if (curStatus.value === CONNECT_FAIL) return //
curStatus.value = RECONNECTING curStatus.value = RECONNECTING
console.warn('连接断开,3秒后自动重连: ', host.value) console.warn('连接断开,3秒后自动重连: ', hostId.value)
term.value.write('\r\n连接断开,3秒后自动重连...\r\n') term.value.write('\r\n连接断开,3秒后自动重连...\r\n')
socket.value.emit('reconnect_terminal') socket.value.emit('reconnect_terminal')
}) })
@ -170,13 +170,13 @@ const connectIO = () => {
socket.value.on('create_fail', (message) => { socket.value.on('create_fail', (message) => {
curStatus.value = CONNECT_FAIL curStatus.value = CONNECT_FAIL
console.error('n创建失败:', host.value, message) console.error('n创建失败:', hostId.value, message)
term.value.write(`\r\n创建失败: ${ message }\r\n`) term.value.write(`\r\n创建失败: ${ message }\r\n`)
}) })
socket.value.on('connect_fail', (message) => { socket.value.on('connect_fail', (message) => {
curStatus.value = CONNECT_FAIL curStatus.value = CONNECT_FAIL
console.error('连接失败:', host.value, message) console.error('连接失败:', hostId.value, message)
term.value.write(`\r\n连接失败: ${ message }\r\n`) term.value.write(`\r\n连接失败: ${ message }\r\n`)
}) })
}) })

View File

@ -75,10 +75,10 @@ let isAllConfssh = computed(() => {
return hostList.value?.every(item => item.isConfig) return hostList.value?.every(item => item.isConfig)
}) })
function linkTerminal({ id }) { function linkTerminal(hostInfo) {
let targetHost = hostList.value.find(item => item.id === id) let targetHost = hostList.value.find(item => item.id === hostInfo.id)
const { host, name } = targetHost const { id, host, name } = targetHost
terminalTabs.push({ key: randomStr(16), name, host, status: CONNECTING }) terminalTabs.push({ key: randomStr(16), id, name, host, status: CONNECTING })
} }
function handleUpdateHost(row) { function handleUpdateHost(row) {
@ -110,8 +110,8 @@ onActivated(async () => {
const { hostIds } = route.query const { hostIds } = route.query
if (!hostIds) return if (!hostIds) return
let targetHosts = hostList.value.filter(item => hostIds.includes(item.id)).map(item => { let targetHosts = hostList.value.filter(item => hostIds.includes(item.id)).map(item => {
const { name, host } = item const { id, name, host } = item
return { key: randomStr(16), name, host, status: CONNECTING } return { key: randomStr(16), id, name, host, status: CONNECTING }
}) })
if (!targetHosts || !targetHosts.length) return if (!targetHosts || !targetHosts.length) return
terminalTabs.push(...targetHosts) terminalTabs.push(...targetHosts)