Non è possibile reperire .bashrc con Ansible


85

Posso eseguire ssh sull'host remoto e fare un source /home/username/.bashrc- tutto funziona bene. Tuttavia, se lo faccio:

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

Ottengo:

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

Non ho idea di cosa sto sbagliando ...


sourceha senso solo quando lo si esegue all'interno di una shell esistente: esegue i comandi in quella shell , ed è quindi utile / utile solo quando c'è una shell esistente di cui si desidera modificare lo stato o la configurazione. Quando esegui un'azione ansible, questa crea una shell completamente nuova ed esegue un comando all'interno di quella shell, quindi non aggiorni le variabili di ambiente in nessun altro contesto, quindi non avrebbe effettivamente alcun effetto utile / duraturo , anche se devi farlo funzionare senza errori.
Charles Duffy

@CharlesDuffy Se vuoi eseguire un comando che si aspetta la definizione di variabili d'ambiente, provare a generare qualcosa come .bashrc o .bash_profile per definire tali variabili è un caso d'uso valido, vero?
htellez

@htellez, in esecuzione sourcedefinisce solo le variabili per la durata della shell in cui viene eseguito . E quella shell è terminata (e le variabili che definisce sono andate perse) nel momento in cui il comando ansible termina e inizia quello successivo.
Charles Duffy

@htellez, ... quindi, l'unica risposta qui che è effettivamente utile in un modo significativo è quella di Steve Midgley , poiché ti fa fare qualcos'altro nella stessa shell che girava source, prima che uscisse.
Charles Duffy

Questo è esattamente il caso d'uso che ho cercato di descrivere, mi dispiace se non sono stato chiaro. Ho provato a descrivere uno scenario in cui si desidera eseguire qualcosa che si aspetta un ambiente particolare definito. Sono arrivato a questo thread perché ho ricevuto lo stesso errore e leggendo la risposta di Steve mi sono reso conto che l'attività della shell di ansible utilizza sh per impostazione predefinita invece di bash. Rendere il comando un comando bash esplicitamente fa sourcefunzionare il modo in cui molto probabilmente sei abituato.
htellez

Risposte:


88

