No es posible obtener .bashrc con Ansible

85

Puedo enviar ssh al host remoto y hacer una source /home/username/.bashrc- todo funciona bien. Sin embargo, si lo hago:

- name: source bashrc
  sudo: no
  action: command source /home/username/.bashrc

Yo obtengo:

failed: [hostname] => {"cmd": ["source", "/home/username/.bashrc"], "failed": true, "rc": 2}
msg: [Errno 2] No such file or directory

No tengo idea de lo que estoy haciendo mal ...

pldimitrov
fuente
sourcesolo tiene sentido cuando lo ejecuta dentro de un shell existente: ejecuta comandos en ese shell y, por lo tanto, solo es útil / útil cuando hay un shell existente cuyo estado o configuración desea cambiar. Cuando ejecuta una acción ansible, eso crea un shell completamente nuevo y ejecuta un comando dentro de ese shell, por lo que no estaría actualizando las variables de entorno en ningún otro contexto, por lo que en realidad no tendría ningún efecto útil / duradero , incluso si logra que esto se ejecute sin errores.
Charles Duffy
@CharlesDuffy Si desea ejecutar un comando que espera que se definan variables de entorno, entonces intentar obtener algo como .bashrc o .bash_profile para definir dichas variables es un caso de uso válido, ¿no?
htellez
@htellez, la ejecución sourcesolo define variables durante la duración del shell en el que se ejecuta . Y ese shell ha salido (y las variables que define se han perdido) en el momento en que el comando ansible sale y comienza el siguiente.
Charles Duffy
@htellez, ... por lo tanto, la única respuesta aquí que es realmente útil de alguna manera significativa es la de Steve Midgley , ya que te hace hacer otra cosa en el mismo shell que se ejecutó source, antes de salir.
Charles Duffy
Ese es exactamente el caso de uso que traté de describir, lo siento si no estaba claro. Traté de describir un escenario en el que desea ejecutar algo que espera que se defina un entorno particular. Llegué a este hilo porque recibí el mismo error, y al leer la respuesta de Steve, me di cuenta de que la tarea de shell de ansible usa sh de forma predeterminada en lugar de bash. Convertir el comando en un comando bash explícitamente hace que el sourcetrabajo funcione de la manera más probable.
htellez

Respuestas:

88

Tiene dos opciones para usar la fuente con ansible. Una es con el comando "shell:" y / bin / sh (el valor predeterminado de ansible). "fuente" se llama "." en / bin / sh. Entonces tu comando sería:

- name: source bashrc
  sudo: no   
  shell: . /home/username/.bashrc && [the actual command you want run]

Tenga en cuenta que debe ejecutar un comando después de obtener .bashrc b / c cada sesión ssh es distinta: cada comando ansible se ejecuta en una transacción ssh separada.

Su segunda opción es forzar a Ansible shell a usar bash y luego puede usar el comando "fuente":

- name: source bashrc
  sudo: no   
  shell: source /home/username/.bashrc && [the actual command you want run]
  args:
     executable: /bin/bash

Finalmente, señalaré que es posible que desee obtener "/ etc / profile" si está en Ubuntu o similar, que simula más completamente un inicio de sesión local.

