Как получить произвольный домашний каталог удаленного пользователя в Ansible?
Я могу сделать это с помощью оболочки, используя комбинацию 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>
факт.
Как получить домашний каталог произвольного удаленного пользователя?
10 ответов
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'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, если вы не можете получить модуль, который даст вам то, что вы хотите, вы всегда можете выложить (хотя это следует использовать экономно, поскольку оно может быть хрупким и будет менее наглядным), используя что-то вроде этого:
- 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
ищите, но это должно дать вам то, что вы хотите.
Я думаю, что здесь дано несколько ответов, которые сработают, но я подумал, что покажу, что вы можете получить это из пользовательского пользовательского модуля, зарегистрировав его как переменную.
# 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:
name: "{{ webserver_user }}"
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
Ansible 1.8 представил getent
модуль. Он регистрирует полученный результат как факт хоста - в данном случае это getent_passwd
,
Примеры:
Распечатать домашнюю папку для данного user
:
---
- getent:
database: passwd
key: "{{ user }}"
split: ":"
- debug:
msg: "{{ getent_passwd[user][4] }}"
Накопить справочную таблицу (user_homes
), используя set_fact
и Джинджа2 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]}) }}"
Было бы лучше с модулем пользовательских фактов, хотя.
Эта проблема
lookup()
или ENV var методы для поиска дома произвольного пользователя, к сожалению, не будут надежно работать с Ansible, потому что он работает как пользователь, указанный в --user=REMOTE_USER
и, возможно, с sudo
(если sudo: yes
в пьесе или --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
Создайте простую пьесу под названием: 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, а не вызывать внешнюю команду: в основном ответ @Tom сuser:
в сочетании с комментарием @Tomáš Pospíšek к этому ответу, чтобы предотвратить создание пользователя, если он еще не существует:
- ansible.builtin.user:
name: www-data
state: present
register: user_info
check_mode: true # Important, otherwise user will be created
Теперь допроситьuser_info
: Атрибут сообщит вам, был ли пользователь создан, т.е. он еще не существует. Если не задано (значит, пользователь уже существует), домашний каталог будет вuser_info.home
,
- ansible.builtin.debug:
var: user_info.home
В качестве альтернативы, если не гарантируется, что пользователь уже существует, вы можете найти один из следующих полезных способов, используяchanged
атрибут для управления вашими действиями,
- ansible.builtin.debug:
var: user_info.home
when:
not user_info.changed
- ansible.builtin.debug:
msg: "{% if user_info.changed|bool %}user doesn't exist{% else %}{{ user_info.home }}{% endif %}"
- ansible.builtin.fail:
msg: "User doesn't exist. Create user before using this playbook."
when: user_info.changed
Я знаю, что это довольно старая тема, но я думаю, что это немного более простой способ получить домашний каталог пользователей
- 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 в той же книге.
Массив user_home.results будет содержать детали задачи "Получить домашний каталог". Теперь мы перебираем этот массив и извлекаем значение stdout, которое содержит путь к домашнему каталогу.
Я поставил loop_control только для печати домашнего каталога, иначе он распечатает весь массив.
Посредством этого процесса мы можем гарантировать, что если существует n пользователей, мы можем следовать этому методу и обо всем позаботимся.
Примечание: я начал изучать Ansible, в случае, если какая-либо терминология, которую я использовал, неверна, извините. Я потратил некоторое время на то, чтобы понять, как это сделать, и подумал о том, чтобы поделиться тем же.
Ты можешь использовать expanduser
,
Например, во время цикла по списку пользователей:
- name: Deploys .bashrc
template:
src: bashrc.j2
dest: "{{ '~' + item | expanduser }}/.bashrc"
mode: 0640
owner: "{{ item }}"
group: "{{ item }}"
with_items: user_list
Я пришел в эту ветку, потому что мне нужно было распечатать переменную env PGDATA от пользователя postgres, я не нашел, как сделать это более "родно" в недоступном, но у меня получилось, что это работает:
- name: Find postgresql data directory
shell: 'echo $PGDATA'
become: yes
become_user: postgres
become_flags: "-i "
register: pgdata_dir
Тогда я могу ссылаться на это в другом задании, используя "{{ pgdata_dir.stdout }}"
В Ansible сейчас нет простого способа сделать это, и поэтому вы должны добавить свои голоса к этому вопросу.
https://github.com/ansible/ansible/issues/15901
Хотя вы можете использовать этот обходной путь: /questions/2350838/kak-poluchit-proizvolnyij-domashnij-katalog-udalennogo-polzovatelya-v-ansible/2350851#2350851 вы не должны забывать отправлять отзывы, которые вы хотите, чтобы это было легко использовать.