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

适用于Ansible的Linux命令:获取用户及其所属组并生成指定输出

Solution 1: Modified Bash Command (Escaped for Ansible)

Here's the updated single-line command that appends group information, with all quotes properly escaped to work in Ansible's shell or command module:

cat /etc/passwd | xargs -n1 -I{} bash -c 'a=$(echo "{}" | cut -f1 -d:); echo -e "\n$a"; chage -l "$a"; echo -e "Linux shell\t: $(echo "{}" | cut -f7 -d:)"; echo -e "Groups\t: $(groups "$a" | cut -d: -f2 | sed '\''s/^ //; s/ /, /g'\'')"' >> users-list.log

Key Changes:

  • Added a line to fetch and format groups: groups "$a" gets all groups for the user, cut removes the username prefix, and sed cleans up spacing to separate groups with commas.
  • Escaped single quotes in the sed command using \'\' to avoid breaking the outer single-quoted bash -c string (critical for Ansible compatibility).
  • Switched from backticks to $() for command substitution to improve readability and avoid nested quote conflicts.
  • Added quotes around $a to handle edge cases with usernames containing spaces (though uncommon).

For a more maintainable, idempotent approach that leverages Ansible's built-in modules instead of raw bash, use this playbook. It gathers user, shadow, and group data natively and templates the output to your log file:

- name: Collect detailed user information
  hosts: your_target_hosts
  tasks:
    - name: Gather passwd, shadow, and group data
      getent:
        database: "{{ item }}"
      loop:
        - passwd
        - shadow
        - group

    - name: Generate formatted user info log
      copy:
        dest: /users-list.log
        content: |
          {% for username in getent_passwd %}
          {{ username[0] }}
          {% set shadow = getent_shadow[username[0]] %}
          Last password change : {% if shadow[2] == '0' %}never{% else %}{{ (shadow[2] | int * 86400) | strftime('%b %d, %Y') }}{% endif %}
          Password expires : {% set max_days = shadow[4] | int %}{% if max_days == 99999 %}never{% else %}{{ (shadow[2] | int + max_days) * 86400 | strftime('%b %d, %Y') }}{% endif %}
          Password inactive : {% set inactive_days = shadow[6] | int %}{% if inactive_days == -1 %}never{% else %}{{ (shadow[2] | int + shadow[4] | int + inactive_days) * 86400 | strftime('%b %d, %Y') }}{% endif %}
          Account expires : {% set expire_date = shadow[7] | int %}{% if expire_date == -1 %}never{% else %}{{ expire_date * 86400 | strftime('%b %d, %Y') }}{% endif %}
          Minimum number of days between password change : {{ shadow[3] }}
          Maximum number of days between password change : {{ shadow[4] }}
          Number of days of warning before password expires : {{ shadow[5] }}
          Linux shell : {{ username[6] }}
          Groups : {{ getent_group | selectattr('1', 'contains', username[0]) | map(attribute='0') | join(', ') }}
          {% endfor %}
        force: yes

Why This Is Better:

  • No dependency on external bash commands (uses Ansible's built-in getent module which works across most Unix-like systems).
  • Idempotent: Running the playbook multiple times won't append duplicate entries to the log (the copy module replaces the file each time).
  • Easier to modify or extend (e.g., add more user attributes) without dealing with complex bash string escaping.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:28:38