Подтвердить что ты не робот

Как получить произвольный удаленный домашний каталог пользователя в Ansible?

Я могу сделать это с помощью 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>.

Как получить домашний каталог произвольного удаленного пользователя?

4b9b3361

Ответ 1

Ansible (начиная с версии 1.4) уже отображает переменные среды для пользователя в переменной ansible_env.

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

В качестве альтернативы, вы можете получить доступ к переменным среды, используя поиск в env:

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

К сожалению, очевидно, что вы можете использовать это только для получения переменных окружения для подключенного пользователя, как показано в этом списке воспроизведения:

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

    - name: debug specified user 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 home dir through ansible.env] *******************
ok: [192.168.0.30] => {
    "var": {
        "/home/vagrant": "/home/vagrant"
    }
}

TASK: [debug specified user 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, если вы не можете получить модуль, который даст вам то, что вы хотите, вы всегда можете shell выложить (хотя это следует использовать экономно, так как оно может быть хрупким и будет менее наглядным), используя что-то вроде этого:

- 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, но это должно дать вам то, что вы хотите.

Ответ 2

В Ansible 1.8 появился модуль getent. Он регистрирует полученный результат как основной факт - в данном случае это getent_passwd.

Примеры:

Распечатайте домашнюю папку для данного user:

---

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

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

Накопить справочную таблицу (user_homes), используя set_fact и фильтр Jinja2 combine():

---

- 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]}) }}"

Было бы лучше с модулем пользовательских фактов, хотя.

Ответ 3

Проблема

Методы lookup() или ENV var для поиска произвольного домашнего сайта не будут надежно работать с Ansible, поскольку он работает как пользователь, указанный с помощью --user=REMOTE_USER, и необязательно с sudo (если sudo: yes в playbook или --sudo). Эти два режима запуска (sudo или no sudo) изменят среду оболочки, в которой работает Ansible, и даже тогда вы будете ограничены пользователем, указанным как -u REMOTE_USER или root.

Вы можете попробовать использовать sudo: yes и sudo_user: myarbitraryuser вместе... однако из-за ошибки в определенных версиях Ansible вы может видеть, что он не ведет себя так, как должен. Если вы находитесь на Ansible >= 1.9, вы можете использовать become: true и become_user: myarbitraryuser. Однако это означает, что загружаемые вами книги и роли не будут работать в предыдущих версиях Ansible.

Если вы ищете переносной способ получить домашний каталог пользователя, который также будет работать с LDAP или какой-либо другой службой каталогов, используйте getent.

Сильный гент Пример

Создайте простой плей-лист с именем: 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"

Ответ 4

Я думаю, что здесь дано несколько ответов, которые сработают, но я подумал, что покажу, что вы можете получить это из модуля ansible user, зарегистрировав его как переменную.

- user:
    name: www-data
    state: present
  register: webserver_user_registered

Примечание: он создаст пользователя, если он не существует...

Таким образом, мы можем использовать отладку, чтобы показать значения этой переменной, включая путь...

- debug:
    var: webserver_user_registered

TASK [wordpress : debug] ******************
ok: [wordpresssite.org] => {
    "webserver_user_registered": {
        "append": false,
        "changed": false,
        "comment": "www-data",
        "failed": false,
        "group": 33,
        "home": "/var/www",      <<------ this is the user home dir
        "move_home": false,
        "name": "www-data",
        "shell": "/usr/sbin/nologin",
        "state": "present",
        "uid": 33
    }
}

И вы можете использовать эти свойства в других модулях, как этот;

- file:
    name: "{{ webserver_user_registered.home }}/.wp-cli"
    state: directory

Ответ 5

Я знаю, что это довольно старый поток, но я думаю, что это немного проще для получения домашней директории пользователей.

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

В системах Linux (или Unix) знак тильды указывает на домашний каталог пользователей.

Ответ 6

Вы можете использовать expanduser.

Например, при переходе по списку пользователей:

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

Ответ 7

В каждом ответе говорится о том, как распечатать информацию о домашнем каталоге при запуске playbook и отобразить его на экране, используя debug и var.

Адаптация к ответу @TrinitronX

Дополнительная информация об использовании этой информации для нового задания.

У меня есть список пользователей, чей домашний каталог нужно извлечь. Итак, я добавил данные пользователя в список

- name: Get home directory
  shell: >
         getent passwd {{ item.user }} | cut -d: -f6
  changed_when: false
  with_items:
   - "{{java}}"
  register: user_home

Здесь этот шаг перебирает весь список пользователей и регистрирует эти данные в user_home. И это будет в виде массива.

Затем следующим шагом будет использование этой информации для новой задачи, например, для поиска файла в профиле bash. Это всего лишь пример и может быть любой сценарий, но метод останется прежним.

- name: Set Java home in .bash_profile
  lineinfile: path="{{ item.stdout }}/.bash_profile" regexp='^source "{{ java_dir }}/.bash_profile_java"' line='source "{{ java_dir }}/.bash_profile_java"' state=present
  with_items:
   - "{{ user_home.results }}"
  loop_control:
    label: "{{ item.stdout }}"

Я установил факт для java_dir в /usr/java/latest в той же книге.

Массив user_home.results будет содержать детали задачи "Получить домашний каталог". Теперь мы перебираем этот массив и извлекаем значение stdout, которое содержит путь к домашнему каталогу.

Я поставил loop_control только для печати домашнего каталога, иначе он распечатает весь массив.

Посредством этого процесса мы можем гарантировать, что если существует n пользователей, мы можем следовать этому методу и обо всем позаботимся.

Примечание: я начал изучать Ansible, в случае, если какая-либо терминология, которую я использовал, неверна, извините. Я потратил некоторое время на то, чтобы понять, как это сделать, и подумал о том, чтобы поделиться тем же.

Ответ 8

В настоящий момент нет простого способа сделать это в Ansible, и почему вы должен добавить свои голоса в эту проблему

https://github.com/ansible/ansible/issues/15901

В то время как вы можете использовать этот обходной путь: fooobar.com/questions/144669/..., вы не должны забывать отправлять отзывы, которые хотите, чтобы это было легко использовать.

Ответ 9

Мне нужна была аналогичная функция, но иногда мне хотелось получить домашнюю папку для другого пользователя, кроме исполнителя. Поэтому я написал фильтр, который, кажется, работает очень хорошо - НО только в среде с одним машиной (см. Первый комментарий).

import pwd
from ansible.errors import AnsibleFilterError

def user_attribute(user, key):
    """
    User attribute lookup.
    :param user: the user to get the attribute for
    :param key: the attribute index to return
    :return: the attribute of the given user
    """
    try:
        return pwd.getpwnam(user).__getattribute__(key)
    except KeyError:
        raise AnsibleFilterError('No such user {}'.format(user))
    except AttributeError:
        raise AnsibleFilterError('Wrong index supplied: {}'.format(key))


class FilterModule(object):

    @staticmethod
    def filters():
        return {
            'user_home': lambda x: user_attribute(x, 'pw_dir'),
        }

Просто включите это среди своих фильтров, и вы можете ввести {{ username | user_home }} для любого пользователя, которого вы хотите. Он полагается на пакет pwd, чтобы он не был безупречным.

Ответ 10

Я пришел в эту ветку, потому что мне нужно было напечатать переменную 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}}"