✨
This commit is contained in:
parent
0d0b24de75
commit
bcfbe0d6b3
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,3 +1,14 @@
|
|||||||
|
## [1.2.1](https://github.com/chaos-zhu/easynode/releases) (2022-12-12)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* 新增支持终端长命令输入模式 ✔
|
||||||
|
* 新增前端静态文件缓存 ✔
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* v1.2的若干bug...
|
||||||
|
|
||||||
## [1.2.0](https://github.com/chaos-zhu/easynode/releases) (2022-09-12)
|
## [1.2.0](https://github.com/chaos-zhu/easynode/releases) (2022-09-12)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
8
Q&A.md
8
Q&A.md
@ -1,8 +1,6 @@
|
|||||||
# 用于收集一些疑难杂症
|
# Q&A
|
||||||
|
|
||||||
- **欢迎pr~**
|
## CentOS7/8启动服务失败
|
||||||
|
|
||||||
## 甲骨文CentOS7/8启动服务失败
|
|
||||||
|
|
||||||
> 先关闭SELinux
|
> 先关闭SELinux
|
||||||
|
|
||||||
@ -17,6 +15,6 @@ SELINUX=disabled
|
|||||||
|
|
||||||
> 查看SELinux状态:sestatus
|
> 查看SELinux状态:sestatus
|
||||||
|
|
||||||
## 甲骨文ubuntu20.04客户端服务启动成功,无法连接?
|
## 客户端服务启动成功,无法连接?
|
||||||
|
|
||||||
> 端口未开放:`iptables -I INPUT -s 0.0.0.0/0 -p tcp --dport 22022 -j ACCEPT` 或者 `rm -rf /etc/iptables && reboot`
|
> 端口未开放:`iptables -I INPUT -s 0.0.0.0/0 -p tcp --dport 22022 -j ACCEPT` 或者 `rm -rf /etc/iptables && reboot`
|
||||||
|
10
README.md
10
README.md
@ -42,12 +42,10 @@
|
|||||||
|
|
||||||
- 依赖Node.js环境
|
- 依赖Node.js环境
|
||||||
|
|
||||||
- 占用端口:8082(http端口)、8083(https端口)、22022(客户端端口)
|
- 占用端口:8082(http端口)、22022(客户端端口)
|
||||||
|
|
||||||
- 建议使用**境外服务器**(最好延迟低)安装服务端,客户端信息监控与webssh功能都将以`该服务器作为跳板机`
|
- 建议使用**境外服务器**(最好延迟低)安装服务端,客户端信息监控与webssh功能都将以`该服务器作为跳板机`
|
||||||
|
|
||||||
- https服务需自行配置证书,或者使用`nginx反代`解决(推荐)
|
|
||||||
|
|
||||||
#### Docker镜像
|
#### Docker镜像
|
||||||
|
|
||||||
> 注意:网速统计功能可能受限,docker网络将使用host模式(与宿主机共享端口,占用: 8082、22022)
|
> 注意:网速统计功能可能受限,docker网络将使用host模式(与宿主机共享端口,占用: 8082、22022)
|
||||||
@ -88,12 +86,6 @@ wget -qO- --no-check-certificate https://ghproxy.com/https://raw.githubuserconte
|
|||||||
|
|
||||||
- 默认登录密码:admin(首次部署完成后请及时修改).
|
- 默认登录密码:admin(首次部署完成后请及时修改).
|
||||||
|
|
||||||
6. 部署https服务
|
|
||||||
- 部署https服务需要自己上传域名证书至`\server\app\config\pem`,并且证书和私钥分别命名:`key.pem`和`cert.pem`
|
|
||||||
- 配置域名:vim server/app/config/index.js 在domain字段中填写你解析到服务器的域名
|
|
||||||
- pm2 restart easynode-server
|
|
||||||
- 不出意外你就可以访问https服务:https://domain:8083
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 客户端安装
|
### 客户端安装
|
||||||
|
0
client/bin/www
Normal file → Executable file
0
client/bin/www
Normal file → Executable file
@ -73,9 +73,16 @@ mv ${FILE_PATH}/${SERVER_NAME}.service ${SERVICE_PATH}
|
|||||||
# echo "***********************daemon-reload***********************"
|
# echo "***********************daemon-reload***********************"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
|
||||||
echo "***********************启动服务***********************"
|
echo "***********************准备启动服务***********************"
|
||||||
systemctl start ${SERVER_NAME}
|
systemctl start ${SERVER_NAME}
|
||||||
|
|
||||||
|
if [ $? != 0 ]
|
||||||
|
then
|
||||||
|
echo "***********************${SERVER_NAME}.service启动失败***********************"
|
||||||
|
echo "***********************可能是服务器开启了SELinux, 参见Q&A***********************"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "***********************服务启动成功***********************"
|
||||||
|
|
||||||
# echo "***********************设置开机启动***********************"
|
# echo "***********************设置开机启动***********************"
|
||||||
systemctl enable ${SERVER_NAME}
|
systemctl enable ${SERVER_NAME}
|
||||||
|
@ -1,25 +1,11 @@
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const fs = require('fs')
|
|
||||||
|
|
||||||
const getCertificate =() => {
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
cert: fs.readFileSync(path.join(__dirname, './pem/cert.pem')),
|
|
||||||
key: fs.readFileSync(path.join(__dirname, './pem/key.pem'))
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
domain: 'xxx.com', // https域名, 可不配置
|
|
||||||
httpPort: 8082,
|
httpPort: 8082,
|
||||||
httpsPort: 8083,
|
|
||||||
clientPort: 22022, // 勿更改
|
clientPort: 22022, // 勿更改
|
||||||
certificate: getCertificate(),
|
|
||||||
uploadDir: path.join(process.cwd(),'app/static/upload'),
|
uploadDir: path.join(process.cwd(),'app/static/upload'),
|
||||||
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'),
|
||||||
sshRecordPath: path.join(process.cwd(),'app/storage/ssh-record.json'),
|
sshRecordPath: path.join(process.cwd(),'app/storage/ssh-record.json'),
|
||||||
keyPath: path.join(process.cwd(),'app/storage/key.json'),
|
keyPath: path.join(process.cwd(),'app/storage/key.json'),
|
||||||
hostListPath: path.join(process.cwd(),'app/storage/host-list.json'),
|
hostListPath: path.join(process.cwd(),'app/storage/host-list.json'),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const consola = require('consola')
|
const consola = require('consola')
|
||||||
global.consola = consola
|
global.consola = consola
|
||||||
const { httpServer, httpsServer, clientHttpServer } = require('./server')
|
const { httpServer, clientHttpServer } = require('./server')
|
||||||
const initLocal = require('./init')
|
const initLocal = require('./init')
|
||||||
const scheduleJob = require('./schedule')
|
const scheduleJob = require('./schedule')
|
||||||
|
|
||||||
@ -10,6 +10,4 @@ initLocal()
|
|||||||
|
|
||||||
httpServer()
|
httpServer()
|
||||||
|
|
||||||
httpsServer()
|
|
||||||
|
|
||||||
clientHttpServer()
|
clientHttpServer()
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
const cors = require('@koa/cors')
|
const cors = require('@koa/cors')
|
||||||
// const { domain } = require('../config')
|
|
||||||
|
|
||||||
// 跨域处理
|
// 跨域处理
|
||||||
const useCors = cors({
|
const useCors = cors({
|
||||||
origin: ({ req }) => {
|
origin: ({ req }) => {
|
||||||
// return domain || req.headers.origin
|
|
||||||
return req.headers.origin
|
return req.headers.origin
|
||||||
},
|
},
|
||||||
credentials: true,
|
credentials: true,
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
const Koa = require('koa')
|
const Koa = require('koa')
|
||||||
const compose = require('koa-compose') // 组合中间件,简化写法
|
const compose = require('koa-compose') // 组合中间件,简化写法
|
||||||
const http = require('http')
|
const http = require('http')
|
||||||
const https = require('https')
|
|
||||||
const { clientPort } = require('./config')
|
const { clientPort } = require('./config')
|
||||||
const { domain, httpPort, httpsPort, certificate } = require('./config')
|
const { httpPort } = require('./config')
|
||||||
const middlewares = require('./middlewares')
|
const middlewares = require('./middlewares')
|
||||||
const wsMonitorOsInfo = require('./socket/monitor')
|
const wsMonitorOsInfo = require('./socket/monitor')
|
||||||
const wsTerminal = require('./socket/terminal')
|
const wsTerminal = require('./socket/terminal')
|
||||||
@ -17,22 +16,11 @@ const httpServer = () => {
|
|||||||
const server = http.createServer(app.callback())
|
const server = http.createServer(app.callback())
|
||||||
serverHandler(app, server)
|
serverHandler(app, server)
|
||||||
// ws一直报跨域的错误:参照官方文档使用createServer API创建服务
|
// ws一直报跨域的错误:参照官方文档使用createServer API创建服务
|
||||||
server.listen(process.env.PORT || httpPort, () => {
|
server.listen(httpPort, () => {
|
||||||
consola.success(`Server(http) is running on: http://localhost:${ httpPort }`)
|
consola.success(`Server(http) is running on: http://localhost:${ httpPort }`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const httpsServer = () => {
|
|
||||||
if(!certificate) return consola.error('未上传证书, 创建https服务失败')
|
|
||||||
const app = new Koa()
|
|
||||||
const server = https.createServer(certificate, app.callback())
|
|
||||||
serverHandler(app, server)
|
|
||||||
server.listen(httpsPort, (err) => {
|
|
||||||
if (err) return consola.error('https server error: ', err)
|
|
||||||
consola.success(`Server(https) is running: https://${ domain }:${ httpsPort }`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clientHttpServer = () => {
|
const clientHttpServer = () => {
|
||||||
const app = new Koa()
|
const app = new Koa()
|
||||||
const server = http.createServer(app.callback())
|
const server = http.createServer(app.callback())
|
||||||
@ -63,6 +51,5 @@ function serverHandler(app, server) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
httpServer,
|
httpServer,
|
||||||
httpsServer,
|
|
||||||
clientHttpServer
|
clientHttpServer
|
||||||
}
|
}
|
@ -109,21 +109,21 @@ function listenInput(sftpClient, socket) {
|
|||||||
socket.emit('sftp_error', error.message)
|
socket.emit('sftp_error', error.message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// socket.on('up_file', async ({ targetPath, fullPath, name, file }) => {
|
socket.on('up_file', async ({ targetPath, fullPath, name, file }) => {
|
||||||
// console.log({ targetPath, fullPath, name, file })
|
console.log({ targetPath, fullPath, name, file })
|
||||||
// const exists = await sftpClient.exists(targetPath)
|
const exists = await sftpClient.exists(targetPath)
|
||||||
// if(!exists) return socket.emit('not_exists_dir', '文件夹不存在或当前不可访问')
|
if(!exists) return socket.emit('not_exists_dir', '文件夹不存在或当前不可访问')
|
||||||
// try {
|
try {
|
||||||
// const localPath = rawPath.join(sftpCacheDir, name)
|
const localPath = rawPath.join(sftpCacheDir, name)
|
||||||
// fs.writeFileSync(localPath, file)
|
fs.writeFileSync(localPath, file)
|
||||||
// let res = await sftpClient.fastPut(localPath, fullPath)
|
let res = await sftpClient.fastPut(localPath, fullPath)
|
||||||
// consola.success('sftp上传成功: ', res)
|
consola.success('sftp上传成功: ', res)
|
||||||
// socket.emit('up_file_success', res)
|
socket.emit('up_file_success', res)
|
||||||
// } catch (error) {
|
} catch (error) {
|
||||||
// consola.error('up_file Error', error.message)
|
consola.error('up_file Error', error.message)
|
||||||
// socket.emit('sftp_error', error.message)
|
socket.emit('sftp_error', error.message)
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
|
|
||||||
/** 分片上传 */
|
/** 分片上传 */
|
||||||
// 1. 创建本地缓存文件夹
|
// 1. 创建本地缓存文件夹
|
||||||
@ -186,7 +186,7 @@ function listenInput(sftpClient, socket) {
|
|||||||
clearDir(resultDirPath, true) // 传服务器后移除文件夹及其文件
|
clearDir(resultDirPath, true) // 传服务器后移除文件夹及其文件
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
consola.error('sftp上传失败: ', error.message)
|
consola.error('sftp上传失败: ', error.message)
|
||||||
socket.emit('sftp_error', error.message)
|
socket.emit('up_file_fail', error.message)
|
||||||
clearDir(resultDirPath, true) // 传服务器后移除文件夹及其文件
|
clearDir(resultDirPath, true) // 传服务器后移除文件夹及其文件
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
File diff suppressed because one or more lines are too long
BIN
server/app/static/assets/index.5de3ed69.js.gz
Normal file
BIN
server/app/static/assets/index.5de3ed69.js.gz
Normal file
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
server/app/static/assets/index.cf7d36d4.css.gz
Normal file
BIN
server/app/static/assets/index.cf7d36d4.css.gz
Normal file
Binary file not shown.
Binary file not shown.
@ -5,8 +5,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=0,user-scalable=yes">
|
<meta name="viewport" content="width=device-width, initial-scale=0,user-scalable=yes">
|
||||||
<title>EasyNode</title>
|
<title>EasyNode</title>
|
||||||
<script src="//at.alicdn.com/t/c/font_3309550_flid0kihu36.js"></script>
|
<script src="//at.alicdn.com/t/c/font_3309550_flid0kihu36.js"></script>
|
||||||
<script type="module" crossorigin src="/assets/index.eb5f280e.js"></script>
|
<script type="module" crossorigin src="/assets/index.5de3ed69.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index.a9194a35.css">
|
<link rel="stylesheet" href="/assets/index.cf7d36d4.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -1,2 +1 @@
|
|||||||
[
|
[]
|
||||||
]
|
|
@ -63,7 +63,7 @@ const getNetIPInfo = async (searchIp = '') => {
|
|||||||
let { origip: ip, location: country, city = '', regionName = '' } = res || {}
|
let { origip: ip, location: country, city = '', regionName = '' } = res || {}
|
||||||
searchResult.push({ ip, country, city: `${ regionName } ${ city }`, date })
|
searchResult.push({ ip, country, city: `${ regionName } ${ city }`, date })
|
||||||
}
|
}
|
||||||
console.log(searchResult)
|
// console.log(searchResult)
|
||||||
let validInfo = searchResult.find(item => Boolean(item.country))
|
let validInfo = searchResult.find(item => Boolean(item.country))
|
||||||
consola.info('查询IP信息:', validInfo)
|
consola.info('查询IP信息:', validInfo)
|
||||||
return validInfo || { ip: '获取IP信息API出错,请排查或更新API', country: '未知', city: '未知', date }
|
return validInfo || { ip: '获取IP信息API出错,请排查或更新API', country: '未知', city: '未知', date }
|
||||||
|
0
server/bin/www
Normal file → Executable file
0
server/bin/www
Normal file → Executable file
Loading…
x
Reference in New Issue
Block a user