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
相关产品推荐
相关产品推荐

