如何使用 Deno.Run 在 Deno 中重新创建等同于 linux bash 的语句
How to re-create an equivalent to linux bash statement in Deno with Deno.Run
如何在 Deno 中重新创建等同于以下 Linux bash 语句的语句?
docker compose exec container_name -uroot -ppass db_name < ./dbDump.sql
我尝试了以下方法:
const encoder = new TextEncoder
const p = await Deno.run({
cmd: [
'docker',
'compose',
'exec',
'container_name',
'mysql',
'-uroot',
'-ppass',
'db_name',
],
stdout: 'piped',
stderr: 'piped',
stdin: "piped",
})
await p.stdin.write(encoder.encode(await Deno.readTextFile('./dbDump.sql')))
await p.stdin.close()
await p.close()
但出于某种原因,每当我这样做时,我都会收到一个错误 ERROR 1064 (42000) at line 145: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version
,当我在 bash.
中执行完全相同的命令时,该错误不会发生
有人可以向我解释一下必须如何正确完成吗?
首先,注意几点:
Deno 目前不提供创建分离子流程的方法。 (您没有提到这一点,但鉴于典型的 docker 组合用法,它似乎可能与您的场景相关)请参阅 denoland/deno#5501.
Deno 的子流程 API 目前正在返工中。参见 denoland/deno#11016。
其次,这里是相关文档的链接:
现在,这里以您的场景为例,详细说明了如何创建子流程(根据当前 API):
module.ts
:
const dbUser = 'actual_database_username';
const dbPass = 'actual_database_password'
const dbName = 'actual_database_name';
const dockerExecProcCmd = ['mysql', '-u', dbUser, '-p', dbPass, dbName];
const serviceName = 'actual_compose_service_name';
// Build the run command
const cmd = ['docker', 'compose', 'exec', '-T', serviceName, ...dockerExecProcCmd];
/**
* Create the subprocess
*
* For now, leave `stderr` and `stdout` undefined so they'll print
* to your console while you are debugging. Later, you can pipe (capture) them
* and handle them in your program
*/
const p = Deno.run({
cmd,
stdin: 'piped',
// stderr: 'piped',
// stdout: 'piped',
});
/**
* If you use a relative path, this will be relative to `Deno.cwd`
* at the time the subprocess is created
*
* https://doc.deno.land/deno/stable/~/Deno.cwd
*/
const sqlFilePath = './dbDump.sql';
// Write contents of SQL script to stdin
await p.stdin.write(await Deno.readFile(sqlFilePath));
/**
* Close stdin
*
* I don't know how `mysql` handles `stdin`, but if it needs the EOT sent by
* closing and you don't need to write to `stdin` any more, then this is correct
*/
p.stdin.close();
// Wait for the process to finish (either OK or NOK)
const {code} = await p.status();
console.log({'docker-compose exit status code': code});
// Not strictly necessary, but better to be explicit
p.close();
没有示例输入文件,就无法确定您的确切问题。
尽管考虑到上下文,我怀疑您的输入文件对于单个 proc.stdin.write()
调用来说太大了。尝试使用 the writeAll()
function 以确保完整的有效负载通过:
import { writeAll } from "https://deno.land/std@0.119.0/streams/conversion.ts";
await writeAll(proc.stdin, await Deno.readFile(sqlFilePath));
为了显示此修复的内容,这里有一个 Deno 程序 pipe-to-wc.ts
,它将其输入传递给 Linux 'word count' 实用程序(在字符计数模式下):
#!/usr/bin/env -S deno run --allow-read=/dev/stdin --allow-run=wc
const proc = await Deno.run({
cmd: ['wc', '-c'],
stdin: 'piped',
});
await proc.stdin.write(await Deno.readFile('/dev/stdin'));
proc.stdin.close();
await proc.status();
如果我们使用这个程序,输入较小,则计数为:
# use the shebang to make the following commands easier
$ chmod +x pipe-to-wc.ts
$ dd if=/dev/zero bs=1024 count=1 | ./pipe-to-wc.ts
1+0 records in
1+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.000116906 s, 8.8 MB/s
1024
但是一旦输入很大,只有65k字节通过!
$ dd if=/dev/zero bs=1024 count=100 | ./pipe-to-wc.ts
100+0 records in
100+0 records out
102400 bytes (102 kB, 100 KiB) copied, 0.0424347 s, 2.4 MB/s
65536
要解决此问题,让我们将 write()
调用替换为 writeAll()
:
#!/usr/bin/env -S deno run --allow-read=/dev/stdin --allow-run=wc
const proc = await Deno.run({
cmd: ['wc', '-c'],
stdin: 'piped',
});
import { writeAll } from "https://deno.land/std@0.119.0/streams/conversion.ts";
await writeAll(proc.stdin, await Deno.readFile('/dev/stdin'));
proc.stdin.close();
await proc.status();
现在所有字节都在大输入上传递 :D
$ dd if=/dev/zero bs=1024 count=1000 | ./pipe-to-wc.ts
1000+0 records in
1000+0 records out
1024000 bytes (1.0 MB, 1000 KiB) copied, 0.0854184 s, 12.0 MB/s
1024000
请注意,一旦输入超过程序可用的内存量,这仍然会在大量输入时失败。 writeAll()
解决方案应该可以达到 100 兆字节左右。在那之后,您可能想切换到流媒体解决方案。
如何在 Deno 中重新创建等同于以下 Linux bash 语句的语句?
docker compose exec container_name -uroot -ppass db_name < ./dbDump.sql
我尝试了以下方法:
const encoder = new TextEncoder
const p = await Deno.run({
cmd: [
'docker',
'compose',
'exec',
'container_name',
'mysql',
'-uroot',
'-ppass',
'db_name',
],
stdout: 'piped',
stderr: 'piped',
stdin: "piped",
})
await p.stdin.write(encoder.encode(await Deno.readTextFile('./dbDump.sql')))
await p.stdin.close()
await p.close()
但出于某种原因,每当我这样做时,我都会收到一个错误 ERROR 1064 (42000) at line 145: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version
,当我在 bash.
有人可以向我解释一下必须如何正确完成吗?
首先,注意几点:
Deno 目前不提供创建分离子流程的方法。 (您没有提到这一点,但鉴于典型的 docker 组合用法,它似乎可能与您的场景相关)请参阅 denoland/deno#5501.
Deno 的子流程 API 目前正在返工中。参见 denoland/deno#11016。
其次,这里是相关文档的链接:
现在,这里以您的场景为例,详细说明了如何创建子流程(根据当前 API):
module.ts
:
const dbUser = 'actual_database_username';
const dbPass = 'actual_database_password'
const dbName = 'actual_database_name';
const dockerExecProcCmd = ['mysql', '-u', dbUser, '-p', dbPass, dbName];
const serviceName = 'actual_compose_service_name';
// Build the run command
const cmd = ['docker', 'compose', 'exec', '-T', serviceName, ...dockerExecProcCmd];
/**
* Create the subprocess
*
* For now, leave `stderr` and `stdout` undefined so they'll print
* to your console while you are debugging. Later, you can pipe (capture) them
* and handle them in your program
*/
const p = Deno.run({
cmd,
stdin: 'piped',
// stderr: 'piped',
// stdout: 'piped',
});
/**
* If you use a relative path, this will be relative to `Deno.cwd`
* at the time the subprocess is created
*
* https://doc.deno.land/deno/stable/~/Deno.cwd
*/
const sqlFilePath = './dbDump.sql';
// Write contents of SQL script to stdin
await p.stdin.write(await Deno.readFile(sqlFilePath));
/**
* Close stdin
*
* I don't know how `mysql` handles `stdin`, but if it needs the EOT sent by
* closing and you don't need to write to `stdin` any more, then this is correct
*/
p.stdin.close();
// Wait for the process to finish (either OK or NOK)
const {code} = await p.status();
console.log({'docker-compose exit status code': code});
// Not strictly necessary, but better to be explicit
p.close();
没有示例输入文件,就无法确定您的确切问题。
尽管考虑到上下文,我怀疑您的输入文件对于单个 proc.stdin.write()
调用来说太大了。尝试使用 the writeAll()
function 以确保完整的有效负载通过:
import { writeAll } from "https://deno.land/std@0.119.0/streams/conversion.ts";
await writeAll(proc.stdin, await Deno.readFile(sqlFilePath));
为了显示此修复的内容,这里有一个 Deno 程序 pipe-to-wc.ts
,它将其输入传递给 Linux 'word count' 实用程序(在字符计数模式下):
#!/usr/bin/env -S deno run --allow-read=/dev/stdin --allow-run=wc
const proc = await Deno.run({
cmd: ['wc', '-c'],
stdin: 'piped',
});
await proc.stdin.write(await Deno.readFile('/dev/stdin'));
proc.stdin.close();
await proc.status();
如果我们使用这个程序,输入较小,则计数为:
# use the shebang to make the following commands easier
$ chmod +x pipe-to-wc.ts
$ dd if=/dev/zero bs=1024 count=1 | ./pipe-to-wc.ts
1+0 records in
1+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.000116906 s, 8.8 MB/s
1024
但是一旦输入很大,只有65k字节通过!
$ dd if=/dev/zero bs=1024 count=100 | ./pipe-to-wc.ts
100+0 records in
100+0 records out
102400 bytes (102 kB, 100 KiB) copied, 0.0424347 s, 2.4 MB/s
65536
要解决此问题,让我们将 write()
调用替换为 writeAll()
:
#!/usr/bin/env -S deno run --allow-read=/dev/stdin --allow-run=wc
const proc = await Deno.run({
cmd: ['wc', '-c'],
stdin: 'piped',
});
import { writeAll } from "https://deno.land/std@0.119.0/streams/conversion.ts";
await writeAll(proc.stdin, await Deno.readFile('/dev/stdin'));
proc.stdin.close();
await proc.status();
现在所有字节都在大输入上传递 :D
$ dd if=/dev/zero bs=1024 count=1000 | ./pipe-to-wc.ts
1000+0 records in
1000+0 records out
1024000 bytes (1.0 MB, 1000 KiB) copied, 0.0854184 s, 12.0 MB/s
1024000
请注意,一旦输入超过程序可用的内存量,这仍然会在大量输入时失败。 writeAll()
解决方案应该可以达到 100 兆字节左右。在那之后,您可能想切换到流媒体解决方案。