كيفية الحصول على الدليل الرئيسي للمستخدم عن بعد التعسفي في Ansible؟




ansible-facts (6)

المشكلة

إن أساليب lookup() أو ENV var للعثور على منزل مستخدم تعسفي للأسف لن تعمل بشكل موثوق مع Ansible لأنه يعمل كمستخدم محدد مع --user=REMOTE_USER ، واختيارياً مع sudo (إذا كان sudo: yes في playbook أو --sudo مرت). سيؤدي وضعان التشغيل (sudo أو بدون sudo) إلى تغيير بيئة shell التي يعمل Ansible من خلالها ، وحتى ذلك الحين ستقتصر على المستخدم المحدد كـ -u REMOTE_USER أو root .

يمكنك محاولة استخدام sudo: yes ، و sudo_user: myarbitraryuser معًا ... ولكن نظرًا لوجود خطأ في إصدارات معينة من Ansible قد ترى أنه لا يتصرف كما يجب. إذا كنت تستخدم Ansible> = 1.9 ، فيمكنك استخدام become: true ، و become_user: myarbitraryuser بدلاً من ذلك. ومع ذلك ، فإن هذا يعني أن قواعد اللعب والأدوار التي تكتبها لن تعمل على الإصدارات السابقة من Ansible.

إذا كنت تبحث عن طريقة محمولة للحصول على dir المنزلي الخاص بالمستخدم والذي سيعمل أيضًا مع LDAP أو بعض خدمات الدليل الأخرى ، فاستخدم getent .

مثال غير واضح

قم بإنشاء كتاب playbooks/ad-hoc/get-user-homedir.yml بسيط باسم: playbooks/ad-hoc/get-user-homedir.yml

- hosts: all
  tasks:
    - name:
      shell: >
        getent passwd {{ user }} | cut -d: -f6
      changed_when: false
      register: user_home

    - name: debug output
      debug: var=user_home.stdout

تشغيله مع:

ansible-playbook -i inventory/racktables.py playbooks/ad-hoc/get-user-homedir.yml -e "user=someuser"

يمكنني القيام بذلك باستخدام shell باستخدام مزيج من getent و awk مثل هذا:

getent passwd $user | awk -F: '{ print $6 }'

للإشارة ، في Puppet يمكنني استخدام حقيقة مخصصة ، مثل هذا:

require 'etc'

Etc.passwd { |user|

   Facter.add("home_#{user.name}") do
      setcode do
         user.dir
      end
   end

}

مما يجعل الدليل الرئيسي للمستخدم متاحًا home_<user name> .

كيف يمكنني الحصول على الدليل الرئيسي للمستخدم عن بعد التعسفي ؟


Ansible (من 1.4 وما بعده) يكشف بالفعل عن متغيرات البيئة للمستخدم تحت متغير ansible_env .

- hosts: all
  tasks:
    - name: debug through ansible.env
      debug: var=ansible_env.HOME

بدلاً من ذلك ، يمكنك الوصول إلى متغيرات البيئة باستخدام lookup على env :

- hosts: all
  tasks:
    - name: debug through lookup on env
      debug: var=lookup('env','HOME')

لسوء الحظ ، لا يمكنك استخدام هذا على ما يبدو إلا للحصول على متغيرات البيئة للمستخدم المتصل كما يظهر هذا playbook والمخرجات:

- hosts: all
  tasks:
    - name: debug specified user's home dir through ansible.env
      debug: var=ansible_env.HOME
      become: true
      become_user: "{{ user }}"

    - name: debug specified user's home dir through lookup on env
      debug: var=lookup('env','HOME')
      become: true
      become_user: "{{ user }}"

الإخراج :

[email protected]:~$ ansible-playbook -i "inventory/vagrant" env_vars.yml -e "user=testuser"

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.30]

TASK: [debug specified user's home dir through ansible.env] *******************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

TASK: [debug specified user's home dir through lookup on env] *****************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

PLAY RECAP ********************************************************************
192.168.0.30               : ok=3    changed=0    unreachable=0    failed=0

كما هو الحال مع أي شيء في Ansible ، إذا لم تتمكن من الحصول على وحدة لإعطائك ما تريد ، فأنت دائمًا ما تكون حرًا في الخروج (على الرغم من أنه يجب استخدام هذا بشكل بسيط لأنه قد يكون هشًا وسيكون أقل وصفية) باستخدام شيء مثل هذا :

- hosts: all
  tasks:
    - name: grep and register
      shell: >
              egrep "^{{ user }}:" /etc/passwd | awk -F: '{ print $6 }'
      changed_when: false
      register: user_home

    - name: debug output
      debug: var=user_home.stdout

قد تكون هناك طريقة أنظف للقيام بذلك ، وأنا مندهش قليلاً من أن استخدام become_user للتبديل إلى المستخدم المحدد لا يبدو أنه يؤثر على بحث env لكن يجب أن يعطيك هذا ما تريد.


أعرف أن هذا مؤشر ترابط قديم جدًا ، لكنني أعتقد أن هذه طريقة أبسط قليلاً للحصول على الدليل الرئيسي للمستخدمين

- name: Get users homedir
  local_action: command echo ~
  register: homedir

على أنظمة Linux (أو Unix) ، تشير علامات التلدة إلى دليل المستخدم الرئيسي.


قدم Ansible 1.8 وحدة getent . يسجل نتيجة getent كحقيقة مضيفة - في هذه الحالة ، يكون getent_passwd .

أمثلة:

اطبع المجلد الرئيسي user معين:

---

- getent:
    database: passwd
    key: "{{ user }}"
    split: ":"

- debug:
    msg: "{{ getent_passwd[user][4] }}"

قم user_homes جدول بحث ( user_homes ) ، والاستفادة من set_fact وفلتر combine() في Jinja2:

---

- assert:
    that:
      - user_name is defined

- when: user_homes is undefined or user_name not in user_homes
  block:
    - name: getent
      become: yes
      getent:
        database: passwd
        key: "{{ user_name }}"
        split: ":"

    - name: set fact
      set_fact:
        "user_homes": "{{ user_homes | d({}) | combine({user_name: getent_passwd[user_name][4]}) }}"

سيكون أفضل مع وحدة الحقيقة المخصصة رغم ذلك.


لقد جئت إلى هذا الموضوع لأنني كنت بحاجة إلى طباعة متغير PGDATA env من مستخدم postgres ، لم أجد كيفية القيام بذلك أكثر "أصليًا" في ansible ، لكنني انتهيت من عمل هذا:

 - name: Find postgresql data directory shell: 'echo $PGDATA' become: yes become_user: postgres become_flags: "-i " register: pgdata_dir 

ثم يمكنني الإشارة إلى ذلك في وظيفة أخرى باستخدام "{{pgdata_dir.stdout}}"


يمكنك استخدام expanduser .

على سبيل المثال ، أثناء تنفيذ الحلقات فوق قائمة المستخدمين:

- name: Deploys .bashrc
  template:
    src: bashrc.j2
    dest: "{{ '~' + item | expanduser }}/.bashrc"
    mode: 0640
    owner: "{{ item }}"
    group: "{{ item }}"
  with_items: user_list




ansible-facts