【问题标题】:Formatting escaped literal quotes in Ansible for PowerShell invoke-sqlcmd command在 Ansible for PowerShell invoke-sqlcmd 命令中格式化转义的文字引号
【发布时间】:2020-04-27 22:09:30
【问题描述】:

在这里与社区联系。我正在处理 Ansible 脚本,并且需要将一些配置数据从设置文件插入 Microsoft SQL Server DB。设置在 XML 中指定。

设置 JSON 文件示例 (ConfigData.json)

{
   "ConfigDataXML": "<Settings xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><PathSettings=\"Windows\"></PathSettings></Settings>",
   "ConfigDescription": "OS File Config",
   "ConfigPermissions": "Readonly"
}

Ansible 数据库插入

- name 'read config file into var'
  include_vars:
     file: ConfigData.json
     name: configData

- name 'add config to DB'
  win_shell: "invoke-sqlcmd -username \"{{db_user}}\" -password \"{{db_pass}}\" -Query \"INSERT INTO ConfigData (Data, ConfigId) VALUES ({{ configData.ConfigDataXML}},'{{ item.configId }}')\""

执行上述操作时,INSERT 失败,因为 PowerShell invoke-sqlcmd 返回错误:

A positional parameter cannot be found that accepts argument 'http'

这是由于已在 XML 数据中转义的文字双引号引起的。 PowerShell 要求任何双引号必须先用反引号“`”转义,因此为了使上面的 Config XML 传递 PowerShell 语法规则,它需要在出现转义双引号的地方使用反引号:

"ConfigDataXML": "<Settings xmlns:xsd=`\"http://www.w3.org/2001/XMLSchema`\" xmlns:xsi=`\"http://www.w3.org/2001/XMLSchema-instance`\"><PathSettings=`\"Windows`\"></PathSettings></Settings>"

问题:JSON 文件是静态的,因为它是从另一个系统读取的,因此无法更改。唯一的选择是让 Ansible 脚本解析 XML 字符串并添加反引号。我想知道如何在 Ansible 中实现这一点。

【问题讨论】:

  • 你可以试试regex_replace filter
  • 知道搜索词是否需要全局模式标志来匹配所有?例如/\\\"/g
  • SQL-Server 的哪个版本?从 v2016 开始,支持 JSON。您可以按原样传递字符串,使用 JSON 处理内容,将其转换为 XML,然后使用 XML 的方法来完成其余的工作......
  • @zeitounator 更改 {{ configData.ConfigDataXML }} 以包含带有反引号 {{ configData.ConfigDataXML | regex_replace('\"','`\"') }} 的 regex_replace 与我的原始 SQL 查询一起使用
  • @mactwixs 如果这解决了您原来的问题,您应该将其添加为您自己问题的答案并将其标记为已接受(除非已经有更好的问题)。

标签: sql-server xml powershell ansible


【解决方案1】:

只要 XML 不包含任何单引号,这应该可以工作:

- name 'add config to DB'
  win_shell: |
    Invoke-Sqlcmd -username "{{db_user}}" -password "{{db_pass}}" -Query "
      INSERT INTO ConfigData (Data, ConfigId) 
      VALUES ('{{ configData.ConfigDataXML }}', '{{ item.configId }}')
    "

根据documentation| 引入了一个多行 shell 命令,该命令消除了对括起来的引号的需要,因此不需要任何额外的引号转义。


如果您希望 XML 中有单引号,或者只是为了安全起见,您可以使用像这样的 @"here-string"@ 语法(PowerShell 需要在打开 @" 之后和关闭之前立即换行"@,但是在两者之间允许使用引号和换行符的任意组合而无需进一步转义,这对于可以包含任何内容的{{placeholders}} 非常方便):

- name 'add config to DB'
  win_shell: |
    $xmlstring = @"
    {{ configData.ConfigDataXML }}
    "@
    $xmlstring = $xmlstring -replace "'","''"

    Invoke-Sqlcmd -username "{{db_user}}" -password "{{db_pass}}" -Query "
      INSERT INTO ConfigData (Data, ConfigId) 
      VALUES ('$xmlstring', '{{ item.configId }}')
    "

注意/警告这些都不能保护您免受恶意制作的 ConfigDataXML 值的侵害。对于您的使用上下文,这可能不太可能发生,但“从字符串连接 SQL”仍然不干净。

【讨论】:

  • 感谢您的详细想法。 XML 中没有单引号。我尝试了您解决方案的第一部分,它似乎给出了一个稍微不同的错误:A positional parameter cannot be found that accepts argument 'http://www.w3.org/2001/XMLSchema xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance&gt;&lt;PathSettings=Windows&gt;&lt;/PathSettings&gt;&lt;/Settings&gt;),'5481') - 所以现在 XML 出现时没有引号?
  • 我在{{ configData.ConfigDataXML }} 周围设置了单引号。你有吗?
  • 是的,请确认这是我使用的 VALUES ('{{ configData.ConfigDataXML }}', '{{ item.configId }}') + 未使用转义的 \" 留下的 .json 文件
  • \" 是 JSON 要求,当读取 JSON 文件时它们会消失,所以这不是问题。 (虽然您问题中的 XML 在语法上无效,但我想这只是因为您在发布前缩短它时剪掉了太多。)
  • @mactwixs 调试想法。将Invoke-Sqlcmd ... 更改为Set-Content -Path "$env:TEMP\sqlquery.txt" -Value " the SQL query exactly as above"。查看生成的文件。对您来说,它看起来像有效的 SQL 吗?调整 Set-Content 调用,直到它看起来正确(并且在粘贴到 SSMS 时有效)。之后,使用更新后的查询返回Invoke-Sqlcmd
猜你喜欢
  • 1970-01-01
  • 2016-05-11
  • 2014-01-24
  • 1970-01-01
  • 2016-01-15
  • 1970-01-01
  • 2012-09-08
  • 2021-06-05
  • 1970-01-01
相关资源
最近更新 更多