问题
I'm trying to detect if a particular filesystem is mounted read-only or read-write on Linux (Ubuntu 16.04). Using the stat module won't work because it always returns the posix permissions regardless of the actual ability to write into the directory. I'm able to accomplish this with the rather intrusive and cumbersome code below, which attempts to create a dot file. I'd appreciate a cleaner and more elegant alternative, that can also detect if the directory is not a mount point (which would be an error).
- name: Determine whether we have write access to the shared dir
command: touch /mnt/shared-data/.WriteTest
register: shared_dir_write_test
failed_when: "shared_dir_write_test.rc != 0 and 'read-only' not in (shared_dir_write_test.stderr | lower)"
changed_when: shared_dir_write_test.rc == 0
Ansible advised me to use instead the file module with state=touch, however the code below fails since there doesn't seem to be a way to examine the interim result of file.
- name: Determine whether we have write access to the shared dir
file: path=/mnt/shared-data/.WriteTest state=touch
register: shared_dir_write_test
failed_when: "shared_dir_write_test.failed and 'read-only' not in (shared_dir_write_test.msg | lower)"
The conditional check 'shared_dir_write_test.failed and 'read-only' not in (shared_dir_write_test.stderr | lower)' failed. The error was: error while evaluating conditional (shared_dir_write_test.failed and 'read-only' not in (shared_dir_write_test.stderr | lower)): 'dict object' has no attribute 'failed'
回答1:
You could gather Ansible facts, there are mount options for each mount:
ansible localhost -m setup -a "filter=ansible_mounts"
sample output:
[root@ansible ansible]# ansible localhost -m setup -a "filter=ansible_mounts"
localhost | SUCCESS => {
"ansible_facts": {
"ansible_mounts": [
{
"block_available": 3007928,
"block_size": 4096,
"block_total": 3929600,
"block_used": 921672,
"device": "/dev/mapper/fedora-root",
"fstype": "xfs",
"inode_available": 7787042,
"inode_total": 7864320,
"inode_used": 77278,
"mount": "/",
"options": "rw,relatime,attr2,inode64,noquota",
"size_available": 12320473088,
"size_total": 16095641600,
"uuid": "5faf23bb-281b-41d9-bd20-f8da6463eba0"
},
{
"block_available": 185772,
"block_size": 4096,
"block_total": 249830,
"block_used": 64058,
"device": "/dev/sda1",
"fstype": "ext4",
"inode_available": 65179,
"inode_total": 65536,
"inode_used": 357,
"mount": "/boot",
"options": "rw,relatime,data=ordered",
"size_available": 760922112,
"size_total": 1023303680,
"uuid": "866845e7-6c62-41c9-bbd2-87b463326601"
}
]
},
"changed": false
}
[root@ansible ansible]# ansible localhost -m setup -a "filter=ansible_mounts"
回答2:
The information can be obtained from Ansible facts. Ansible code that accomplishes this:
- name: Determine shared-dir mount point
command: "/usr/bin/env stat -c '%m' {{ shared_dir_real_path }}"
register: shared_dir_mount_point
changed_when: False
- name: Determine the mount point's filesystem type and mount options
set_fact:
"shared_dir_mount_{{ item }}": "{{ ansible_mounts | selectattr('mount', 'equalto', shared_dir_mount_point.stdout) | map(attribute = item) | join(',') }}"
with_items:
- fstype
- options
- name: Determine the access to the shared-data directory
set_fact:
shared_dir_access_flags: "{{ ['ro', 'rw'] | intersect( shared_dir_mount_options.split(',') )}}"
- name: Verify Access mode sanity
assert:
that: shared_dir_access_flags | length == 1
Then to determine whether the mount is R/W or R/O I use:
when: "'rw' in shared_dir_access_flags"
or
when: "'ro' in shared_dir_access_flags"
Another, more terse but perhaps less clean approach that I used previously, was to obtain the information from /proc/self/mountinfo. A little more platform-specific than I hoped, but it only depends on documented intrefaces.
- name: Get Shared dir mount options
shell: "grep -F `stat -c '%m' {{ shared_dir_path }}` /proc/self/mountinfo | cut -d' ' -f 6"
register: shared_dir_mount_options
changed_when: False
Then the expressions to determine whether the mount is R/W or R/O I would become a bit more cumbersome:
when: "'rw' in shared_dir_mount_options.stdout.split(',')"
or
when: "'ro' in shared_dir_mount_options.stdout.split(',')"
来源:https://stackoverflow.com/questions/49609588/ansible-detect-if-a-linux-filesystem-is-mounted-read-only