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


Я могу сделать это с консоли с помощью комбинации getent и awk такой:

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

для справки, в Puppet я могу использовать пользовательский факт, например:

require 'etc'

Etc.passwd { |user|

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

}

что делает домашний каталог пользователя как home_<user name> факт.

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

8 53

8 ответов:

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

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

кроме того, вы можете получить доступ к переменным среды с помощью поиск on 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 }}"

выход:

vagrant@Test-01:~$ 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, если вы не можете получить модуль, чтобы дать вам то, что вы хотите, то вы всегда можете shell out (хотя это должно использоваться экономно, поскольку оно может быть хрупким и будет менее описательным), используя что-то вроде этого:

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

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

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

Проблема

The 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.

пример Ansible getent

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

Ansible 1.8 ввел getent модуль. Он регистрирует результат 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]}) }}"

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

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

# The `webserver_user` value will usually be provided by a distro 
# specific vars file. But for the purposes of demonstration, let's
# hard code it to something...

- set_fact:
    webserver_user: www-data
  when: ansible_os_family is 'Debian'

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

- user:
    name: "{{ webserver_user }}"
    state: present
  register: webserver_user_registered

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

- 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

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

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

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

каждый ответ упоминает о том, как распечатать детали домашнего каталога во время запуска 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 в том же playbook.

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

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

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

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

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

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

в то время как вы можете использовать этот обходной путь:https://stackoverflow.com/a/33343455/99834 Вы не должны забывать, чтобы отправить обратную связь, что вы хотите, чтобы это было легко использовать.

можно использовать expanduser.

например, при циклическом просмотре списка пользователей:

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