给 Shell 命令传递参数

如果你需要在命令行下插入一个值,通常需要使用引号将其括起来,尤其是当其包含空格时更是如此。 shellquote 函数可以携带任意数量的参数(包括数组), 它会使用引号将每个参数都括起来并返回一个可以传递到 Shell 命令行上的以空格间隔的字符串。

在下面的例子中,我们想要创建一个用于文件改名的 exec 资源, 然而源文件名和目标文件名都包含空格,因此在命令行上需要正确地使用引号将它们括起来。

操作步骤

  1. 在你的配置清单中添加如下的代码:

    $source = "Hello Jerry"
    $target = "Hello... Newman"
    $argstring = shellquote( $source, $target )
    $command = "/bin/mv ${argstring}"
    notify { $command: }
    
  2. 运行 Puppet:

    notice: /bin/mv "Hello Jerry" "Hello... Newman"
    

工作原理

  1. 首先我们定义了 $source 和 $target 两个变量, 它们的值是将要在命令行上使用的两个文件名:

    $source = "Hello Jerry"
    $target = "Hello... Newman"
    
  2. 然后我们调用 shellquote 串连两个变量为一个以空格间隔的使用引号将每个变量值括起来的字符串:

    $argstring = shellquote( $source, $target )
    
  3. 然后将这其组织到一起,形成最终的命令行:

    $command = "/bin/mv ${argstring}"
    

    结果为:

    /bin/mv "Hello Jerry" "Hello... Newman"
    
  4. 现在可以使用 exec 资源执行这个命令行了。若我们没有使用 shellquote 会发生什么?

    $source = "Hello Jerry"
    $target = "Hello... Newman"
    $command = "/bin/mv ${source}  ${target}"
    notify { $command: }
    

    结果为:

    notice: /bin/mv Hello Jerry Hello... Newman
    

    这将无法工作,因为 mv 命令期望以空格间隔的参数, 所以 mv 将参数解释为请求移动的三个文件:Hello、Jerry 和 Hello… 以及移动的目标目录 Newman,这可不是我们想要的结果。