关于 Deno.run() 中使用的 `cmd` 参数组成的困惑

Confusion about the composition of the `cmd` parameter used in Deno.run()

我尝试使用 Deno 替代 shell 脚本,但卡住了。

我试图使用 Deno/Typescript 来执行与此等效的工作:

docker run \
  -d \
  -v pgdata:/var/lib/postgresql/data \
  --name pg \
  -e POSTGRES_PASSWORD=123456 \
  --rm \
  -p 5432:5432 \
  postgres

ts 代码如下所示:

function runCmd(s: string[]): Deno.Process {
    return Deno.run({ cmd: s, stdout: "piped", stderr: "piped" })
}

function runPg() {
    const cmd = [
        "docker", 
        `run -d -v ${VOLUME}:/var/lib/postgresql/data --name pg -e POSTGRES_PASSWORD=${PASSWORD} --rm -p 5432:5432 postgres`
    ];

    return runCmd(cmd);
}

将执行位添加到此 ts 文件并 运行 它在终端中:

在此之后,我尝试了

function runPg() {
    const cmd = [
        "docker", 
        "run",
        `-d -v ${VOLUME}:/var/lib/postgresql/data --name pg -e POSTGRES_PASSWORD=${PASSWORD} --rm -p 5432:5432 postgres`
    ];

    return runCmd(cmd);
}

从命令选项中移出子命令 run

我明白了:

我想 Deno.run 不会简单地连接传入的命令粒子字符串,但我找不到足够的信息来解决这个问题。

我还没有研究过这个 API 的 rust 源代码,但我认为在尝试困难的方法之前寻求帮助会更好。

您需要将命令的每个部分指定为 cmd 数组中的单独字符串:

function runPg() {
    const cmd = [
        "docker", 
        "run",
        "-d",
        "-v",
        `${VOLUME}:/var/lib/postgresql/data`,
        "--name",
        "pg",
        "-e",
        `POSTGRES_PASSWORD=${PASSWORD}`,
        "--rm",
        "-p",
        "5432:5432",
        "postgres"
    ];

    return runCmd(cmd);
}

这会将 run 作为第一个参数发送给 docker,而不是将 run -d … 作为第一个参数发送。

您也可以将命令构建为单个字符串,然后使用 split(" "),只要参数不包含空格即可。

在此顶部继续我的试错之旅。

在读一本关于 unix shell 编程的书时,它指出了一种方法来帮助 shell 区分标识符 中的 space和 space 作为分隔符 。当一个人试图 cat 一个名为 a b 的文件(中间有一个 space)时,命令应该是 cat a\ b 或者,使用引号 cat 'a b'

这让我明白了为什么我的命令在 Deno 中不起作用。看,当我将 delimiter-space 与标识符混淆时,cmd 字符串列表中的每个项目都是一个 identifier ,命令被错误地解释。

例如。

如果我想要 cat 一个名为 a b 的文件。在 Deno.run 中,我需要使用 { cmd: ["cat", "a b"] }.

如果我想要 cat 两个名为 ab 的文件。在 Deno.run 中,我需要使用 { cmd: ["cat", "a", "b"] }.

请记住,命令助词中的 space 算作该词的一部分。