Es ist nicht möglich, .bashrc mit Ansible zu beschaffen


85

Ich kann ssh zum Remote-Host und mache ein source /home/username/.bashrc- alles funktioniert gut. Wenn ich es jedoch tue:

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

Ich bekomme:

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

Ich habe keine Ahnung, was ich falsch mache ...


sourceDies ist nur dann sinnvoll, wenn Sie es in einer vorhandenen Shell ausführen. Es führt Befehle in dieser Shell aus und ist daher nur dann nützlich / hilfreich, wenn eine vorhandene Shell vorhanden ist, deren Status oder Konfiguration Sie ändern möchten. Wenn Sie eine ansible-Aktion ausführen, wird eine ganz neue Shell erstellt und ein Befehl in dieser Shell ausgeführt. Sie würden also die Umgebungsvariablen in keinem anderen Kontext aktualisieren, sodass sie keinen nützlichen / dauerhaften Effekt hätte , auch wenn Sie dies ohne Fehler laufen lassen.
Charles Duffy

@CharlesDuffy Wenn Sie einen Befehl ausführen möchten, der die Definition von Umgebungsvariablen erwartet, ist der Versuch, so etwas wie .bashrc oder .bash_profile als Quelle für solche Variablen zu verwenden, ein gültiger Anwendungsfall, oder?
Htellez

@htellez, running sourcedefiniert nur Variablen für die Dauer der Shell, in der es ausgeführt wird . Und diese Shell ist beendet (und die von ihr definierten Variablen sind verloren gegangen), als der ansible-Befehl beendet wird und der nächste startet.
Charles Duffy

@htellez, ... daher ist die einzige Antwort, die hier tatsächlich in irgendeiner sinnvollen Weise nützlich ist, die von Steve Midgley , da Sie etwas anderes in derselben Shell tun müssen, die ausgeführt wurde source, bevor sie beendet wurde.
Charles Duffy

Das ist genau der Anwendungsfall, den ich beschreiben wollte. Es tut mir leid, wenn ich nicht klar war. Ich habe versucht, ein Szenario zu beschreiben, in dem Sie etwas ausführen möchten, das eine bestimmte definierte Umgebung erwartet. Ich bin zu diesem Thread gekommen, weil ich den gleichen Fehler habe, und als ich Steves Antwort gelesen habe , habe ich festgestellt, dass die Shell-Aufgabe des Ansible standardmäßig sh anstelle von bash verwendet. Wenn Sie den Befehl explizit zu einem Bash-Befehl machen, sourcefunktioniert dies wie gewohnt.
Htellez

Antworten:


88

Sie haben zwei Möglichkeiten, die Quelle mit ansible zu verwenden. Eine davon ist der Befehl "shell:" und / bin / sh (die ansible Standardeinstellung). "Quelle" heißt "." in / bin / sh. Ihr Befehl wäre also:

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

Beachten Sie, dass Sie nach der Beschaffung von .bashrc b / c einen Befehl ausführen müssen. Jede SSH-Sitzung ist unterschiedlich. Jeder ansible-Befehl wird in einer separaten SSH-Transaktion ausgeführt.

Ihre zweite Option besteht darin, die Ansible-Shell zur Verwendung von bash zu zwingen. Anschließend können Sie den Befehl "source" verwenden:

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

Abschließend möchte ich darauf hinweisen, dass Sie möglicherweise "/ etc / profile" als Quelle verwenden möchten, wenn Sie Ubuntu oder ähnliches verwenden, wodurch eine lokale Anmeldung vollständiger simuliert wird.


3
Beachten Sie auch, dass dieses Problem als Fehler- / Funktionsanforderung in Ansible Core abgelegt (und von mir kommentiert) wurde. Aber Ansible schloss es und sagte "schreibe ein Plugin." Bah. github.com/ansible/ansible/issues/4854
Steve Midgley

1
Lesen Sie meine Gedanken? Sie haben dies vor 3 .source
Monaten

Ich habe es versucht source "/etc/profile"- es hat bei mir nicht funktioniert. Dies funktionierte:source "~/.profile"
Warvariuc

5
Ich habe einige Bash-Funktionen in .bashrc und nach der Beschaffung von .bashrc definiert. Wie kann ich diese Funktionen ausführen / aufrufen? Ich versuche es shell: . ~/.bashrc && nvm install {{ node_version }}und es heißt , nvm command not found. Wie kann ich das lösen?
RaviTezu

1
@ RaviTezu: Das Problem in meinem Fall war auf die folgenden Zeilen in .bashrc zurückzuführen: # Wenn Sie nicht interaktiv ausgeführt werden, tun Sie nichts, wenn $ - in i ) ;; *) Rückkehr;; esac Dies ist zumindest ein Problem unter ubuntu-16.04 xenial64, wo .bashrc nicht auf nicht interaktiven Shells ausgeführt wird, was beim Ausführen von Befehlen über ssh der Fall ist. Um es auszuprobieren, setzen Sie PATH in ~ / .bashrc und führen Sie es aus (vorausgesetzt, Sie haben Port 2222 auf Gast-OS an 22 weitergeleitet): ssh -p 2222 ubuntu@127.0.0.1 'echo $ PATH' Wenn der obige Befehl dies nicht tut ' t zeigen Sie den Pfad, den Sie in .bashrc eingestellt haben, und korrigieren Sie dann .bashrc
Divick