Steve Midgley
fuente
3
También tenga en cuenta que este problema ha sido archivado (y comentado por mí) como una solicitud de error / función en el núcleo de Ansible. Pero Ansible lo cerró y dijo "escribe un complemento". Bah. github.com/ansible/ansible/issues/4854
Steve Midgley
1
Estas leyendo mi mente? Respondió esto hace 3 meses, y estaba pensando en editar esto .-> source- e inmediatamente hizo esto :)
warvariuc
Lo intenté source "/etc/profile", no funcionó para mí. Esto funcionó:source "~/.profile"
warvariuc
5
Tengo algunas funciones de bash definidas dentro de .bashrc y después de obtener el .bashrc. ¿Cómo puedo ejecutar / llamar a esas funciones? Lo estoy intentando shell: . ~/.bashrc && nvm install {{ node_version }}y dice nvm command not found. ¿Como puedo resolver esto?
RaviTezu
1
@RaviTezu: El problema en mi caso se debió a las siguientes líneas en .bashrc: # Si no se ejecuta de forma interactiva, no hagas nada case $ - in i ) ;; *) regreso;; esac Esto es al menos un problema en ubuntu-16.04 xenial64 donde .bashrc no se ejecuta en shells no interactivos, que es el caso cuando se ejecutan comandos a través de ssh. Para probarlo, establezca alguna RUTA en ~ / .bashrc y ejecute (suponiendo que haya configurado el puerto 2222 reenviado a 22 en el sistema operativo invitado): ssh -p 2222 [email protected] 'echo $ PATH' Si el comando anterior no lo hace ' t muestre la RUTA que ha establecido en .bashrc y luego corrija .bashrc
Divick
24

Entonces commandsolo ejecutará ejecutables. sourceper se no es un ejecutable. (Es un comando de shell incorporado). ¿Hay alguna razón por la que desee sourceuna variable de entorno completa?

Hay otras formas de incluir variables de entorno en Ansible. Por ejemplo, la environmentdirectiva:

- name: My Great Playbook
  hosts: all
  tasks:
    - name: Run my command
      sudo: no
      action: command <your-command>
      environment:
          HOME: /home/myhome

Otra forma es usar el shellmódulo Ansible:

- name: source bashrc
  sudo: no
  action: shell source /home/username/.bashrc && <your-command>

o

- name: source bashrc
  sudo: no   
  shell: source /home/username/.bashrc && <your-command>

En estos casos, la instancia / entorno de shell terminará una vez que se ejecute el paso de Ansible.

Rico
fuente
2
casi bueno, desafortunadamente / bin / sh no solo tiene comando de origen. así se shell source /home/username/.bashrcconvierte enshell . /home/username/.bashrc
b1r3k
La tarea de shell toma un parámetro como tal: executable=/usr/bin/bashque luego lo ejecutará en bash si está disponible como tal.
fgysin reintegra a Monica el
16

Sé que esta respuesta llegó demasiado tarde, pero he visto en suficiente código que puede usar la opción sudo -i para:

- name: source bashrc
  shell: sudo -iu {{ansible_user_id}} [the actual command you want run]

Como se dice en la documentación

The -i (simulate initial login) option runs the shell specified by the password database entry of the target user as a login shell.  This means that login-specific
               resource files such as .profile or .login will be read by the shell.  If a command is specified, it is passed to the shell for execution via the shell's -c option.
               If no command is specified, an interactive shell is executed.  sudo attempts to change to that user's home directory before running the shell.  It also initializes
               the environment to a minimal set of variables, similar to what is present when a user logs in.  The Command environment section below documents in detail how the -i
               option affects the environment in which a command is run.
Clempat
fuente
5

Estaba experimentando el mismo problema al intentar que virtualenvwrapper funcionara en un servidor Ubuntu. Estaba usando Ansible así:

- name: Make virtual environment
  shell: source /home/username/.bashrc && makevirtualenv virenvname
  args:
    executable: /bin/bash

pero el comando de origen no funcionaba.

Finalmente descubrí que el archivo .bashrc tiene algunas líneas en la parte superior del archivo que impiden que la fuente funcione cuando Ansible lo llama:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Comenté esas líneas en .bashrc y todo funcionó como se esperaba después de eso.

gwerner
fuente
Ese es un encabezado perfectamente razonable y estándar para la mayoría de los .bashrcarchivos. Probablemente desee obtener un archivo de shell diferente o usarlo BASH_ENVcomo se explica en los documentos de bash.
2

Bueno, probé las respuestas enumeradas, pero no me funcionaron al instalar ruby ​​a través de rbenv . Tuve que buscar debajo de las líneas de/root/.bash_profile

