ssh-client-wrapper 1.7.9 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/run_test.yml +0 -22
- package/lib/fork.js +5 -2
- package/lib/sshExec.js +41 -10
- package/package.json +1 -1
|
@@ -34,25 +34,3 @@ jobs:
|
|
|
34
34
|
node-version: ${{ matrix.node-version }}
|
|
35
35
|
- run: npm ci
|
|
36
36
|
- run: npm run test
|
|
37
|
-
- run: npm run coverage
|
|
38
|
-
- uses: actions/upload-artifact@v3
|
|
39
|
-
with:
|
|
40
|
-
name: code-coverage-report
|
|
41
|
-
path: coverage-report.lcov
|
|
42
|
-
retention-days: 1
|
|
43
|
-
coverage:
|
|
44
|
-
needs: [test]
|
|
45
|
-
name: coverage report
|
|
46
|
-
runs-on: ubuntu-latest
|
|
47
|
-
env:
|
|
48
|
-
CC_TEST_REPORTER_ID: 52ae52d099fd6546c12030f23b20e2a4e0b485c6a1b139ec11e3615ab073e689
|
|
49
|
-
steps:
|
|
50
|
-
- run: echo ${CC_TEST_REPORTER_ID}
|
|
51
|
-
- run: echo '${{ toJSON(secrets.ccid) }}'
|
|
52
|
-
- uses: actions/checkout@v3
|
|
53
|
-
- uses: actions/download-artifact@v3
|
|
54
|
-
with:
|
|
55
|
-
name: code-coverage-report
|
|
56
|
-
- uses: paambaati/codeclimate-action@v5.0.0
|
|
57
|
-
with:
|
|
58
|
-
coverageLocations: "coverage-report.lcov:lcov"
|
package/lib/fork.js
CHANGED
|
@@ -62,9 +62,10 @@ function getMasterPty(hostInfo) {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
async function fork(hostInfo, cmd, args, outputCallback) {
|
|
65
|
-
|
|
65
|
+
let ptyProcess = null;
|
|
66
|
+
const p = new Promise((resolve, reject)=>{
|
|
66
67
|
debug(`cmd=${cmd}: args=${args}`);
|
|
67
|
-
|
|
68
|
+
ptyProcess = spawn(cmd, args, nodePtyOpt);
|
|
68
69
|
ptyProcess.onData(buff2String.bind(null, debugVerbose));
|
|
69
70
|
ptyProcess.onData((data)=>{
|
|
70
71
|
const output = data.toString();
|
|
@@ -97,6 +98,8 @@ async function fork(hostInfo, cmd, args, outputCallback) {
|
|
|
97
98
|
return reject(err);
|
|
98
99
|
});
|
|
99
100
|
});
|
|
101
|
+
p.pty = ptyProcess;
|
|
102
|
+
return p;
|
|
100
103
|
}
|
|
101
104
|
module.exports = {
|
|
102
105
|
fork,
|
package/lib/sshExec.js
CHANGED
|
@@ -64,6 +64,9 @@ async function canConnect(hostInfo, timeout = 60) {
|
|
|
64
64
|
* @returns {boolean} - true if master session exists
|
|
65
65
|
*/
|
|
66
66
|
async function existsMaster(hostInfo) {
|
|
67
|
+
const ac = new AbortController();
|
|
68
|
+
const signal = ac.signal;
|
|
69
|
+
|
|
67
70
|
const args = getSshOption(hostInfo);
|
|
68
71
|
args.push("-Ocheck");
|
|
69
72
|
|
|
@@ -72,16 +75,38 @@ async function existsMaster(hostInfo) {
|
|
|
72
75
|
output += e;
|
|
73
76
|
};
|
|
74
77
|
|
|
78
|
+
let rt = true; //if timeout occurred during ssh -Ocheck, it will turn to false
|
|
79
|
+
let p;
|
|
80
|
+
const timeout = hostInfo.ConnectTimeout || 60;
|
|
81
|
+
setTimeoutPromise(timeout * 1000, "neverUsedValue", { signal })
|
|
82
|
+
.then(()=>{
|
|
83
|
+
if (p.pty) {
|
|
84
|
+
p.pty.kill();
|
|
85
|
+
}
|
|
86
|
+
rt = false;
|
|
87
|
+
})
|
|
88
|
+
.catch((err)=>{
|
|
89
|
+
if (err.name === "AbortError") {
|
|
90
|
+
debug("timeout was aborted because master session check has done");
|
|
91
|
+
} else {
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
|
|
75
97
|
try {
|
|
76
98
|
debug(`check master session: ${sshCmd} ${args.join(" ")}`);
|
|
77
|
-
|
|
99
|
+
p = fork(hostInfo, sshCmd, args, cb);
|
|
100
|
+
await p;
|
|
101
|
+
ac.abort();
|
|
78
102
|
} catch (err) {
|
|
79
103
|
if (err.rt !== 255) {
|
|
80
104
|
debug("check master session failed", err);
|
|
81
105
|
throw err;
|
|
82
106
|
}
|
|
83
107
|
}
|
|
84
|
-
|
|
108
|
+
|
|
109
|
+
return rt && !/Control socket connect.*: No such file or directory/.test(output);
|
|
85
110
|
}
|
|
86
111
|
|
|
87
112
|
/**
|
|
@@ -94,8 +119,13 @@ async function connect(hostInfo, timeout = 60) {
|
|
|
94
119
|
return;
|
|
95
120
|
}
|
|
96
121
|
debug(`create master ssh session to ${hostInfo.host}`);
|
|
97
|
-
|
|
98
|
-
hostInfo.masterPty
|
|
122
|
+
|
|
123
|
+
if (!hostInfo.masterPty) {
|
|
124
|
+
debug(`create master pty for ${hostInfo.host}`);
|
|
125
|
+
hostInfo.masterPty = getMasterPty(hostInfo);
|
|
126
|
+
} else {
|
|
127
|
+
debug(`master pty for ${hostInfo.host} exists`);
|
|
128
|
+
}
|
|
99
129
|
|
|
100
130
|
const ac = new AbortController();
|
|
101
131
|
const signal = ac.signal;
|
|
@@ -105,8 +135,8 @@ async function connect(hostInfo, timeout = 60) {
|
|
|
105
135
|
err.host = hostInfo.host;
|
|
106
136
|
err.user = hostInfo.user;
|
|
107
137
|
err.port = hostInfo.port;
|
|
108
|
-
|
|
109
|
-
|
|
138
|
+
hostInfo.masterPty.write("\n");
|
|
139
|
+
hostInfo.masterPty.write("exit\n");
|
|
110
140
|
throw err;
|
|
111
141
|
})
|
|
112
142
|
.catch((err)=>{
|
|
@@ -119,8 +149,9 @@ async function connect(hostInfo, timeout = 60) {
|
|
|
119
149
|
const re = new RegExp(`^${words}`);
|
|
120
150
|
const p = new Promise((resolve, reject)=>{
|
|
121
151
|
let done = false;
|
|
122
|
-
|
|
152
|
+
hostInfo.masterPty.onData((data)=>{
|
|
123
153
|
if (done) {
|
|
154
|
+
//safeguard
|
|
124
155
|
return;
|
|
125
156
|
}
|
|
126
157
|
const output = data.toString();
|
|
@@ -128,7 +159,7 @@ async function connect(hostInfo, timeout = 60) {
|
|
|
128
159
|
|
|
129
160
|
if (re.test(output)) {
|
|
130
161
|
debug("test done. call exit on remotehost");
|
|
131
|
-
|
|
162
|
+
hostInfo.masterPty.write("exit\n");
|
|
132
163
|
done = true;
|
|
133
164
|
resolve();
|
|
134
165
|
} else if (/Permission denied \(/.test(output)) {
|
|
@@ -141,7 +172,7 @@ async function connect(hostInfo, timeout = 60) {
|
|
|
141
172
|
reject(new Error("Operation timed out"));
|
|
142
173
|
}
|
|
143
174
|
});
|
|
144
|
-
|
|
175
|
+
hostInfo.masterPty.onExit((e)=>{
|
|
145
176
|
debug("master pty exit", e);
|
|
146
177
|
resolve(e);
|
|
147
178
|
});
|
|
@@ -151,7 +182,7 @@ async function connect(hostInfo, timeout = 60) {
|
|
|
151
182
|
args.push(`echo ${words}`);
|
|
152
183
|
const cmd = `${sshCmd} ${args.join(" ")}\n`;
|
|
153
184
|
debugVerbose(cmd);
|
|
154
|
-
|
|
185
|
+
hostInfo.masterPty.write(cmd);
|
|
155
186
|
await p;
|
|
156
187
|
ac.abort();
|
|
157
188
|
debug(`connected to ${hostInfo.host}`);
|