命令字面量¶
命令字面量是用反引号 ` 或 %x 百分号字面量分隔的字符串。它将在运行时被子 shell 中执行字符串的捕获输出替换。
与百分号字符串字面量类似,%x 的有效分隔符是圆括号 ()、方括号 []、大括号 {}、尖括号 <> 和管道 ||。除了管道之外,所有分隔符都可以嵌套;这意味着字符串内部的起始分隔符将转义下一个结束分隔符。
特殊变量 $? 持有命令的退出状态,作为 Process::Status。它仅在与命令字面量相同的范围内可用。
`echo foo` # => "foo"
$?.success? # => true
在内部,编译器将命令字面量重写为对顶层方法 `() 的调用,该方法带有包含命令作为参数的字符串字面量:`echo #{argument}` 和 %x(echo #{argument}) 将被重写为 `("echo #{argument}")。
安全问题¶
虽然命令字面量可能对简单的脚本式工具有用,但在插值用户输入时要格外小心,因为它很容易导致命令注入。
user_input = "hello; rm -rf *"
`echo #{user_input}`
此命令将写入 hello,然后删除当前工作目录中的所有文件和文件夹。
为了避免这种情况,命令字面量通常不应与插值的用户信息一起使用。标准库中的 Process 提供了一种安全的方式将用户信息作为命令参数提供
user_input = "hello; rm -rf *"
process = Process.new("echo", [user_input], output: Process::Redirect::Pipe)
process.output.gets_to_end # => "hello; rm -rf *"
process.wait.success? # => true