working - when syntax ansible




Como obter o diretório home de um usuário remoto arbitrário no Ansible? (6)

O problema

Os métodos lookup() ou ENV var para localizar a casa de um usuário arbitrário infelizmente não funcionarão com Ansible porque ele é executado como o usuário especificado com --user=REMOTE_USER e, opcionalmente, com sudo (se sudo: yes no playbook ou --sudo passou). Esses dois modos de execução (sudo ou nenhum sudo) alterarão o ambiente do shell no qual o Ansible está sendo executado e, mesmo assim, você estará limitado ao usuário especificado como -u REMOTE_USER ou root .

Você poderia tentar usar sudo: yes , e sudo_user: myarbitraryuser juntos ... no entanto devido a um bug em certas versões do Ansible você pode ver que ele não se comporta como deveria. Se você estiver no Ansible> = 1.9 , você poderá usar become: true e, em vez disso, o become_user: myarbitraryuser . No entanto, isso significa que os playbooks e as funções que você escreve não funcionarão nas versões anteriores do Ansible.

Se você estiver procurando uma maneira portátil de obter o diretório inicial de um usuário que também funcionará com o LDAP ou algum outro serviço de diretório, use getent .

Exemplo de getableible

Crie um livro de exercícios simples chamado: 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

Execute-o com:

ansible-playbook -i inventory/racktables.py playbooks/ad-hoc/get-user-homedir.yml -e "user=someuser"

Eu posso fazer isso com shell usando a combinação de getent e awk assim:

getent passwd $user | awk -F: '{ print $6 }'

Para a referência, no Puppet eu posso usar um fato customizado, assim:

require 'etc'

Etc.passwd { |user|

   Facter.add("home_#{user.name}") do
      setcode do
         user.dir
      end
   end

}

que torna o diretório home do usuário disponível como um fato home_<user name> .

Como faço para obter o diretório pessoal de um usuário remoto arbitrário ?


Ansible (a partir de 1.4 em diante) já revela variáveis ​​de ambiente para o usuário sob a variável ansible_env .

- hosts: all
  tasks:
    - name: debug through ansible.env
      debug: var=ansible_env.HOME

Como alternativa, você pode acessar variáveis ​​de ambiente usando uma lookup no env :

- hosts: all
  tasks:
    - name: debug through lookup on env
      debug: var=lookup('env','HOME')

Infelizmente, aparentemente, você só pode usar isso para obter variáveis ​​de ambiente para o usuário conectado, como mostra este manual e mostra a saída:

- 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 }}"

SAÍDA :

[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'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

Como com qualquer coisa no Ansible, se você não puder obter um módulo para dar o que você quer, então você está sempre livre para shell (embora isto deva ser usado com moderação, pois pode ser frágil e será menos descritivo) usando algo como isto :

- 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

Pode haver uma maneira mais limpa de fazer isso e estou um pouco surpreso ao usar o método become_user para alternar para o usuário especificado não parece afetar a pesquisa de env mas isso deve dar o que você deseja.


Eu sei que isso é bastante antigo, mas eu acho que isso é um pouco mais simples para obter o diretório home dos usuários

- name: Get users homedir
  local_action: command echo ~
  register: homedir

Nos sistemas Linux (ou Unix), o sinal de til aponta para o diretório inicial do usuário.


Não há uma maneira fácil de fazer isso no Ansible neste momento e é por isso que você deve adicionar seus votos a essa questão

https://github.com/ansible/ansible/issues/15901

Enquanto você pode usar esta solução alternativa: https://.com/a/33343455/99834 você não deve esquecer de enviar o feedback que você quer que isso seja fácil de ser usado.


Você pode usar o expanduser .

Por exemplo, durante o loop de uma lista de usuários:

- name: Deploys .bashrc
  template:
    src: bashrc.j2
    dest: "{{ '~' + item | expanduser }}/.bashrc"
    mode: 0640
    owner: "{{ item }}"
    group: "{{ item }}"
  with_items: user_list

Cada resposta menciona sobre como imprimir os detalhes do diretório inicial durante a execução do playbook e exibi-lo na tela usando debug e var .

Adaptando-se à answer @TrinitronX

Uma informação adicional sobre o uso desta informação para uma nova tarefa.

Eu tenho uma lista de usuários cujo diretório home precisa ser extraído. Então eu adicionei os detalhes do usuário a uma lista

- name: Get home directory
  shell: >
         getent passwd {{ item.user }} | cut -d: -f6
  changed_when: false
  with_items:
   - "{{java}}"
  register: user_home

Aqui, este passo irá percorrer toda a lista de usuários e registrará esses detalhes para user_home. E isso será na forma de uma matriz.

Em seguida, o próximo passo é usar essas informações para uma nova tarefa, o que significa, por exemplo, o fornecimento de um arquivo no perfil bash. Este é apenas um exemplo e pode ser qualquer cenário, mas o método permanecerá o mesmo.

- 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 }}"

Eu defini um fato para java_dir para / usr / java / latest no mesmo playbook.

Array user_home.results conterá os detalhes da tarefa Obter diretório pessoal. Agora, percorremos esse array e retiramos o valor stdout que contém o caminho do diretório inicial.

Eu coloquei loop_control para imprimir o diretório home apenas, senão ele irá imprimir toda a matriz.

Por este processo, podemos garantir que, se n número de usuários estiverem lá, podemos seguir este método e todos serão atendidos.

Nota: Eu comecei a aprender o Ansible, caso alguma terminologia que usei esteja errada, por favor, desculpe. Eu gastei algum tempo para descobrir como fazer isso e pensei em compartilhar o mesmo.







ansible-facts