lua-shell-games

执行 shell 命令并捕获其输出和退出代码。包括用于执行 shell 转义/引用的辅助函数。

$ opm get GUI/lua-shell-games

shell-games

[!Circle CI](https://circleci.com/gh/GUI/lua-shell-games)

一个 Lua 库,用于更轻松、更安全地执行 shell 命令。

  • 轻松执行 shell 命令,同时捕获命令的输出和退出代码。包括跨 Lua、LuaJIT 和 OpenResty 版本的兼容性,其中io.popen可能不返回退出代码(Lua 5.2 之前的行为)。

  • 用于引用和转义 shell 参数的实用程序,以实现更安全、更不易出错的执行。

在执行 shell 命令时,shell-games 会包装os.executeio.popen(取决于是否正在捕获输出)。

OpenResty 注意:如果将 shell-games 与 OpenResty 一起使用,请注意,使用此库执行 shell 命令是一个阻塞操作。这在不同的 nginx 阶段可能是可以的(在init中阻塞是可以的),也可能不行,具体取决于您的应用程序的需求。如果阻塞是一个问题,您可能需要考虑其他替代方案,例如lua-resty-shelllua-resty-exec

安装

通过LuaRocks

    luarocks install shell-games

或通过OPM

    opm get GUI/lua-shell-games

用法

    local shell = require "shell-games"
    
    -- Execute a command, with error handling.
    local result, err = shell.run({ "touch", "/tmp/hello.txt" })
    if err then
      print(err)
      exit(1)
    end
    
    -- Executue a command, capturing both its stdout and stderr output.
    local result, err = shell.capture_combined({ "ls", "-l", "/tmp" })
    print("Exit code: " .. result["status"])
    print("Command output: " .. result["output"])
    
    -- Quoting
    shell.quote("ls") -- "ls"
    shell.quote("It's happening.") -- [['It'"'"'s happening.']]
    shell.quote("$PATH") -- "'$PATH'"
    
    -- Quote and join
    shell.join({ "ls", "-l", "/tmp/foo bar" }) -- "ls -l '/tmp/foo bar'"

兼容性

已测试

  • Lua 5.1

  • Lua 5.2

  • Lua 5.3

  • LuaJIT 2.0

  • 使用LUAJIT_ENABLE_LUA52COMPAT编译的 LuaJIT 2.0

  • LuaJIT 2.1-beta

  • 使用LUAJIT_ENABLE_LUA52COMPAT编译的 LuaJIT 2.1-beta

  • OpenResty

API

run

语法:result, err = shell.run(command[, options])

执行 shell 命令。

comamnd参数必须作为单个参数的表传递,这些参数将被转义。虽然这是推荐的执行命令方式,但如果您需要从字符串执行任意 shell 命令,请参阅`run_raw`

options表接受以下字段

  • capture(布尔值):是否捕获命令的输出。(默认值:false

    默认情况下,不会捕获命令输出,因此命令生成的任何 stdout/stderr 将显示在父进程中。

    如果为true,则命令的 stdout 将被捕获并返回到结果中,但 stderr 仍将在父进程中打印。要捕获命令的 stderr,必须将其重定向。有关更轻松地运行命令和捕获输出的便捷包装器,请参阅`capture_combined``capture`

  • chdir(字符串):在执行命令之前,将当前工作目录更改为此路径。(默认值:nil

  • env(表):在执行命令之前设置环境变量。接受环境变量名称和值的表。(默认值:{}

  • stderr(字符串):将命令的 stderr 输出重定向到不同的路径。(默认值:nil

  • stdout(字符串):将命令的 stdout 输出重定向到不同的路径。(默认值:nil

  • umask(字符串):在执行命令之前更改进程的 umask。(默认值:nil

如果执行命令失败(返回非 0 的退出代码),则err将是描述错误的字符串。在失败的情况下,仍将返回result表(其中包含命令的退出代码和输出)。

返回的result表具有以下字段

  • command(字符串):显示已执行的完整命令的字符串,已考虑转义和选项。

  • status(整数):命令的退出代码。

  • output(字符串):仅当启用了capture选项时,此字段才存在。如果启用了捕获,则这反映了命令的输出。默认情况下,这仅包含命令的 stdout,而不包含 stderr。有关更轻松地运行命令和捕获输出的便捷包装器,请参阅`capture_combined``capture`

    -- Basic example
    local result, err = shell.run({ "ls", "-l", "/tmp" })
    
    -- Example with options
    local result, err = shell.run({ "ls", "-l", "/tmp" }, {
      capture = true,
      chdir = "/tmp",
      env = {
        LD_LIBRARY_PATH = "/usr/local/lib",
      },
      stderr = "/tmp/stderr.log",
      stdout = "/tmp/stdout.log",
      umask = "0022",
    })

capture

语法:result, err = shell.capture(command[, options])

执行 shell 命令,并将 stdout 捕获为字符串。

这是在使用`run`捕获 stdout 时执行命令的便捷包装器。它等效于使用{ capture = true }选项调用run

commandoptions参数的格式与`run`中的格式相同。

    local result, err = shell.capture({ "ls", "-l", "/tmp" })

capture_combined

语法:result, err = shell.capture_combined(command[, options])

执行 shell 命令,并将 stdout 和 stderr 都捕获为单个字符串。

这是在使用`run`捕获 stdout 和 stderr(通过将 stderr 重定向到 stdout)时执行命令的便捷包装器。它等效于使用{ capture = true, stderr = "&1" }选项调用run

commandoptions参数的格式与`run`中的格式相同。

    local result, err = shell.capture_combined({ "ls", "-l", "/tmp/non-existent" })

run_raw

语法:result, err = shell.run_raw(command[, options])

执行作为原始字符串给出的 shell 命令。

通常,建议使用`run``capture``capture_combined`,它们都接受作为单个参数的表的命令(因为它们为您处理 shell 转义和引用)。但是,在您需要执行未转义的命令的情况下,可以使用此run_raw直接逐字运行命令字符串。

comamnd参数必须作为字符串传递。确保在此字符串中手动处理任何转义。

options参数的格式与`run`中的格式相同。

    local result, err = shell.run_raw("echo $PATH", {
      capture = true,
    })
    print(result["output"])

quote

语法:quoted_string = shell.quote(str)

返回字符串的 shell 转义版本。转义后的字符串可以安全地用作 shell 命令中的一个标记。

    shell.quote("ls") -- "ls"
    shell.quote("It's happening.") -- [['It'"'"'s happening.']]
    shell.quote("$PATH") -- "'$PATH'"

join

语法:quoted_string = shell.join(table)

接受单个命令参数的表,这些参数将被转义(使用`quote`)并用空格连接在一起。适用于将命令参数列表转换为单个命令字符串。

    shell.join({ "ls", "-l", "/tmp/foo bar" }) -- "ls -l '/tmp/foo bar'"

开发

检出仓库后,可以使用 Docker 运行测试套件

    docker-compose run --rm app make test

发布流程

要将新版本发布到 LuaRocks 和 OPM

  • 确保CHANGELOG.md是最新的。

  • 更新lib/shell-games.lua中的_VERSION

  • 将 rockspec 文件移动到新的版本号(git mv shell-games-X.X.X-1.rockspec shell-games-X.X.X-1.rockspec),并在 rockspec 文件中更新versiontag变量。

  • 提交并标记发布(git tag -a vX.X.X -m "Tagging vX.X.X" && git push origin vX.X.X)。

  • 运行make release VERSION=X.X.X

作者

Nick Muerdter

许可证

mit

版本

  • 执行 shell 命令并捕获其输出和退出代码。包括用于执行 shell 转义/引用的辅助函数。 2019-09-30 00:42:38
  • 执行 shell 命令并捕获其输出和退出代码。包括用于执行 shell 转义/引用的辅助函数。 2019-09-29 16:31:02
  • 执行 shell 命令并捕获其输出和退出代码。包括用于执行 shell 转义/引用的辅助函数。 2019-05-01 03:24:52
  • 执行 shell 命令并捕获其输出和退出代码。包括用于执行 shell 转义/引用的辅助函数。 2018-12-11 03:49:47