@xtail/ssh
Version:
X-Tail SSH 库,包含 SSH 连接服务器的类和工具方法等
167 lines (166 loc) • 5.84 kB
JavaScript
var l = Object.defineProperty;
var g = (n, s, t) => s in n ? l(n, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[s] = t;
var i = (n, s, t) => g(n, typeof s != "symbol" ? s + "" : s, t);
import f from "ssh2-promise";
import a from "../node_modules/.pnpm/strip-ansi@7.1.0/node_modules/strip-ansi/index.js";
import u from "../node_modules/.pnpm/split-lines@3.0.0/node_modules/split-lines/index.js";
import { SSHUtil as e } from "../utils/index.js";
const R = "SSH";
class B {
constructor(s) {
// 服务器连接配置
i(this, "config");
// 服务器连接实例
i(this, "ssh", null);
// 是否已连接服务器
i(this, "connected", !1);
// 与服务器 Shell 交互的 socket 实例
i(this, "socket", null);
// 是否已经与服务器创建会话
i(this, "isSession", !1);
// 当前执行的命令
i(this, "currentCmd", {});
this.config = s;
}
/**
* 是否已经 SSH 连接到服务器
*
* @returns {boolean} true 已连接,false 未连接
*/
get isConnected() {
return this.connected;
}
/**
* SSH 连接服务器
*
* @returns {Promise<SSHResultType>} SSH 连接结果
*/
async connect() {
if (this.connected)
return e.genSuccessResultByConf(this.config, { message: "已连接成功" });
try {
return this.ssh = new f(this.config), await this.ssh.connect(), this.connected = !0, e.genSuccessResultByConf(this.config, { message: "连接成功" });
} catch (s) {
return this.connected = !1, this.ssh = null, e.genFailResultByConf(this.config, {
message: s.message ?? "连接失败",
detail: s
});
}
}
/**
* 断开与服务器的 SSH 连接
*
* @returns {Promise<SSHResultType>} 断开与服务器的 SSH 连接的结果
*/
async close() {
var s;
(!this.ssh || !this.connected) && e.genSuccessResultByConf(this.config, { message: "已断开服务器连接" });
try {
return await ((s = this.ssh) == null ? void 0 : s.close()), this.connected = !1, this.ssh = null, e.genSuccessResultByConf(this.config, { message: "断开服务器连接成功" });
} catch (t) {
return e.genFailResultByConf(this.config, {
message: t.message ?? "断开服务器连接失败",
detail: t
});
}
}
/**
* SSH 连接服务器后执行命令<br/>
* 注意:如果未连接服务器,会返回失败结果,所以需要先调用 {@link connect} 方法连接服务器
*
* @param {string} cmd 需要执行的命令
* @returns {Promise<SSHResultType>} 执行命令结果
*/
async exec(s) {
if (!this.ssh || !this.connected)
return e.genFailResultByConf(this.config, { message: "未连接服务器,请先连接服务器" });
try {
const t = await this.ssh.exec(s);
return e.genSuccessResultByConf(this.config, {
message: `${s} 执行成功`,
detail: t
});
} catch (t) {
return e.genFailResultByConf(this.config, {
message: t.message ?? `${s} 执行失败`,
detail: t
});
}
}
/**
* 是否已经与服务器创建会话
*
* @returns {boolean} true 已创建会话,false 未创建会话
*/
get isSessionOpen() {
return this.isSession;
}
/**
* 与服务器创建 Shell 会话
*
* @param {(data: string) => void} onData 服务器返回数据时的回调函数
* @param {() => void} onClose 与服务器之间的 Shell 会话关闭时的回调函数
* @returns {Promise<SSHResultType>} 创建会话结果
*/
async sessionOpen(s, t) {
if (!this.ssh || !this.connected)
return e.genFailResultByConf(this.config, { message: "未连接服务器,请先连接服务器" });
try {
return this.socket = await this.ssh.shell(), this.socket.on("data", (r) => {
let o = "";
const h = u(r.toString("utf8"));
for (const c of h)
Reflect.has(this.currentCmd, c.trim()) ? Reflect.deleteProperty(this.currentCmd, c.trim()) : Reflect.has(this.currentCmd, a(c).trim()) ? Reflect.deleteProperty(this.currentCmd, a(c).trim()) : o += c + `
`;
o.trim() && s(o);
}), this.socket.on("close", t), this.isSession = !0, e.genSuccessResultByConf(this.config, { message: "会话创建成功" });
} catch (r) {
return this.isSession = !1, this.socket = null, e.genFailResultByConf(this.config, {
message: r.message ?? "会话创建失败",
detail: r
});
}
}
/**
* 在与服务器创建的 Shell 会话中执行命令
*
* @param {string} cmd 需要执行的命令
* @returns {Promise<SSHResultType>} 命令执行结果
*/
async sessionExec(s) {
if (!this.socket || !this.isSession)
return e.genFailResultByConf(this.config, {
message: "未与服务器创建会话,请先创建会话"
});
try {
return this.currentCmd[s] = s, this.socket.write(s + `
`), e.genSuccessResultByConf(this.config, { message: `${s} 执行成功` });
} catch (t) {
return e.genFailResultByConf(this.config, {
message: t.message ?? `${s} 执行失败`,
detail: t
});
}
}
/**
* 关闭与服务器创建的 Shell 会话
*
* @returns {Promise<SSHResultType>} 关闭会话结果
*/
async sessionClose() {
if (!this.socket || !this.isSession)
return e.genSuccessResultByConf(this.config, { message: "会话已关闭" });
try {
return await this.socket.destroy(), this.currentCmd = {}, this.isSession = !1, this.socket = null, e.genSuccessResultByConf(this.config, { message: "会话关闭成功" });
} catch (s) {
return e.genFailResultByConf(this.config, {
message: s.message ?? "会话关闭失败",
detail: s
});
}
}
}
export {
B as SSH,
R as SSH_Name
};