【问题标题】:how to extend windows path variable using ansible如何使用ansible扩展windows路径变量
【发布时间】:2015-10-16 04:25:34
【问题描述】:

使用 win_environment,可以向 Windows 主机添加/删除环境变量。 但是要修改已经存在的变量,win_environment 似乎没有用,因为您无法读取旧值来修改和更新变量。对吧?

【问题讨论】:

  • 为什么你认为修改环境变量没有用?
  • 正如docs.ansible.com/ansible/win_environment_module.html 记录的那样,它可以只设置一个变量,因此您在更新时不能使用旧值。
  • 我猜它必须通过 win_regedit 而不是 win_environment 完成。
  • 你用 win_regedit 让它工作了吗?

标签: windows path ansible


【解决方案1】:

编辑: 从 Ansible 2.3 开始,win_path 模块为您完成所有繁重的工作。只需给它一个路径中应该存在的项目列表,它就会确保它们存在并且按照您指定的相对顺序。

(如果你还在使用老版本的 Ansible,下面的方法还是可以的)

要使其正常工作,您需要结合替换和搜索过滤器,仅当您想要的值不存在时才进行更改。例如(这是针对 Ansible 1.9):

  - raw: echo %PATH%
    register: path_out

  - win_environment: 
      name: path
      value: "{{ path_out.stdout | regex_replace('[\r\n]*', '') + ';C:\\\\newpath' }}"
      state: present
      level: machine
    when: not (path_out.stdout | search("(?i)c:\\\\newpath"))

这比它应该做的要困难得多——我有一半的心思为 2.0 破解一个 win_path 模块以使其更容易......

对于 2.0,raw 在 Powershell 下运行,因此您需要 Get-Item env:PATH。

【讨论】:

  • 这与Devis的问题相同,它将用户路径与机器路径结合起来,并将机器路径设置为该值。
【解决方案2】:

我刚刚花了几个小时与 Ansible、Jinja2 和 JSON 反斜杠地狱作斗争,最后找到了一个通用的解决方案 - 即,允许您将任何目录添加到系统路径,并且不会添加相同的路径两次.我调整了 Devis 的解决方案,但使 SETX 命令和 when: 子句都接受(相同){{item}},因此可以对其进行参数化。这是我想出的。

另存为extend-path.yml:

---
- name: Get current machine PATH.
  raw: $ENV:PATH
  register: path_out

- name: "Add {{ item }} to PATH."
  raw: SETX /M PATH "$ENV:PATH;{{ item }}"
  when: "not (path_out.stdout | urlencode | search( '{{ item | urlencode }}' ) )"
  changed_when: true

然后,例如,在您的playbook.yml:

---
tasks:
  - name: Add tools to PATH.
    include: extend-path.yml
    with_items:
      - C:\bin
      - C:\Program Files (x86)\CMake\bin
      - C:\Program Files\git\cmd

(如你所见,我实际上输掉了反斜杠之战,并决定使用urlencode 完全绕过它。)

【讨论】:

  • 这和上面的Devis有同样的问题,它将用户路径与机器路径结合起来,并将机器路径设置为该值。
【解决方案3】:

用 Ansible 2.0 试试这个

- name: Get actual PATH
  raw: $ENV:PATH
  register: path_out
  tags: path

- name: Add Notepad++ to PATH
  raw: SETX /M PATH "$ENV:PATH;C:\Program Files (x86)\Notepad++"
  when: path_out.stdout.find('Notepad') == -1
  tags: path

【讨论】:

  • 这会将用户路径与机器路径结合起来。当您调用 $ENV:PATH 时,您将获得机器路径和用户路径的组合。然后,当您调用 SETX /M PATH 时,您正在将机器路径设置为该组合。所以现在用户路径将被复制到机器路径。
【解决方案4】:

这是一个将 msbuild 设置为机器路径的示例。如果需要,您可以添加更多项目。在修改机器路径之前只检索机器路径很重要。如果你只是调用 $ENV:PATH,你会得到机器路径和用户路径的组合。如果您使用它来设置机器路径,那么您将所有用户路径值复制到机器路径,我假设这不是您想要的。

- name: Get System PATH
  raw: '[Environment]::GetEnvironmentVariables("Machine").Path'
  register: path_out

- name: Modify System PATH
  raw: SETX /M PATH "$([Environment]::GetEnvironmentVariables("Machine").Path | Out-String);{{ item }}"
  when: path_out.stdout.find(item) == -1
  with_items: 
    - 'C:\Program Files (x86)\MSBuild\14.0\Bin'

【讨论】:

    【解决方案5】:

    您可以使用 Powershell 将字符串添加到路径。下面的代码将给定路径添加到 PATH 变量,同时确保如果给定路径已存在于 PATH 中,则不会修改路径。

    $env = [Environment]::GetEnvironmentVariable('path','machine') -split ';'
    $msdeploypath = 'C:\Program Files\IIS\Microsoft Web Deploy'
    
    if ($env -notcontains $msdeploypath) {
        $env += $msdeploypath
        [Environment]::SetEnvironmentVariable('path', ($env -join ';'), 'machine')
        Write-Host "changed"
    }
    

    在 Ansible 2 中,您也可以使用原始模块,因为它使用 Powershell

    - name: Set Path
      raw: $env = [Environment]::GetEnvironmentVariable('path','machine') -split ';' ; $msdeploypath = 'C:\Program Files\IIS\Microsoft Web Deploy' ; if ($env -notcontains $msdeploypath) { $env += $msdeploypath ; [Environment]::SetEnvironmentVariable('path', ($env -join ';'), 'machine') ; Write-Host "changed" } 
      register: pathchange
      changed_when: pathchange.stdout.find('changed') != -1
    

    【讨论】:

      【解决方案6】:

      Casey 的解决方案非常接近。唯一的问题是 [Environment]::SetEnvironmentVariable 在 PATH 末尾添加了一个换行符。因此,当您添加到它时,它会将所有新值放在另一行上,从而使 PATH 不起作用。这就是我所做的,而且效果很好。

      只需要在换行符上添加一个拆分...然后系统 PATH 变量设置正确。

      这是 Casey 的解决方案和 Chris Hillery 的结合:

      在一个名为extend-path.yml的文件中:

       ---
       - name: Get current machine PATH.
         raw: "$([Environment]::GetEnvironmentVariables(\"Machine\").Path -split '\r\n')"
         register: path_out
      
      - name: Print Out PATH
        debug:
        msg: "PATH: {{ path_out }}"
      
      - name: "Add {{ item }} to PATH."
        raw: SETX /M PATH "$($([Environment]::GetEnvironmentVariables("Machine").Path -split '\r\n'));{{ item }}"
        when: path_out.stdout.find(item) == -1
        changed_when: true
      

      然后在你的剧本中调用它:

      - name: Update system PATH
        include: tasks/win_system_path.yml
        with_items:
          - C:\Program Files\Git\bin
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-20
        • 2020-04-08
        • 1970-01-01
        相关资源
        最近更新 更多