Comment obtenir le répertoire personnel d'un utilisateur distant arbitraire dans Ansible?
Je peux le faire avec shell en utilisant la combinaison de getent
et awk
comme ceci:
getent passwd $user | awk -F: '{ print $6 }'
Pour la référence, dans Puppet je peux utiliser un fait personnalisé, comme ceci:
require 'etc'
Etc.passwd { |user|
Facter.add("home_#{user.name}") do
setcode do
user.dir
end
end
}
Qui rend le répertoire personnel de l'utilisateur disponible en tant que fait home_<user name>
.
Comment puis-je obtenir le répertoire personnel d'un utilisateur distant arbitraire?
8 réponses
Ansible (à partir de la version 1.4) révèle déjà des variables d'environnement pour ansible_env
variable.
- hosts: all
tasks:
- name: debug through ansible.env
debug: var=ansible_env.HOME
Vous pouvez également accéder aux variables d'environnement à l'aide d'une recherche sur env
:
- hosts: all
tasks:
- name: debug through lookup on env
debug: var=lookup('env','HOME')
Malheureusement, vous ne pouvez apparemment l'utiliser que pour obtenir des variables d'environnement pour l'utilisateur connecté comme le montre ce playbook et la sortie:
- 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 }}"
SORTIE:
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
Comme avec N'importe quoi dans Ansible, si vous ne pouvez pas obtenir un module pour vous donner ce que vous voulez, vous êtes toujours libre de shell out (bien que cela devrait être utilisé avec parcimonie car il peut être fragile et sera moins descriptif) en utilisant quelque chose comme ceci:
- 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
Il pourrait bien y avoir une façon plus propre de le faire et je suis un peu surpris que l'utilisation become_user
passer à l'utilisateur spécifié ne semble pas affecter la recherche env
mais cela devrait vous donner ce que vous voulez.
Le Problème
Les méthodes lookup()
ou ENV var pour trouver la maison d'un utilisateur arbitraire ne fonctionneront malheureusement pas de manière fiable avec Ansible car elles fonctionnent comme l'utilisateur spécifié avec --user=REMOTE_USER
, et éventuellement avec sudo
(Si {[5] } dans playbook ou --sudo
passé). Ces deux modes d'exécution (sudo ou no sudo) modifieront L'environnement shell dans lequel Ansible s'exécute, et même dans ce cas, vous serez limité à l'utilisateur spécifié comme -u REMOTE_USER
ou root
.
Vous pouvez essayer d'utiliser sudo: yes
, et sudo_user: myarbitraryuser
ensemble... cependant, en raison d'un bogue dans certaines versions de Ansible, vous pouvez voir qu'il ne se comporte pas comme il le devrait. Si vous êtes sur Ansible >= 1.9
, vous pouvez utiliser become: true
, et become_user: myarbitraryuser
à la place. Cependant, cela signifie que les playbooks et les rôles que vous écrivez ne fonctionneront pas sur les versions précédentes D'Ansible.
Si vous cherchez un moyen portable d'obtenir le répertoire personnel d'un utilisateur qui fonctionnera également avec LDAP ou un autre service d'annuaire, utilisez getent
.
Ansible getent Exemple
Créer un simple playbook nommé: 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
Exécutez-le avec:
ansible-playbook -i inventory/racktables.py playbooks/ad-hoc/get-user-homedir.yml -e "user=someuser"
Ansible 1.8 introduit l'getent
module. Il enregistre le résultat getent comme un fait hôte-dans ce cas, c'est getent_passwd
.
Exemples:
Imprimer le dossier d'accueil pour un user
donné:
---
- getent:
database: passwd
key: "{{ user }}"
split: ":"
- debug:
msg: "{{ getent_passwd[user][4] }}"
Accumuler une table de recherche (user_homes
), en tirant parti de set_fact
et le Jinja2 combine()
filtre:
---
- 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]}) }}"
Serait mieux avec un module de fait personnalisé cependant.
Je pense qu'il y a plusieurs réponses données ici qui fonctionneraient, mais je pensais montrer que vous pouvez l'obtenir à partir du module Ansible user , en l'enregistrant en tant que variable.
# 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'
Ensuite, utilisez le module utilisateur ansible pour vous assurer que l'utilisateur est présent et lisez l'attribut dans une variable enregistrée pour une utilisation ultérieure.
- user:
name: "{{ webserver_user }}"
state: present
register: webserver_user_registered
Nous pouvons donc utiliser debug pour afficher les valeurs de cette var, y compris le chemin...
- 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
}
}
Et vous pouvez utiliser ces propriétés dans d'autres modules comme ça;
- file:
name: "{{ webserver_user_registered.home }}/.wp-cli"
state: directory
Je sais que c'est un fil assez vieux, mais je pense que c'est un moyen un peu plus simple d'obtenir le répertoire personnel des utilisateurs
- name: Get users homedir
local_action: command echo ~
register: homedir
Sur les systèmes Linux (ou Unix), le signe tilde pointe vers le répertoire personnel des utilisateurs.
Chaque réponse mentionne comment imprimer les détails du répertoire personnel lors de l'exécution du playbook et de l'afficher à l'écran en utilisant debug et var.
Adaptation à @ TrinitronX réponse
Une information supplémentaire sur l'utilisation de ces informations pour une nouvelle tâche.
J'ai une liste d'utilisateurs dont le répertoire personnel doit être extrait. J'ai donc ajouté les détails de l'utilisateur à une liste
- name: Get home directory
shell: >
getent passwd {{ item.user }} | cut -d: -f6
changed_when: false
with_items:
- "{{java}}"
register: user_home
Ici, cette étape parcourra toute la liste des utilisateurs et enregistrez ces détails sur user_home. Et ce sera sous la forme d'un tableau.
Ensuite, l'étape suivante consiste à utiliser ces informations pour une nouvelle tâche, c'est-à-dire par exemple l'approvisionnement d'un fichier dans le profil bash. C'est juste un exemple et peut être n'importe quel scénario, mais la méthode reste la même.
- 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 }}"
J'ai mis un fait pour java_dir à /usr/java/latest dans le même playbook.
Tableau user_home.les résultats contiendront les détails de la tâche Get home directory.
Maintenant, nous bouclons ce tableau et retirez la valeur stdout qui contient le chemin du répertoire personnel.
J'ai mis loop_control pour imprimer le répertoire personnel seulement, sinon il imprimera le tableau entier.
Par ce processus, nous pouvons nous assurer que si n nombre d'utilisateurs sont là, nous pouvons suivre cette méthode et tout sera pris en charge.
Note: j'ai commencé à apprendre L'Ansible, au cas où une terminologie que j'ai utilisée serait fausse, veuillez excuser. J'ai passé un peu de temps pour comprendre sur comment faire cela et pensé à partager la même chose.
Il N'y a pas de moyen facile de le faire dans Ansible en ce moment et c'est pourquoi vous ajouter votre voix à cette question
Https://github.com/ansible/ansible/issues/15901
While vous pouvez utiliser cette solution de contournement: https://stackoverflow.com/a/33343455/99834 vous ne devez pas oublier d'envoyer les commentaires que vous voulez que ce soit facile à utiliser.
Vous pouvez utiliser expanduser
.
Par exemple, lors d'une boucle sur une liste d'utilisateurs:
- name: Deploys .bashrc
template:
src: bashrc.j2
dest: "{{ '~' + item | expanduser }}/.bashrc"
mode: 0640
owner: "{{ item }}"
group: "{{ item }}"
with_items: user_list