You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible因变量格式问题无法获取已有文件的stat信息

问题

尝试获取Ansible变量source_files中第一个文件的所有者,该变量由OLAM API生成,无法修改其格式,示例中已硬编码。变量中的两个文件实际存在:

[wluser@mylocalhost ~]$ ls -ltr '/tmp/my  private.txt' /tmp/files.sh  
-rw-r--r-- 1 wluser mygrp 0 Nov 12 21:52 /tmp/files.sh    
-rw-r--r-- 1 wluser mygrp 0 Nov 12 21:52 /tmp/my  private.txt

Playbook

[wluser@mylocalhost ~]$ cat formatstring.yml
---
- name: "Play 1-Find the details here"

  hosts: localhost
  any_errors_fatal: True
  gather_facts: no

  tasks:

   - name: Set source_files variable
     set_fact:
       source_files: "'/tmp/my  private.txt','/tmp/files.sh'"
 
   - name: Print source_files
     debug:
       msg: "source_files: {{ source_files }}"
     
   - name: Loop Print source_files
     debug:
       msg: "{{ item }}"
     loop: "{{ source_files.split(',') }}"

   - name: Single Print source_files
     debug:
       msg: "{{ source_files.split(',')[0] }}"
   
   - name: Get directory owner
     ansible.builtin.stat:
       path: "{{ tomcat_home_item }}"
     register: dir_stat
     vars:
       tomcat_home_item: "{{ source_files.split(',')[0] | trim }}"

   - name: Store directory owner's UID in a variable
     set_fact:
       owner_uid: "{{ dir_stat.stat.pw_name | default('baduser') }}"

   - debug:
       msg: "Detected user is: {{ owner_uid }}"

   - name: Get directory owner
     ansible.builtin.stat:
       path: "{{ tomcat_home_item | regex_replace('^\\s*'|'\\s*$', '') }}"
     register: dir_stat
     vars:
       tomcat_home_item: "{{ source_files.split(',')[0] | trim }}"

   - name: Store directory owner's UID in a variable
     set_fact:
       owner_uid: "{{ dir_stat.stat.pw_name | default('baduser') }}"
 
   - debug:
       msg: "Detected user is: {{ owner_uid }}"

输出

[wluser@mylocalhost ~]$ ansible-playbook formatstring.yml -vvv
ansible-playbook 2.8.4
  config file = /etc/ansible/ansible.cfg
PLAYBOOK: formatstring.yml ****************************************************************************************************
1 plays in formatstring.yml

PLAY [Play 1-Find the details here] *******************************************************************************************
META: ran handlers

TASK [Set source_files variable] **********************************************************************************************
task path: /home/wluser/formatstring.yml:10
Sunday 12 November 2023  22:02:56 -0600 (0:00:00.044)       0:00:00.044 *******
ok: [localhost] => {
    "ansible_facts": {
        "source_files": "'/tmp/my  private.txt','/tmp/files.sh'"
    },
    "changed": false
}

TASK [Print source_files] *****************************************************************************************************
task path: /home/wluser/formatstring.yml:15
Sunday 12 November 2023  22:02:56 -0600 (0:00:00.018)       0:00:00.062 *******
ok: [localhost] => {
    "msg": "source_files: '/tmp/my  private.txt','/tmp/files.sh'"
}

TASK [Loop Print source_files] ************************************************************************************************
task path: /home/wluser/formatstring.yml:19
Sunday 12 November 2023  22:02:56 -0600 (0:00:00.017)       0:00:00.080 *******
ok: [localhost] => (item='/tmp/my  private.txt') => {
    "msg": "'/tmp/my  private.txt'"
}
ok: [localhost] => (item='/tmp/files.sh') => {
    "msg": "'/tmp/files.sh'"
}

TASK [Single Print source_files] **********************************************************************************************
task path: /home/wluser/formatstring.yml:24
Sunday 12 November 2023  22:02:56 -0600 (0:00:00.033)       0:00:00.114 *******
ok: [localhost] => {
    "msg": "'/tmp/my  private.txt'"
}