PATH=$PATH:$HOME/bin:$HOME/.rbenv/bin:$HOME/.rbenv/plugins/ruby-build/bin
export PATH
eval "$(rbenv init -)"

Finalmente, se me ocurrió esto

- shell: sudo su - root -c 'rbenv install -v {{ ruby_version }}'

Uno puede usar esto con cualquier comando.

- shell: sudo su - root -c 'your command'
vikas027
fuente
1
Este enfoque clásico funciona con Ansible 2.2.0.0. Sin embargo, me molesta que deba usar become, become_methody en su become_userlugar ... no pude encontrar una combinación de esos parámetros de "método" que funcionarían de todos modos.
Yuri
2

Encontré convertido en la mejor solución:

- name: Source .bashrc
  shell: . .bashrc
  become: true

Puede cambiar el usuario agregando (predeterminado: root):

- name: Source .bashrc
  shell: . .bashrc
  become: true
  become-user: {your_remote_user}

Más información aquí: Ansible convertirse

Zlopez
fuente
2

Muchas respuestas recomiendan la fuente ~ / .bashrc, pero el problema principal es que el shell ansible no es interactivo y la implementación de ~ / .bashrc por defecto ignora el shell no interactivo (verifique su comienzo).

La mejor solución para ejecutar comandos como usuario después de su inicio de sesión interactivo ssh que encontré es:

- hosts: all
  tasks:
    - name: source user profile file
      #become: yes
      #become_user: my_user  # in case you want to become different user (make sure acl package is installed)
      shell: bash -ilc 'which python' # example command which prints
      register: which_python
    - debug:
      var: which_python

bash: '-i' significa shell interactivo, por lo que .bashrc no se ignorará '-l' significa shell de inicio de sesión que obtiene el perfil de usuario completo

Juraj Michalak
fuente
0

Probé todas las opciones anteriores con ansible 2.4.1.0 y nadie funciona hasta otros dos y aquí está el detalle para volver a producir el caso.

$ cat ~/.bash_aliases 
alias ta="echo 'this is test for ansible interactive shell'";

Y esta es la prueba ansible :

- name: Check the basic string operations
  hosts: 127.0.0.1 
  connection: local

  tasks:
  - name: Test Interactive Bash Failure
    shell: ta
    ignore_errors: True

  - name: Test Interactive Bash Using Source
    shell: source ~/.bash_aliases && ta
    args:
      executable: /bin/bash
    ignore_errors: yes

  - name: Test Interactive Bash Using .
    shell: . ~/.bash_aliases && ta
    ignore_errors: yes

  - name: Test Interactive Bash Using /bin/bash -ci
    shell: /bin/bash -ic 'ta'
    register: result
    ignore_errors: yes

  - debug: msg="{{ result }}"

  - name: Test Interactive Bash Using sudo -ui
    shell: sudo -ui hearen ta
    register: result
    ignore_errors: yes

  - name: Test Interactive Bash Using ssh -tt localhost /bin/bash -ci
    shell: ssh -tt localhost /bin/bash -ci 'ta'
    register: result
    ignore_errors: yes

Y este es el resultado:

$ ansible-playbook testInteractiveBash.yml 
 [WARNING]: Could not match supplied host pattern, ignoring: all

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [Check the basic string operations] ************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************
ok: [127.0.0.1]

