@lazycatcloud/lzc-cli 1.2.39 → 1.2.42

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.
@@ -187,6 +187,11 @@ export class LpkBuild {
187
187
  if (!isValidPackageName(this.manifest["package"])) {
188
188
  throw `${this.manifest["package"]} 含有非法字符,请使用正确的包名格式(java的包名格式),如:cloud.lazycat.apps.video`
189
189
  }
190
+
191
+ if (!this.manifest["application"]["subdomain"]) {
192
+ throw `application 模块下的 subdomain 字段不能为空`
193
+ }
194
+
190
195
  return this.manifest
191
196
  }
192
197
 
@@ -28,7 +28,11 @@ export class LpkManifest {
28
28
  if (!manifestFilePath) {
29
29
  manifestFilePath = path.join(
30
30
  this.pwd,
31
- "../../template/_lpk/manifest.yml.in"
31
+ "..",
32
+ "..",
33
+ "template",
34
+ "_lpk",
35
+ "manifest.yml.in"
32
36
  )
33
37
  }
34
38
 
@@ -88,7 +92,11 @@ export class TemplateInit {
88
92
  // 优先使用模板项目自定义的模板文件
89
93
  const typeTemplatePath = path.join(
90
94
  contextDirname(import.meta.url),
91
- `../../template/_lpk/${this.type}.manifest.yml.in`
95
+ "..",
96
+ "..",
97
+ "template",
98
+ "_lpk",
99
+ `${this.type}.manifest.yml.in`
92
100
  )
93
101
  const templatePath = isFileExist(typeTemplatePath) ? typeTemplatePath : ""
94
102
  await this.lpkManifest.init(templatePath, true)
@@ -10,10 +10,10 @@ import logger from "loglevel"
10
10
  const __dirname = contextDirname(import.meta.url)
11
11
 
12
12
  async function loadFiles(dirPath, prefix = "") {
13
- const templateRoot = path.join(__dirname, "../../template/")
13
+ const templateRoot = path.join(__dirname, "..", "..", "template")
14
14
  const templateDir = path.join(templateRoot, dirPath)
15
15
 
16
- const _files = await glob(["**/*"], { cwd: templateDir })
16
+ const _files = await glob(["**/*", "**/.*", ".*"], { cwd: templateDir })
17
17
  let content
18
18
  let files = {}
19
19
  for (let p of _files) {
@@ -59,7 +59,11 @@ function appendREADME(dir) {
59
59
  const readme = path.resolve(dir, "README.md")
60
60
  const readmeTemplate = path.resolve(
61
61
  __dirname,
62
- "../../template/_lpk/README.md"
62
+ "..",
63
+ "..",
64
+ "template",
65
+ "_lpk",
66
+ "README.md"
63
67
  )
64
68
  if (!isFileExist(readme)) {
65
69
  fs.copyFileSync(readmeTemplate, readme)
@@ -85,14 +89,22 @@ function vueTemplate(type) {
85
89
 
86
90
  const lzcBuildTemplatePath = path.resolve(
87
91
  __dirname,
88
- `../../template/_lpk/vue.lzc-build.yml.in`
92
+ "..",
93
+ "..",
94
+ "template",
95
+ "_lpk",
96
+ "vue.lzc-build.yml.in"
89
97
  )
90
98
  logger.debug("复制", lzcBuildTemplatePath)
91
99
  fs.copyFileSync(lzcBuildTemplatePath, path.resolve(name, "lzc-build.yml"))
92
100
 
93
101
  const iconPngPath = path.resolve(
94
102
  __dirname,
95
- "../../template/_lpk/lazycat.png"
103
+ "..",
104
+ "..",
105
+ "template",
106
+ "_lpk",
107
+ "lazycat.png"
96
108
  )
97
109
  fs.copyFileSync(iconPngPath, path.resolve(name, "lazycat.png"))
98
110
 
@@ -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 sshCmdArgs(...args) {
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].join(" ")
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
- "ssh",
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
- "ssh",
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("ssh", [
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("ssh", [
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("ssh", [
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("ssh", [
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
- "ssh",
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 ssh = spawn(
189
- "ssh",
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(ssh.stdin)
207
+ stream.pipe(buildStream.stdin)
197
208
  return new Promise((resolve, reject) => {
198
- ssh.on("close", (code) => {
209
+ buildStream.on("close", (code) => {
199
210
  code == 0
200
211
  ? resolve(`dev.${this.boxname}.heiyu.space/${tag}`)
201
212
  : reject("在盒子中构建 image 失败")
@@ -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
- "../../template/_lpk/busybox-1.35.0"
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
- "../../template/_lpk/init_debug_bridge.sh"
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
- "../../template/_lpk/exec.sh"
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
- fs.chmodSync(dest, 0o775)
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
- "../../template/_lpk/Dockerfile.in"
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 = `root@${host}:/lzcapp/cache/devshell`
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
- "../../template/_lpk/win-rsync/rsync.exe"
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
  })
@@ -93,8 +93,12 @@ export class LpkInstaller {
93
93
  const tempDir = fs.mkdtempSync(".lzc-cli-install")
94
94
  let manifest
95
95
  try {
96
- unzipSync(pkgPath, tempDir)
96
+ unzipSync(pkgPath, tempDir, ["manifest.yml", "icon.png"])
97
97
  manifest = loadFromYaml(path.join(tempDir, "manifest.yml"))
98
+ if (!manifest["application"]["subdomain"]) {
99
+ throw "manifest.yml 中的 `application.subdomain` 字段不能为空"
100
+ }
101
+
98
102
  logger.debug("是否生成APK:", installConfig.apk)
99
103
  if (installConfig.apk) {
100
104
  await triggerApk(
@@ -6,6 +6,7 @@ import inquirer from "inquirer"
6
6
  import path from "node:path"
7
7
  import { isFileExist, isPngWithFile, unzipSync } from "../utils.js"
8
8
  import env from "../env.js"
9
+ import { Publish } from "./publish.js"
9
10
 
10
11
  async function askChangeLog() {
11
12
  const noEmpty = (value) => value != ""
@@ -37,36 +38,6 @@ export class PrePublish {
37
38
  this.baseUrl = baseUrl
38
39
  }
39
40
 
40
- /**
41
- * @param {string} raw
42
- */
43
- isJSON(raw) {
44
- const ml = raw.length
45
- if (ml <= 1) return false
46
- return raw[0] == "{" && raw[ml - 1] == "}"
47
- }
48
-
49
- preCheck(pkgPath) {
50
- const tempDir = fs.mkdtempSync(".lzc-cli-publish")
51
- try {
52
- unzipSync(pkgPath, tempDir)
53
- if (isFileExist(path.join(tempDir, "devshell"))) {
54
- logger.error(
55
- "不能发布一个devshell的版本,请重新使用 `lzc-cli project build` 构建"
56
- )
57
- return false
58
- }
59
- const tempIcon = path.join(tempDir, "icon.png")
60
- if (!isFileExist(tempIcon) || !isPngWithFile(tempIcon)) {
61
- logger.error("icon 必须是 png 格式")
62
- return false
63
- }
64
- return true
65
- } finally {
66
- fs.rmSync(tempDir, { recursive: true })
67
- }
68
- }
69
-
70
41
  async getDict() {
71
42
  const url = this.baseUrl + "/groups/dict"
72
43
  const token = env.get("token")
@@ -77,7 +48,7 @@ export class PrePublish {
77
48
  }
78
49
  })
79
50
  const text = (await res.text()).trim()
80
- if (!this.isJSON(text)) {
51
+ if (!Publish.isJSON(text)) {
81
52
  logger.error(`parse error: dict resp text not is json`)
82
53
  return
83
54
  }
@@ -101,7 +72,7 @@ export class PrePublish {
101
72
  }
102
73
  })
103
74
  const text = (await res.text()).trim()
104
- if (!this.isJSON(text)) {
75
+ if (!Publish.isJSON(text)) {
105
76
  logger.error(`parse error: upload resp text not is json`)
106
77
  return
107
78
  }
@@ -115,7 +86,7 @@ export class PrePublish {
115
86
  * @param {string} changelog
116
87
  */
117
88
  async publish(pkgPath, changelog, gid) {
118
- if (!this.preCheck(pkgPath)) return
89
+ if (!Publish.preCheck(pkgPath)) return
119
90
 
120
91
  await autoLogin()
121
92
 
@@ -26,16 +26,16 @@ export class Publish {
26
26
  /**
27
27
  * @param {string} raw
28
28
  */
29
- isJSON(raw) {
29
+ static isJSON(raw) {
30
30
  const ml = raw.length
31
31
  if (ml <= 1) return false
32
32
  return raw[0] == "{" && raw[ml - 1] == "}"
33
33
  }
34
34
 
35
- preCheck(pkgPath) {
35
+ static preCheck(pkgPath) {
36
36
  const tempDir = fs.mkdtempSync(".lzc-cli-publish")
37
37
  try {
38
- unzipSync(pkgPath, tempDir)
38
+ unzipSync(pkgPath, tempDir, ["devshell", "icon.png"])
39
39
  if (isFileExist(path.join(tempDir, "devshell"))) {
40
40
  logger.error(
41
41
  "不能发布一个devshell的版本,请重新使用 `lzc-cli project build` 构建"
@@ -44,7 +44,7 @@ export class Publish {
44
44
  }
45
45
  const tempIcon = path.join(tempDir, "icon.png")
46
46
  if (!isFileExist(tempIcon) || !isPngWithFile(tempIcon)) {
47
- logger.error("icon 必须是 png 格式")
47
+ logger.error("icon 必须存在且要求是 png 格式")
48
48
  return false
49
49
  }
50
50
  return true
@@ -58,7 +58,7 @@ export class Publish {
58
58
  * @param {string} changelog
59
59
  */
60
60
  async publish(pkgPath, changelog) {
61
- if (!this.preCheck(pkgPath)) return
61
+ if (!Publish.preCheck(pkgPath)) return
62
62
 
63
63
  await autoLogin()
64
64
 
@@ -80,7 +80,7 @@ export class Publish {
80
80
  body: form
81
81
  })
82
82
  const text = (await res.text()).trim()
83
- if (!this.isJSON(text)) {
83
+ if (!Publish.isJSON(text)) {
84
84
  logger.info("upload lpk fail", text)
85
85
  return
86
86
  }
package/lib/utils.js CHANGED
@@ -474,14 +474,24 @@ export async function resolveDomain(domain) {
474
474
  }
475
475
  }
476
476
 
477
- export function unzipSync(zipPath, destPath) {
477
+ export function unzipSync(zipPath, destPath, entries = []) {
478
478
  // 确保目标目录存在
479
479
  fs.mkdirSync(destPath, { recursive: true })
480
480
  // 创建 zip 实例
481
481
  const zip = new AdmZip(zipPath)
482
482
 
483
- // 同步解压所有文件
484
- zip.extractAllTo(destPath, true)
483
+ if (entries.length > 0) {
484
+ entries.forEach((entry) => {
485
+ try {
486
+ zip.extractEntryTo(entry, destPath, false, true)
487
+ } catch {
488
+ logger.debug(`压缩包中没有找到 ${entry} 文件`)
489
+ }
490
+ })
491
+ } else {
492
+ // 同步解压所有文件
493
+ zip.extractAllTo(destPath, true)
494
+ }
485
495
  }
486
496
 
487
497
  export function findSshPublicKey() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazycatcloud/lzc-cli",
3
- "version": "1.2.39",
3
+ "version": "1.2.42",
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
@@ -4,7 +4,7 @@
4
4
  # 从1号进程读取环境变量
5
5
  cat > /tmp/lzcapp_env.sh << EOF
6
6
  #!/bin/sh
7
- $(/lzcapp/pkg/content/devshell/busybox tr '\0' '\n' < /proc/1/environ | /lzcapp/pkg/content/devshell/busybox xargs -I{} echo export {})
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
- BUSYBOX=/lzcapp/pkg/content/devshell/busybox
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
- ${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/dropbearmulti -O /usr/bin/dropbearmulti
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
- ${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/rsync -O /usr/bin/rsync
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
- ${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/authorized_keys -O /root/.ssh/authorized_keys
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
- ${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/bannerfile -O /etc/debug.bridge/bannerfile
28
+ ${LZCBUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/bannerfile -O /etc/debug.bridge/bannerfile
24
29
 
25
- if ${BUSYBOX} netstat -tln | grep ':22222' >/dev/null; then
30
+ if ${LZCBUSYBOX} netstat -tln | grep ':22222' >/dev/null; then
26
31
  echo "端口22222正在监听"
27
- ${BUSYBOX} sleep infinity
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
@@ -0,0 +1,4 @@
1
+ **/*.lpk
2
+ **/*.tar.gz
3
+ **/*.md5
4
+ /.pushed.timestamp
@@ -0,0 +1,25 @@
1
+ .DS_Store
2
+ node_modules
3
+ dist
4
+ *.lpk
5
+
6
+ # local env files
7
+ .env.local
8
+ .env.*.local
9
+
10
+ # Log files
11
+ npm-debug.log*
12
+ yarn-debug.log*
13
+ yarn-error.log*
14
+ pnpm-debug.log*
15
+
16
+ # Editor directories and files
17
+ .idea
18
+ .vscode
19
+ *.suo
20
+ *.ntvs*
21
+ *.njsproj
22
+ *.sln
23
+ *.sw?
24
+ .temp
25
+ .cache