when tutorial run playbook how files español define arquitectura ansible ansible-facts

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.