TASK [Test Interactive Bash Failure] ****************************************************************************************************************************************************
fatal: [127.0.0.1]: FAILED! => {"changed": true, "cmd": "ta", "delta": "0:00:00.001341", "end": "2018-10-31 10:11:39.485897", "failed": true, "msg": "non-zero return code", "rc": 127, "start": "2018-10-31 10:11:39.484556", "stderr": "/bin/sh: 1: ta: not found", "stderr_lines": ["/bin/sh: 1: ta: not found"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Test Interactive Bash Using Source] ***********************************************************************************************************************************************
fatal: [127.0.0.1]: FAILED! => {"changed": true, "cmd": "source ~/.bash_aliases && ta", "delta": "0:00:00.002769", "end": "2018-10-31 10:11:39.588352", "failed": true, "msg": "non-zero return code", "rc": 127, "start": "2018-10-31 10:11:39.585583", "stderr": "/bin/bash: ta: command not found", "stderr_lines": ["/bin/bash: ta: command not found"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Test Interactive Bash Using .] ****************************************************************************************************************************************************
fatal: [127.0.0.1]: FAILED! => {"changed": true, "cmd": ". ~/.bash_aliases && ta", "delta": "0:00:00.001425", "end": "2018-10-31 10:11:39.682609", "failed": true, "msg": "non-zero return code", "rc": 127, "start": "2018-10-31 10:11:39.681184", "stderr": "/bin/sh: 1: ta: not found", "stderr_lines": ["/bin/sh: 1: ta: not found"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Test Interactive Bash Using /bin/bash -ci] ****************************************************************************************************************************************
changed: [127.0.0.1]

TASK [debug] ****************************************************************************************************************************************************************************
ok: [127.0.0.1] => {
    "msg": {
        "changed": true, 
        "cmd": "/bin/bash -ic 'ta'", 
        "delta": "0:00:00.414534", 
        "end": "2018-10-31 10:11:40.189365", 
        "failed": false, 
        "rc": 0, 
        "start": "2018-10-31 10:11:39.774831", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "this is test for ansible interactive shell", 
        "stdout_lines": [
            "this is test for ansible interactive shell"
        ]
    }
}

TASK [Test Interactive Bash Using sudo -ui] *********************************************************************************************************************************************
 [WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running sudo

fatal: [127.0.0.1]: FAILED! => {"changed": true, "cmd": "sudo -ui hearen ta", "delta": "0:00:00.007906", "end": "2018-10-31 10:11:40.306128", "failed": true, "msg": "non-zero return code", "rc": 1, "start": "2018-10-31 10:11:40.298222", "stderr": "sudo: unknown user: i\nsudo: unable to initialize policy plugin", "stderr_lines": ["sudo: unknown user: i", "sudo: unable to initialize policy plugin"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Test Interactive Bash Using ssh -tt localhost /bin/bash -ci] **********************************************************************************************************************
hearen@localhost's password: 
changed: [127.0.0.1]

PLAY RECAP ******************************************************************************************************************************************************************************
127.0.0.1                  : ok=8    changed=6    unreachable=0    failed=0  

Hay dos opciones trabajadas:

  • shell: /bin/bash -ic 'ta'
  • shell: ssh -tt localhost /bin/bash -ci 'ta' pero este requiere la entrada de contraseña localmente.
Hearen
fuente
0

Mis 2 centavos, i dado la vuelta al problema de abastecimiento ~/.nvm/nvm.shen ~/.profiley luego usar sudo -iucomo sugirieron en otra respuesta.

Probado en enero de 2018 vs Ubuntu 16.04.5

- name: Installing Nvm 
  shell: >
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
  args:
    creates: "/home/{{ ansible_user }}/.nvm/nvm.sh"
  tags:
    - nodejs    

- name: Source nvm in ~/.profile
  sudo: yes
  sudo_user: "{{ ansible_user }}"
  lineinfile: >
    dest=~/.profile
    line="source ~/.nvm/nvm.sh"
    create=yes
  tags: 
    - nodejs
  register: output    

- name: Installing node 
  command: sudo -iu {{ ansible_user }} nvm install --lts
  args:
     executable: /bin/bash
  tags:
    - nodejs    
realtebo
fuente
-3

La forma correcta debería ser:

- hosts: all
  tasks:
    - name: source bashrc file
      shell: "{{ item }}"
      with_items:
         - source ~/.bashrc
         - your other command

Nota: es prueba en ansible 2.0.2versión

kwin wng
fuente