TASK [Get directory owner] ****************************************************************************************************
task path: /home/wluser/formatstring.yml:29
Sunday 12 November 2023  22:02:56 -0600 (0:00:00.023)       0:00:00.137 *******
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: wluser
ok: [localhost] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "checksum_algorithm": "sha1",
            "follow": false,
            "get_attributes": true,
            "get_checksum": true,
            "get_md5": null,
            "get_mime": true,
            "path": "'/tmp/my  private.txt'"
        }
    },
    "stat": {
        "exists": false
    }
}

TASK [Store directory owner's UID in a variable] ******************************************************************************
task path: /home/wluser/formatstring.yml:36
Sunday 12 November 2023  22:02:57 -0600 (0:00:00.352)       0:00:00.489 *******
ok: [localhost] => {
    "ansible_facts": {
        "owner_uid": "baduser"
    },
    "changed": false
}

TASK [debug] ******************************************************************************************************************
task path: /home/wluser/formatstring.yml:40
Sunday 12 November 2023  22:02:57 -0600 (0:00:00.020)       0:00:00.510 *******
ok: [localhost] => {
    "msg": "Detected user is: baduser"
}

TASK [Get directory owner] ****************************************************************************************************
task path: /home/wluser/formatstring.yml:43
Sunday 12 November 2023  22:02:57 -0600 (0:00:00.019)       0:00:00.529 *******
fatal: [localhost]: FAILED! => {
    "msg": "template error while templating string: expected token 'name', got 'string'. String: {{ tomcat_home_item | regex_replace('^\\\\s*'|'\\\\s*$', '') }}"
}

NO MORE HOSTS LEFT ************************************************************************************************************
PLAY RECAP ********************************************************************************************************************
localhost                  : ok=7    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

问题核心:source_files变量的每个文件路径被单引号包裹,导致stat模块找不到文件;同时尝试用regex_replace时语法错误(用了|分隔正则,应该用,)。

解决方案

1. 修复字符串处理逻辑,移除路径两端的单引号

分割后的路径包含额外单引号(如'/tmp/my private.txt'),需移除这些单引号才能正确指向文件,有两种简单方法:

方法一:使用replace快速移除单引号

修改stat任务中的路径变量,直接替换所有单引号为空:

- name: Get directory owner
  ansible.builtin.stat:
    path: "{{ tomcat_home_item }}"
  register: dir_stat
  vars:
    tomcat_home_item: "{{ source_files.split(',')[0] | trim | replace(\"'\", '') }}"

方法二:使用regex_replace匹配并移除首尾的单引号和空白

如果需要同时处理首尾的空白字符,用正则更灵活,注意正则参数用逗号分隔(之前的错误是用了竖线):

- name: Get directory owner
  ansible.builtin.stat:
    path: "{{ tomcat_home_item | regex_replace('^\\s*\\'|\\'\\s*$', '') }}"
  register: dir_stat
  vars:
    tomcat_home_item: "{{ source_files.split(',')[0] }}"

2. 优化完整任务示例

修改后的完整任务段可正确获取文件所有者:

- name: Set source_files variable
  set_fact:
    source_files: "'/tmp/my  private.txt','/tmp/files.sh'"

- name: Get first file path with clean format
  set_fact:
    first_file: "{{ source_files.split(',')[0] | trim | replace(\"'\", '') }}"

- name: Get file stat
  ansible.builtin.stat:
    path: "{{ first_file }}"
  register: file_stat

- name: Store owner name
  set_fact:
    owner_uid: "{{ file_stat.stat.pw_name | default('baduser') }}"

- debug:
    msg: "Detected user is: {{ owner_uid }}"

3. 批量处理所有文件(可选)

如果需要处理变量中的所有文件,可循环处理并清理每个路径格式:

- name: Process all source files
  ansible.builtin.stat:
    path: "{{ item | trim | replace(\"'\", '') }}"
  register: file_stats
  loop: "{{ source_files.split(',') }}"

- name: Print all owners
  debug:
    msg: "File {{ item.item | trim | replace(\"'\", '') }} is owned by {{ item.stat.pw_name | default('baduser') }}"
  loop: "{{ file_stats.results }}"

内容的提问来源于stack exchange,提问作者Ashar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:30:55