Hai due opzioni per usare la sorgente con ansible. Uno è con il comando "shell:" e / bin / sh (l'impostazione predefinita ansible). "fonte" si chiama "." in / bin / sh. Quindi il tuo comando sarebbe:

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

Nota che devi eseguire un comando dopo aver acquisito .bashrc b / c ogni sessione ssh è distinta: ogni comando ansible viene eseguito in una transazione ssh separata.

La seconda opzione è forzare la shell Ansible a utilizzare bash e quindi utilizzare il comando "source":

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

Infine, noterò che potresti voler effettivamente sorgente "/ etc / profile" se sei su Ubuntu o simili, che simula in modo più completo un accesso locale.


3
Nota anche che questo problema è stato segnalato (e commentato da me) come richiesta di bug / funzionalità in Ansible core. Ma Ansible lo chiuse e disse "scrivi un plugin". Bah. github.com/ansible/ansible/issues/4854
Steve Midgley

1
Mi stai leggendo nel pensiero? Hai risposto 3 mesi fa e stavo pensando di modificare questo .-> source- e l'hai fatto immediatamente :)
warvariuc

Ho provato source "/etc/profile"- non ha funzionato per me. Ha funzionato:source "~/.profile"
warvariuc

5
Ho alcune funzioni bash definite all'interno di .bashrc e dopo aver acquisito il .bashrc. come posso eseguire / chiamare quelle funzioni? Sto cercando shell: . ~/.bashrc && nvm install {{ node_version }}e sta dicendo, nvm command not found. Come posso risolvere questo?
RaviTezu

1
@RaviTezu: Il problema nel mio caso era dovuto alle seguenti righe in .bashrc: # Se non funziona in modo interattivo, non fare nulla in caso $ - in i ) ;; *) ritorno;; esac Questo è almeno un problema su ubuntu-16.04 xenial64 dove .bashrc non viene eseguito su shell non interattive, come accade quando si eseguono comandi tramite ssh. Per provarlo, imposta alcuni PATH in ~ / .bashrc ed esegui (supponendo che tu abbia impostato la porta 2222 inoltrata a 22 sul sistema operativo guest): ssh -p 2222 ubuntu@127.0.0.1 'echo $ PATH' Se il comando precedente non funziona ' t mostra il PERCORSO che hai impostato in .bashrc quindi correggi .bashrc
Divick

24

Quindi commandeseguirà solo eseguibili. sourcedi per sé non è un eseguibile. (È un comando di shell incorporato). C'è qualche motivo per cui vuoi sourceuna variabile d'ambiente completa?

Esistono altri modi per includere variabili di ambiente in Ansible. Ad esempio, la environmentdirettiva:

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

Un altro modo è utilizzare il shellmodulo 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>

In questi casi, l'istanza / ambiente della shell terminerà una volta eseguito il passaggio Ansible.


2
quasi buono, sfortunatamente / bin / sh non ha solo il comando sorgente. così shell source /home/username/.bashrcdiventashell . /home/username/.bashrc
b1r3k

L'attività della shell accetta un parametro come tale: executable=/usr/bin/bashche lo eseguirà in bash se è disponibile come tale.
fgysin ripristina Monica il

16

So che questa risposta è arrivata troppo tardi, ma ho visto abbastanza codice che puoi usare l'opzione sudo -i così:

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

Come detto nella documentazione

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.

5

Ho riscontrato lo stesso problema durante il tentativo di far funzionare virtualenvwrapper su un server Ubuntu. Stavo usando Ansible in questo modo:

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

ma il comando sorgente non funzionava.

Alla fine ho scoperto che il file .bashrc ha poche righe all'inizio del file che impediscono al sorgente di funzionare quando viene chiamato da Ansible:

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

Ho commentato quelle righe in .bashrc e dopo tutto ha funzionato come previsto.


Questa è un'intestazione perfettamente ragionevole e standard per la maggior parte dei .bashrcfile. Probabilmente vorrai creare un file shell diverso o usarlo BASH_ENVcome discusso nei documenti di bash.

2

Bene, ho provato le risposte elencate ma quelle non hanno funzionato per me durante l'installazione di ruby ​​tramite rbenv . Ho dovuto fonte sotto le righe da/root/.bash_profile

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

Alla fine, ho pensato a questo

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

Si può usare con qualsiasi comando.

- shell: sudo su - root -c 'your command'

1
Questo approccio classico funziona con Ansible 2.2.0.0. Tuttavia, mi tormenta che dovrei usare become, become_methode become_userinvece ... non sono riuscito a trovare una combinazione di quei parametri "metodo" che funzionerebbero comunque.
Yuri

2

Ho trovato diventare la migliore soluzione:

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

Puoi cambiare l'utente aggiungendo (default: root):

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

Maggiori informazioni qui: Ansible diventa


2

Molte risposte raccomandano ai sorgenti ~ / .bashrc ma il problema principale è che la shell ansible non è interattiva e l'implementazione ~ / .bashrc di default ignora la shell non interattiva (controlla il suo inizio).

La migliore soluzione per eseguire comandi come utente dopo il suo login interattivo ssh che ho trovato è:

- 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 interattiva, quindi .bashrc non verrà ignorato '-l' significa shell di login che fornisce il profilo utente completo


0

Ho provato tutte le opzioni precedenti con ansible 2.4.1.0 e nessuno funziona fino ad altri due ed ecco i dettagli per riprodurre il caso.

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

E questo è il test 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

E questo è il risultato:

$ 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  

Sono disponibili due opzioni:

  • shell: /bin/bash -ic 'ta'
  • shell: ssh -tt localhost /bin/bash -ci 'ta' ma questo richiede l'inserimento della password in locale.

0

I miei 2 centesimi, ho circumnavigato il problema di sourcing ~/.nvm/nvm.shin ~/.profilee quindi utilizzando sudo -iucome suggerito in un'altra risposta.

Provato a gennaio 2018 contro 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    

-3

Il modo giusto dovrebbe essere:

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

Nota: è test in ansible 2.0.2versione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.