24

Es commandwerden also nur ausführbare Dateien ausgeführt. sourceper se ist keine ausführbare Datei. (Es ist ein eingebauter Shell-Befehl). Gibt es einen Grund, warum Sie sourceeine vollständige Umgebungsvariable verwenden möchten ?

Es gibt andere Möglichkeiten, Umgebungsvariablen in Ansible aufzunehmen. Zum Beispiel die environmentRichtlinie:

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

Eine andere Möglichkeit ist die Verwendung des shellAnsible-Moduls:

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

oder

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

In diesen Fällen wird die Shell-Instanz / -Umgebung beendet, sobald der Ansible-Schritt ausgeführt wird.


2
fast gut, leider hat / bin / sh nicht nur Quellbefehl. so shell source /home/username/.bashrcwirdshell . /home/username/.bashrc
b1r3k

Die Shell-Task verwendet einen Parameter als solchen, executable=/usr/bin/bashder ihn dann in bash ausführt, wenn er als solcher verfügbar ist.
Fgysin wieder Monica

16

Ich weiß, dass diese Antwort zu spät kommt, aber ich habe in genügend Code gesehen, dass Sie die sudo-Option verwenden können, -i also:

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

Wie in der Dokumentation gesagt

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

Ich hatte das gleiche Problem, als ich versuchte, virtualenvwrapper auf einem Ubuntu-Server zum Laufen zu bringen. Ich habe Ansible folgendermaßen verwendet:

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

aber der Quellbefehl funktionierte nicht.

Schließlich stellte ich fest, dass die .bashrc-Datei oben in der Datei einige Zeilen enthält, die verhindern, dass die Quelle funktioniert, wenn sie von Ansible aufgerufen wird:

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

Ich habe diese Zeilen in .bashrc auskommentiert und danach hat alles wie erwartet funktioniert.


Das ist völlig vernünftig und Standard-Header für die meisten .bashrcDateien. Sie möchten wahrscheinlich eine andere Shell-Datei BASH_ENVals Quelle verwenden oder wie in den Bash-Dokumenten beschrieben verwenden.

2

Nun, ich habe die aufgelisteten Antworten ausprobiert, aber diese haben bei der Installation von Ruby über rbenv nicht funktioniert . Ich musste unter Zeilen von beziehen/root/.bash_profile

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

Schließlich habe ich mir das ausgedacht

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

Man kann dies mit jedem Befehl verwenden.

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

1
Dieser klassische Ansatz funktioniert mit Ansible 2.2.0.0. Es ist jedoch ein Nörgelei, das ich verwenden sollte become, become_methodund become_userstattdessen ... konnte ich keine Kombination dieser "Methoden" -Parameter herausfinden, die sowieso funktionieren würden.
Yuri

2

Ich fand als beste Lösung geworden:

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

Sie können den Benutzer ändern, indem Sie Folgendes hinzufügen (Standard: root):

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

Mehr Infos hier: Ansible werden


2

In vielen Antworten wird empfohlen, ~ / .bashrc als Quelle zu verwenden. Das Hauptproblem besteht jedoch darin, dass die Ansible-Shell nicht interaktiv ist und die Implementierung von ~ / .bashrc standardmäßig nicht interaktive Shell ignoriert (überprüfen Sie den Anfang).

Die beste Lösung für die Ausführung von Befehlen als Benutzer nach der interaktiven Anmeldung von ssh, die ich gefunden habe, ist:

- 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' bedeutet interaktive Shell, daher wird .bashrc nicht ignoriert. '-l' bedeutet Login-Shell, die das vollständige Benutzerprofil erstellt


0

Ich habe alle oben genannten Optionen mit ansible 2.4.1.0 ausprobiert und niemand arbeitet bis zwei weitere und hier ist das Detail, um den Fall wieder herzustellen.

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

Und das ist der ansible Test :

- 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

Und das ist das Ergebnis:

$ 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  

Es gibt zwei Möglichkeiten:

  • shell: /bin/bash -ic 'ta'
  • shell: ssh -tt localhost /bin/bash -ci 'ta' Dieser erfordert jedoch die lokale Passworteingabe.

0

My 2 cents, umsegelte ich das Problem der Beschaffung ~/.nvm/nvm.shin ~/.profileund dann unter Verwendung von sudo -iuwie in einer anderen Antwort vorgeschlagen.

Versucht am Januar 2018 gegen 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

Der richtige Weg sollte sein:

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

Hinweis: Es ist ein Test in der ansible 2.0.2Version

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.