Как получить произвольный удаленный домашний каталог пользователя в 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>
.
Как получить домашний каталог произвольного удаленного пользователя?
Ответы
Ответ 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}}"