面试题答案
一键面试1. Open3.popen3
- 原理:
Open3.popen3
方法会创建一个子进程来执行指定的命令,并同时打开标准输入、标准输出和标准错误流。它允许你与子进程进行通信,并且可以安全地获取其输出。通过这种方式,能有效防止命令注入等安全问题,因为它对输入进行了适当的处理。 - 适用场景:适用于需要同时获取标准输出和标准错误输出,并且可能需要向子进程发送输入的场景。例如,当你执行一个需要输入参数并获取详细执行结果(包括正常输出和错误信息)的外部命令时。
示例代码:
require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3('ls -l')
stdout_result = stdout.read
stderr_result = stderr.read
wait_thr.value
puts "标准输出: #{stdout_result}"
puts "标准错误: #{stderr_result}"
2. Kernel#system
结合管道
- 原理:
system
方法用于执行外部命令,并返回命令执行是否成功的布尔值。通过结合管道(|
)和$?
来获取命令输出。它通过安全的方式执行外部命令,避免了直接在命令字符串中拼接用户输入导致的安全风险。因为它不允许在命令字符串中进行复杂的插值操作。 - 适用场景:适用于只关心命令是否成功执行,并且只需要获取标准输出的简单场景。例如,简单地检查某个目录下文件列表是否符合预期格式,不需要处理复杂的输入输出交互。
示例代码:
output = `ls -l 2>&1`
if $?.success?
puts "命令执行成功,输出: #{output}"
else
puts "命令执行失败,错误输出: #{output}"
end
3. Process.spawn
结合 IO.popen
- 原理:
Process.spawn
启动一个新的子进程来执行命令,而IO.popen
则用于从子进程的标准输出读取数据。这种组合方式通过合理地管理进程和输入输出流,有效避免了安全漏洞。Process.spawn
以一种安全的方式创建子进程,IO.popen
则确保从子进程读取数据时的安全性。 - 适用场景:适用于对进程控制和输出获取有更细粒度需求的场景。例如,当你需要在启动子进程后,对其进行一些额外的进程级操作(如设置进程优先级等),同时获取其输出。
示例代码:
pid = Process.spawn('ls -l')
output = IO.popen(pid) { |io| io.read }
status = Process.waitpid2(pid)
if status[0].success?
puts "命令执行成功,输出: #{output}"
else
puts "命令执行失败"
end