代码之家  ›  专栏  ›  技术社区  ›  LeXaNZ

Ansible-获取UID大于14000的用户列表-字符串到int转换

  •  0
  • LeXaNZ  · 技术社区  · 10 月前

    在我的剧本中,我想得到一个UI超过14000的所有本地用户的列表

    我在/etc/passwd或ansible.buillin.getent上使用了ansible.buillin.slurp,但真正的问题是我得到的UID值是字符串,而不是int,所以我无法正确过滤,我得到的所有结果都是空的,或者因为不是整数而抱怨。

    - name: Get all users from /etc/passwd
      ansible.builtin.getent:
        database: passwd
      register: users_info
    
    - name: Filter users with UID greater than 14000
      set_fact:
        filtered_users: >-
          {{
            users_info.ansible_facts.getent_passwd |
            dict2items |
            selectattr('value.1', 'int') |
            selectattr('value.1', >, 14000) |
            map(attribute='key') |
            list
          }}
    

    我想 selectattr('value.1', 'int') 将转换为int,但结果始终为空。(字典中确实有一些超过14000的UID)

    这里是getent提供的用户字典,所有UID都被引用,因此它们是字符串

        root:
        - x
        - '0'
        - '0'
        - root
        - /root
        - /bin/bash
        shutdown:
        - x
        - '6'
        - '0'
        - shutdown
        - /sbin
        - /sbin/shutdown
        sshd:
        - x
        - '74'
        - '74'
        - Privilege-separated SSH
        - /usr/share/empty.sshd
        - /sbin/nologin
    

    除了运行一些我会避免的shell cmd之外,我已经没有办法尝试了。

    干杯,

    2 回复  |  直到 10 月前
        1
  •  2
  •   larsks    10 月前

    我可以看到你的过滤器链有几个问题:

        filtered_users: >-
          {{
            users_info.ansible_facts.getent_passwd |
            dict2items |
            selectattr('value.1', 'int') |
            selectattr('value.1', >, 14000) |
            map(attribute='key') |
            list
          }}
    

    首先,没有命名的测试 int ,尽管有一个名为的筛选器 integer 遗憾的是,这是一个 测试 ,不是转换过滤器,因此在所有情况下 value.1 这是一个字符串 selectattr() 过滤器将拒绝您的所有条目,导致列表为空。这一点之后的一切都无关紧要,因为没有什么可以过滤的了。

    例如:

    - hosts: localhost
      gather_facts: false
      vars:
        example:
          - val: '1'
          - val: '2'
          - val: '3'
      tasks:
        - debug:
            msg: "{{ example | selectattr('val', 'integer') }}"
    

    结果如下:

    ok: [localhost] => {
        "msg": []
    }
    

    我想你会用 json_query filter 更简单。根据您的要求,我们可以这样做:

      - name: Filter users with UID > 1000
        set_fact:
          filtered_users: >-
              {{
                users_info.ansible_facts.getent_passwd |
                dict2items |
                json_query('[?to_number(value[1]) > `1000`].key')
              }}
    

    在这里,我们使用 to_number function 将字符串值转换为整数以进行比较。

    在我的系统中,这会产生:

    ok: [localhost] => {
        "filtered_users": [
            "nobody"
        ]
    }
    
        2
  •  0
  •   LeXaNZ    10 月前

    Kia或百灵鸟,

    非常感谢您的回复和解释。 现在完全明白了,为什么我得到了空的结果。

    这里我最后查询过滤14000-15000 UID,工作起来很有魅力

    - name: Filter users 14k-15k range
      set_fact:
        filtered_users: >-
          {{
            users_info.ansible_facts.getent_passwd |
            dict2items |
            json_query('[?to_number(value[1]) > `14000` && to_number(value[1]) <= `15000`].key')
          }}