@lazycatcloud/lzc-cli 1.2.39 → 1.2.41
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.
|
@@ -6,12 +6,22 @@ import {
|
|
|
6
6
|
isTraceMode,
|
|
7
7
|
resolveDomain,
|
|
8
8
|
sleep,
|
|
9
|
-
findSshPublicKey
|
|
9
|
+
findSshPublicKey,
|
|
10
|
+
isWindows,
|
|
11
|
+
contextDirname
|
|
10
12
|
} from "../utils.js"
|
|
11
13
|
import logger from "loglevel"
|
|
12
14
|
import commandExists from "command-exists"
|
|
15
|
+
import path from "node:path"
|
|
13
16
|
|
|
14
|
-
function
|
|
17
|
+
export function sshBinary() {
|
|
18
|
+
if (isWindows) {
|
|
19
|
+
return "ssh"
|
|
20
|
+
}
|
|
21
|
+
return "ssh"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function sshCmdArgs(...args) {
|
|
15
25
|
const defaultOptions = [
|
|
16
26
|
`-o "StrictHostKeyChecking=no"`,
|
|
17
27
|
`-o "UserKnownHostsFile=/dev/null"`,
|
|
@@ -19,7 +29,7 @@ function sshCmdArgs(...args) {
|
|
|
19
29
|
"-p 22222",
|
|
20
30
|
`${isTraceMode() ? "-v" : ""}`
|
|
21
31
|
]
|
|
22
|
-
return [...defaultOptions, ...args]
|
|
32
|
+
return [...defaultOptions, ...args]
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
export class DebugBridge {
|
|
@@ -55,9 +65,9 @@ export class DebugBridge {
|
|
|
55
65
|
const stream = fs.createReadStream(lpkPath)
|
|
56
66
|
const resolvedIp = await resolveDomain(this.domain)
|
|
57
67
|
const ssh = spawn(
|
|
58
|
-
|
|
68
|
+
sshBinary(),
|
|
59
69
|
[
|
|
60
|
-
sshCmdArgs(`box@${resolvedIp}`),
|
|
70
|
+
...sshCmdArgs(`box@${resolvedIp}`),
|
|
61
71
|
`install --uid ${this.uid} --pkgId ${pkgId}`
|
|
62
72
|
],
|
|
63
73
|
{
|
|
@@ -87,8 +97,8 @@ export class DebugBridge {
|
|
|
87
97
|
|
|
88
98
|
// 将当前机器上的ssh public key 写到开发者工具中去,并过滤到重复的,管道在执行前会被清空,需要使用一个中间文件
|
|
89
99
|
const stream = spawn.sync(
|
|
90
|
-
|
|
91
|
-
[sshCmdArgs(`box@${resolvedIp}`), `add-ssh-public-key`],
|
|
100
|
+
sshBinary(),
|
|
101
|
+
[...sshCmdArgs(`box@${resolvedIp}`), `add-ssh-public-key`],
|
|
92
102
|
{
|
|
93
103
|
input: sshInfo.content.trimLeft(),
|
|
94
104
|
shell: true,
|
|
@@ -107,16 +117,16 @@ export class DebugBridge {
|
|
|
107
117
|
}
|
|
108
118
|
|
|
109
119
|
async status(appId) {
|
|
110
|
-
return this.common(
|
|
111
|
-
sshCmdArgs(`box@${this.domain}`),
|
|
120
|
+
return this.common(sshBinary(), [
|
|
121
|
+
...sshCmdArgs(`box@${this.domain}`),
|
|
112
122
|
`status --uid ${this.uid}`,
|
|
113
123
|
appId
|
|
114
124
|
])
|
|
115
125
|
}
|
|
116
126
|
|
|
117
127
|
async isDevshell(appId) {
|
|
118
|
-
const stdout = await this.common(
|
|
119
|
-
sshCmdArgs(`box@${this.domain}`),
|
|
128
|
+
const stdout = await this.common(sshBinary(), [
|
|
129
|
+
...sshCmdArgs(`box@${this.domain}`),
|
|
120
130
|
`isDevshell --uid ${this.uid}`,
|
|
121
131
|
appId
|
|
122
132
|
])
|
|
@@ -124,16 +134,16 @@ export class DebugBridge {
|
|
|
124
134
|
}
|
|
125
135
|
|
|
126
136
|
async resume(appId) {
|
|
127
|
-
return this.common(
|
|
128
|
-
sshCmdArgs(`box@${this.domain}`),
|
|
137
|
+
return this.common(sshBinary(), [
|
|
138
|
+
...sshCmdArgs(`box@${this.domain}`),
|
|
129
139
|
`resume --uid ${this.uid}`,
|
|
130
140
|
appId
|
|
131
141
|
])
|
|
132
142
|
}
|
|
133
143
|
|
|
134
144
|
async uninstall(appId) {
|
|
135
|
-
return this.common(
|
|
136
|
-
sshCmdArgs(`box@${this.domain}`),
|
|
145
|
+
return this.common(sshBinary(), [
|
|
146
|
+
...sshCmdArgs(`box@${this.domain}`),
|
|
137
147
|
`uninstall --uid ${this.uid}`,
|
|
138
148
|
appId
|
|
139
149
|
])
|
|
@@ -153,14 +163,15 @@ export class DebugBridge {
|
|
|
153
163
|
const resolvedIp = await resolveDomain(this.domain)
|
|
154
164
|
|
|
155
165
|
const stream = spawn(
|
|
156
|
-
|
|
166
|
+
sshBinary(),
|
|
157
167
|
[
|
|
158
|
-
sshCmdArgs(`box@${resolvedIp}`),
|
|
168
|
+
...sshCmdArgs(`box@${resolvedIp}`),
|
|
159
169
|
"-t",
|
|
160
170
|
"devshell",
|
|
161
171
|
`--uid ${this.uid}`,
|
|
162
172
|
isUserApp ? "--userapp" : "",
|
|
163
173
|
appId,
|
|
174
|
+
"/bin/sh",
|
|
164
175
|
"/lzcapp/pkg/content/devshell/exec.sh"
|
|
165
176
|
],
|
|
166
177
|
{
|
|
@@ -185,17 +196,17 @@ export class DebugBridge {
|
|
|
185
196
|
const resolvedIp = await resolveDomain(this.domain)
|
|
186
197
|
const stream = fs.createReadStream(contextTar)
|
|
187
198
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
[sshCmdArgs(`box@${resolvedIp}`), `build --tag ${tag}`],
|
|
199
|
+
const buildStream = spawn(
|
|
200
|
+
sshBinary(),
|
|
201
|
+
[...sshCmdArgs(`box@${resolvedIp}`), `build --tag ${tag}`],
|
|
191
202
|
{
|
|
192
203
|
shell: true,
|
|
193
204
|
stdio: ["pipe", "inherit", "inherit"]
|
|
194
205
|
}
|
|
195
206
|
)
|
|
196
|
-
stream.pipe(
|
|
207
|
+
stream.pipe(buildStream.stdin)
|
|
197
208
|
return new Promise((resolve, reject) => {
|
|
198
|
-
|
|
209
|
+
buildStream.on("close", (code) => {
|
|
199
210
|
code == 0
|
|
200
211
|
? resolve(`dev.${this.boxname}.heiyu.space/${tag}`)
|
|
201
212
|
: reject("在盒子中构建 image 失败")
|
package/lib/app/lpk_devshell.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import path from "node:path"
|
|
3
3
|
import fs from "node:fs"
|
|
4
4
|
import logger from "loglevel"
|
|
5
|
-
// import { execSync } from "node:child_process"
|
|
6
5
|
import spawn from "cross-spawn"
|
|
7
6
|
import { LpkInstaller } from "./lpk_installer.js"
|
|
8
7
|
import debounce from "lodash.debounce"
|
|
@@ -19,7 +18,6 @@ import {
|
|
|
19
18
|
isUserApp,
|
|
20
19
|
createTemplateFileCommon,
|
|
21
20
|
isDebugMode,
|
|
22
|
-
isTraceMode,
|
|
23
21
|
resolveDomain,
|
|
24
22
|
isWindows,
|
|
25
23
|
isMacOs,
|
|
@@ -157,36 +155,60 @@ export class AppDevShell {
|
|
|
157
155
|
this.lpkBuild.onBeforeTarContent(async (contentdir) => {
|
|
158
156
|
const busyboxPath = path.join(
|
|
159
157
|
contextDirname(import.meta.url),
|
|
160
|
-
"
|
|
158
|
+
"..",
|
|
159
|
+
"..",
|
|
160
|
+
"template",
|
|
161
|
+
"_lpk",
|
|
162
|
+
"busybox-1.35.0"
|
|
161
163
|
)
|
|
162
164
|
let dest = path.join(contentdir, "devshell", "busybox")
|
|
163
165
|
ensureDir(dest)
|
|
164
166
|
fs.copyFileSync(busyboxPath, dest)
|
|
165
|
-
fs.chmodSync(dest, 0o775)
|
|
166
167
|
})
|
|
167
168
|
|
|
168
169
|
// 复制 init_debug_bridge.sh 到 devshell 中去
|
|
169
170
|
this.lpkBuild.onBeforeTarContent(async (contentdir) => {
|
|
170
171
|
const initPath = path.join(
|
|
171
172
|
contextDirname(import.meta.url),
|
|
172
|
-
"
|
|
173
|
+
"..",
|
|
174
|
+
"..",
|
|
175
|
+
"template",
|
|
176
|
+
"_lpk",
|
|
177
|
+
"init_debug_bridge.sh"
|
|
173
178
|
)
|
|
174
179
|
let dest = path.join(contentdir, "devshell", "init_debug_bridge.sh")
|
|
175
180
|
ensureDir(dest)
|
|
176
181
|
fs.copyFileSync(initPath, dest)
|
|
177
|
-
fs.chmodSync(dest, 0o775)
|
|
178
182
|
})
|
|
179
183
|
|
|
180
184
|
// 复制 exec.sh 到 devshell 中去
|
|
181
185
|
this.lpkBuild.onBeforeTarContent(async (contentdir) => {
|
|
182
186
|
const execScriptPath = path.join(
|
|
183
187
|
contextDirname(import.meta.url),
|
|
184
|
-
"
|
|
188
|
+
"..",
|
|
189
|
+
"..",
|
|
190
|
+
"template",
|
|
191
|
+
"_lpk",
|
|
192
|
+
"exec.sh"
|
|
185
193
|
)
|
|
186
194
|
let dest = path.join(contentdir, "devshell", "exec.sh")
|
|
187
195
|
ensureDir(dest)
|
|
188
196
|
fs.copyFileSync(execScriptPath, dest)
|
|
189
|
-
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// 复制 rsyncd.conf 到 devshell 中去
|
|
200
|
+
this.lpkBuild.onBeforeTarContent(async (contentdir) => {
|
|
201
|
+
const execScriptPath = path.join(
|
|
202
|
+
contextDirname(import.meta.url),
|
|
203
|
+
"..",
|
|
204
|
+
"..",
|
|
205
|
+
"template",
|
|
206
|
+
"_lpk",
|
|
207
|
+
"rsyncd.conf"
|
|
208
|
+
)
|
|
209
|
+
let dest = path.join(contentdir, "devshell", "rsyncd.conf")
|
|
210
|
+
ensureDir(dest)
|
|
211
|
+
fs.copyFileSync(execScriptPath, dest)
|
|
190
212
|
})
|
|
191
213
|
|
|
192
214
|
// 复制 setupscript 脚本
|
|
@@ -207,7 +229,6 @@ export class AppDevShell {
|
|
|
207
229
|
} else {
|
|
208
230
|
fs.writeFileSync(dest, `#!/bin/sh\nset -ex\n${devshell["setupscript"]}`)
|
|
209
231
|
}
|
|
210
|
-
fs.chmodSync(dest, 0o775)
|
|
211
232
|
})
|
|
212
233
|
|
|
213
234
|
// 在生成 manifest.yml 之前合并 devshell manifest 模板字段
|
|
@@ -219,9 +240,10 @@ export class AppDevShell {
|
|
|
219
240
|
logger.debug("options devshell delete 'routes' field")
|
|
220
241
|
delete options["devshell"]["routes"]
|
|
221
242
|
|
|
222
|
-
// 添加 devshell
|
|
243
|
+
// 添加 devshell 必要路由,这里需要使用 /bin/sh 启动后面的脚本,因为在
|
|
244
|
+
// Windows 上打包的文件将会丢失可执行权限
|
|
223
245
|
routes.push(
|
|
224
|
-
"/__debug.bridge=exec://80,/lzcapp/pkg/content/devshell/init_debug_bridge.sh"
|
|
246
|
+
"/__debug.bridge=exec://80,/bin/sh /lzcapp/pkg/content/devshell/init_debug_bridge.sh"
|
|
225
247
|
)
|
|
226
248
|
routes.push("/__isdevshell=file:///lzcapp/pkg/devshell")
|
|
227
249
|
|
|
@@ -286,7 +308,11 @@ export class AppDevShell {
|
|
|
286
308
|
try {
|
|
287
309
|
const dockerfilePath = path.join(
|
|
288
310
|
contextDirname(import.meta.url),
|
|
289
|
-
"
|
|
311
|
+
"..",
|
|
312
|
+
"..",
|
|
313
|
+
"template",
|
|
314
|
+
"_lpk",
|
|
315
|
+
"Dockerfile.in"
|
|
290
316
|
)
|
|
291
317
|
await createTemplateFileCommon(
|
|
292
318
|
dockerfilePath,
|
|
@@ -418,25 +444,6 @@ class DevShell {
|
|
|
418
444
|
}
|
|
419
445
|
|
|
420
446
|
async syncProject(appId) {
|
|
421
|
-
// prettier-ignore
|
|
422
|
-
const resolvedIp = await resolveDomain(`dev.${shellApi.boxname}.heiyu.space`);
|
|
423
|
-
let rsh = [
|
|
424
|
-
"ssh",
|
|
425
|
-
"-o",
|
|
426
|
-
`"ProxyCommand ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -q -W %h:%p -p 22222 box@${resolvedIp}"`,
|
|
427
|
-
"-p",
|
|
428
|
-
`22222`,
|
|
429
|
-
"-o",
|
|
430
|
-
`"StrictHostKeyChecking=no"`,
|
|
431
|
-
"-o",
|
|
432
|
-
`"UserKnownHostsFile=/dev/null"`,
|
|
433
|
-
"-o",
|
|
434
|
-
`"ConnectionAttempts=3"`,
|
|
435
|
-
"-o",
|
|
436
|
-
`"ConnectTimeout=30"`,
|
|
437
|
-
"-o",
|
|
438
|
-
`${isTraceMode() ? '"LogLevel=DEBUG"' : '"LogLevel=ERROR"'}`
|
|
439
|
-
].join(" ")
|
|
440
447
|
if (isLinux || isMacOs) {
|
|
441
448
|
// 检查rsync工具是否存在:提示用户
|
|
442
449
|
const rsyncExisted = commandExists.sync("rsync")
|
|
@@ -446,22 +453,29 @@ class DevShell {
|
|
|
446
453
|
}
|
|
447
454
|
}
|
|
448
455
|
|
|
456
|
+
const resolvedIp = await resolveDomain(
|
|
457
|
+
`dev.${shellApi.boxname}.heiyu.space`
|
|
458
|
+
)
|
|
449
459
|
const rsyncDebug = isDebugMode() ? "-P" : ""
|
|
450
460
|
const host = this.isUserApp
|
|
451
461
|
? `${shellApi.uid}.app.${appId}.lzcapp`
|
|
452
462
|
: `app.${appId}.lzcapp`
|
|
453
|
-
const dest = `
|
|
463
|
+
const dest = `rsync://${host}@[${resolvedIp}]:873/lzcapp/cache/devshell`
|
|
454
464
|
const rsyncCmd = isWindows
|
|
455
465
|
? path.join(
|
|
456
466
|
contextDirname(import.meta.url),
|
|
457
|
-
"
|
|
467
|
+
"..",
|
|
468
|
+
"..",
|
|
469
|
+
"template",
|
|
470
|
+
"_lpk",
|
|
471
|
+
"win-rsync",
|
|
472
|
+
"rsync.exe"
|
|
458
473
|
)
|
|
459
474
|
: `rsync`
|
|
460
475
|
|
|
461
476
|
try {
|
|
462
477
|
const rsyncArgs = [
|
|
463
478
|
`${rsyncDebug}`,
|
|
464
|
-
`--rsh='${rsh}'`,
|
|
465
479
|
`--recursive`,
|
|
466
480
|
`--relative`,
|
|
467
481
|
`--perms`,
|
|
@@ -472,6 +486,7 @@ class DevShell {
|
|
|
472
486
|
]
|
|
473
487
|
logger.debug("同步代码: ", rsyncCmd, rsyncArgs.join(" "))
|
|
474
488
|
const rsyncStream = spawn.sync(rsyncCmd, rsyncArgs, {
|
|
489
|
+
env: { RSYNC_PASSWORD: "fakefakefake" },
|
|
475
490
|
shell: true,
|
|
476
491
|
stdio: ["ignore", isDebugMode() ? "inherit" : "ignore", "inherit"]
|
|
477
492
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.41",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"files": [
|
|
6
6
|
"template",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"@balena/dockerignore": "^1.0.2",
|
|
21
21
|
"@grpc/grpc-js": "^1.11.1",
|
|
22
22
|
"@grpc/proto-loader": "^0.7.13",
|
|
23
|
+
"@lazycatcloud/sdk": "^0.1.423",
|
|
23
24
|
"adm-zip": "^0.5.16",
|
|
24
25
|
"archiver": "^7.0.1",
|
|
25
26
|
"axios": "^1.7.7",
|
|
File without changes
|
package/template/_lpk/exec.sh
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# 从1号进程读取环境变量
|
|
5
5
|
cat > /tmp/lzcapp_env.sh << EOF
|
|
6
6
|
#!/bin/sh
|
|
7
|
-
$(/
|
|
7
|
+
$(/usr/lib/debug.bridge/busybox tr '\0' '\n' < /proc/1/environ | /usr/lib/debug.bridge/busybox xargs -I{} echo export {})
|
|
8
8
|
EOF
|
|
9
9
|
. /tmp/lzcapp_env.sh
|
|
10
10
|
|
|
@@ -2,30 +2,38 @@
|
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
4
|
DEBUG_BRIDGE_LZCAPP=http://app.cloud.lazycat.developer.tools.lzcapp
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
mkdir -p /usr/lib/debug.bridge/
|
|
7
|
+
# 不能直接对 pkg content 中的 busybox chmod(Read-Only权限)
|
|
8
|
+
LZCBUSYBOX=/usr/lib/debug.bridge/busybox
|
|
9
|
+
cp /lzcapp/pkg/content/devshell/busybox ${LZCBUSYBOX}
|
|
10
|
+
chmod +x ${LZCBUSYBOX}
|
|
6
11
|
|
|
7
12
|
mkdir -p /root/.ssh
|
|
8
13
|
mkdir -p /etc/debug.bridge
|
|
9
14
|
|
|
10
15
|
if ! [ -f /usr/bin/dropbearmulti ]; then
|
|
11
|
-
${
|
|
16
|
+
${LZCBUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/dropbearmulti -O /usr/bin/dropbearmulti
|
|
12
17
|
chmod +x /usr/bin/dropbearmulti
|
|
13
18
|
fi
|
|
14
19
|
|
|
15
20
|
if ! [ -f /usr/bin/rsync ]; then
|
|
16
|
-
${
|
|
21
|
+
${LZCBUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/rsync -O /usr/bin/rsync
|
|
17
22
|
chmod +x /usr/bin/rsync
|
|
18
23
|
fi
|
|
19
24
|
|
|
20
|
-
${
|
|
25
|
+
${LZCBUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/authorized_keys -O /root/.ssh/authorized_keys
|
|
21
26
|
chmod 0644 /root/.ssh/authorized_keys
|
|
22
27
|
|
|
23
|
-
${
|
|
28
|
+
${LZCBUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/bannerfile -O /etc/debug.bridge/bannerfile
|
|
24
29
|
|
|
25
|
-
if ${
|
|
30
|
+
if ${LZCBUSYBOX} netstat -tln | grep ':22222' >/dev/null; then
|
|
26
31
|
echo "端口22222正在监听"
|
|
27
|
-
${
|
|
32
|
+
${LZCBUSYBOX} sleep infinity
|
|
28
33
|
else
|
|
34
|
+
echo "启动 rsync daemon."
|
|
35
|
+
rsync --daemon --no-detach --config=/lzcapp/pkg/content/devshell/rsyncd.conf &
|
|
36
|
+
|
|
29
37
|
mkdir -p /etc/dropbear
|
|
30
38
|
exec dropbearmulti dropbear -R -F -E -B -p 22222
|
|
31
39
|
fi
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 全局参数
|
|
2
|
+
uid = root
|
|
3
|
+
gid = root
|
|
4
|
+
use chroot = no
|
|
5
|
+
max connections = 4
|
|
6
|
+
timeout = 300
|
|
7
|
+
pid file = /var/run/rsyncd.pid
|
|
8
|
+
lock file = /var/run/rsync.lock
|
|
9
|
+
|
|
10
|
+
# 实时输出设置
|
|
11
|
+
log file = /dev/stdout
|
|
12
|
+
transfer logging = yes
|
|
13
|
+
log format = %t rsync [%p] %o %h [%a] %m %f %l
|
|
14
|
+
|
|
15
|
+
[lzcapp]
|
|
16
|
+
path = /lzcapp
|
|
17
|
+
read only = no
|
|
18
|
+
dont compress = *.gz *.bz2 *.zip
|
|
19
|
+
|
|
20
|
+
[root]
|
|
21
|
+
path = /root/
|
|
22
|
+
read only = no
|
|
23
|
+
dont compress = *.gz *.bz2 *.zip
|
|
24
|
+
|
|
25
|
+
[tmp]
|
|
26
|
+
path = /tmp/
|
|
27
|
+
read only = no
|
|
28
|
+
dont compress = *.gz *.bz2 *.zip
|