tutorial - ¿Cómo obtener el directorio de inicio de un usuario remoto arbitrario en Ansible?
arquitectura ansible (9)
El problema
La
lookup()
o los métodos ENV var para encontrar la casa de un usuario arbitrario lamentablemente no funcionarán de manera confiable con Ansible porque se ejecuta como el usuario especificado con
--user=REMOTE_USER
, y opcionalmente con
sudo
(si
sudo: yes
en el libro de jugadas o
--sudo
pasó).
Estos dos modos de ejecución (sudo o no sudo) cambiarán el entorno de shell en el que se ejecuta Ansible, e incluso entonces estará limitado al usuario especificado como
-u REMOTE_USER
o
root
.
Puede intentar usar
sudo: yes
y
sudo_user: myarbitraryuser
juntos ... sin embargo, debido a un error en
ciertas versiones de Ansible
, puede ver que no se comporta como debería.
Si está en Ansible> =
1.9
, puede usar
become_user: myarbitraryuser
y
become_user: myarbitraryuser
en
become_user: myarbitraryuser
lugar.
Sin embargo, esto significa que los libros de jugadas y los roles que escribes no funcionarán en versiones anteriores de Ansible.
Si está buscando una forma portátil de obtener el directorio de inicio de un usuario que también funcione con LDAP o algún otro servicio de directorio, use
getent
.
Ejemplo de Gent Ansible
Cree un libro de jugadas simple llamado:
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
Ejecútalo con:
ansible-playbook -i inventory/racktables.py playbooks/ad-hoc/get-user-homedir.yml -e "user=someuser"
Puedo hacer eso con shell usando la combinación de
getent
y
awk
esta manera:
getent passwd $user | awk -F: ''{ print $6 }''
Para la referencia, en Puppet puedo usar un hecho personalizado, como este:
require ''etc''
Etc.passwd { |user|
Facter.add("home_#{user.name}") do
setcode do
user.dir
end
end
}
lo que hace que el directorio de inicio del usuario esté disponible como un hecho de
home_<user name>
.
¿Cómo obtengo el directorio de inicio de un usuario remoto arbitrario ?
Ansible (desde 1.4 en adelante) ya revela variables de entorno para el usuario bajo la variable
ansible_env
.
- hosts: all
tasks:
- name: debug through ansible.env
debug: var=ansible_env.HOME
Alternativamente, puede acceder a las variables de entorno utilizando una
lookup
en
env
:
- hosts: all
tasks:
- name: debug through lookup on env
debug: var=lookup(''env'',''HOME'')
Desafortunadamente, aparentemente solo puede usar esto para obtener variables de entorno para el usuario conectado, como muestra este libro de jugadas y la salida:
- 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 }}"
SALIDA
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
Al igual que con cualquier cosa en Ansible, si no puede obtener un módulo que le brinde lo que desea, siempre tiene la libertad de shell (aunque esto debe usarse con moderación, ya que puede ser frágil y será menos descriptivo) usando algo como esto :
- 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
Puede haber una forma más limpia de hacer esto y estoy un poco sorprendido de que el uso de
become_user
para cambiar al usuario especificado no parezca afectar la búsqueda del
env
pero esto debería darle lo que desea.
Ansible 1.8 introdujo el
módulo
getent
.
Registra el resultado getent como un hecho de host; en este caso, es
getent_passwd
.
ejemplos:
Imprima la carpeta de inicio de un
user
determinado:
---
- getent:
database: passwd
key: "{{ user }}"
split: ":"
- debug:
msg: "{{ getent_passwd[user][4] }}"
Acumule una tabla de búsqueda (
user_homes
), aprovechando
set_fact
y el
filtro
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]}) }}"
Sin embargo, sería mejor con un módulo de hechos personalizado.
Creo que hay varias respuestas dadas aquí que funcionarían, pero pensé en mostrar que puede obtener esto del módulo de usuario ansible , registrándolo como una variable.
- user:
name: www-data
state: present
register: webserver_user_registered
Nota: creará el usuario si no existe ...
Entonces podemos usar la depuración para mostrar los valores de esa var, incluida la ruta ...
- 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
}
}
Y puede usar esas propiedades en otros módulos como este;
- file:
name: "{{ webserver_user_registered.home }}/.wp-cli"
state: directory
Llegué a este hilo porque necesitaba imprimir la variable env PGDATA del usuario de postgres, no he encontrado cómo hacerlo de forma más "nativa" en ansible, pero terminé teniendo esto que funciona:
- name: Find postgresql data directory shell: ''echo $PGDATA'' become: yes become_user: postgres become_flags: "-i " register: pgdata_dir
Entonces puedo hacer referencia a eso en otro trabajo usando "{{pgdata_dir.stdout}}"
No hay una manera fácil de hacer esto en Ansible en este momento y es por eso que debe agregar sus votos a este tema
https://github.com/ansible/ansible/issues/15901
Si bien puede usar esta solución alternativa: https://.com/a/33343455/99834 no debe olvidar enviar los comentarios de que desea que sea fácil de usar.
Puedes usar
expanduser
.
Por ejemplo, al recorrer una lista de usuarios:
- name: Deploys .bashrc
template:
src: bashrc.j2
dest: "{{ ''~'' + item | expanduser }}/.bashrc"
mode: 0640
owner: "{{ item }}"
group: "{{ item }}"
with_items: user_list
Sé que este es un hilo bastante antiguo, pero creo que esta es una forma un poco más simple para obtener el directorio de inicio de los usuarios
- name: Get users homedir
local_action: command echo ~
register: homedir
En sistemas Linux (o Unix), el signo de tilde apunta al directorio de inicio de los usuarios.
Cada respuesta menciona cómo imprimir los detalles del directorio de inicio mientras se ejecuta el libro de jugadas y se muestra en la pantalla usando depuración y var
.
Adaptación a la answer @TrinitronX
Una información adicional sobre el uso de esta información para una nueva tarea.
Tengo una lista de usuarios cuyo directorio de inicio debe extraerse. Así que he agregado los detalles del usuario a una lista
- name: Get home directory
shell: >
getent passwd {{ item.user }} | cut -d: -f6
changed_when: false
with_items:
- "{{java}}"
register: user_home
Aquí este paso recorrerá toda la lista de usuarios y registrará esos detalles en user_home.
Y esto será en forma de matriz.
Luego, el siguiente paso es utilizar esta información para una nueva tarea, es decir, por ejemplo, obtener un archivo en el perfil bash.
Este es solo un ejemplo y puede ser cualquier escenario, pero el método seguirá siendo el mismo.
- 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 }}"
He establecido un hecho para java_dir en / usr / java / latest en el mismo libro de jugadas.
La matriz user_home.results contendrá los detalles de la tarea Obtener directorio de inicio.
Ahora recorremos esta matriz y sacamos el valor stdout que contiene la ruta del directorio de inicio.
He puesto loop_control para imprimir solo el directorio de inicio, de lo contrario, imprimirá toda la matriz.
Mediante este proceso, podemos asegurarnos de que si hay un número de usuarios, podemos seguir este método y todos serán atendidos.
Nota: He comenzado a aprender el Ansible, en caso de que alguna terminología que haya utilizado sea incorrecta, disculpe. He dedicado algo de tiempo a descubrir cómo hacer esto y pensé en compartir lo mismo.