Nie można pobrać pliku .bashrc z Ansible


85

Mogę ssh do zdalnego hosta i zrobić source /home/username/.bashrc- wszystko działa dobrze. Jednak jeśli to zrobię:

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

Dostaję:

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

Nie mam pojęcia, co robię źle ...


sourcema sens tylko wtedy, gdy uruchamiasz go w istniejącej powłoce - uruchamia polecenia w tej powłoce , a zatem jest przydatny / pomocny tylko wtedy, gdy istnieje istniejąca powłoka, której stan lub konfigurację chcesz zmienić. Kiedy uruchamiasz akcję ansible, która tworzy zupełnie nową powłokę i uruchamia polecenie wewnątrz tej powłoki - więc nie aktualizowałbyś zmiennych środowiskowych w żadnym innym kontekście, więc nie miałoby to żadnego użytecznego / trwałego efektu , nawet jeśli masz to do działania bez błędów.
Charles Duffy

@CharlesDuffy Jeśli chcesz wykonać polecenie, które oczekuje, że zmienne środowiskowe zostaną zdefiniowane, spróbuj pobrać coś takiego jak .bashrc lub .bash_profile w celu wyeliminowania takich zmiennych, czy to nie jest prawidłowy przypadek użycia?
htellez

@htellez, uruchomienie sourcedefiniuje zmienne tylko na czas trwania powłoki, w której działa . Ta powłoka zakończyła pracę (a zdefiniowane przez nią zmienne zostały utracone) do czasu zakończenia polecenia ansibl i rozpoczęcia następnej.
Charles Duffy

@htellez, ... tak więc jedyną odpowiedzią, która jest faktycznie użyteczna w jakikolwiek znaczący sposób, jest odpowiedź Steve'a Midgleya , ponieważ wymaga ona zrobienia czegoś innego w tej samej powłoce, która została uruchomiona source, zanim zakończyła pracę.
Charles Duffy

To jest dokładnie ten przypadek użycia, który próbowałem opisać, przepraszam, jeśli nie byłem jasny. Próbowałem opisać scenariusz, w którym chcesz uruchomić coś, co wymaga zdefiniowania określonego środowiska. Dotarłem do tego wątku, ponieważ pojawia się ten sam błąd, a czytając odpowiedź Steve'a , zdałem sobie sprawę, że zadanie powłoki ansible domyślnie używa sh zamiast bash. Uczynienie z polecenia polecenia bash jawnie sprawia, że sourcepraca jest taka, do jakiej prawdopodobnie jesteś przyzwyczajony.
htellez

Odpowiedzi:


88

Masz dwie możliwości używania źródła z ansible. Jeden jest z poleceniem "shell:" i / bin / sh (domyślne ustawienie ansible). „źródło” nosi nazwę „”. w / bin / sh. Więc twoje polecenie byłoby następujące:

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

Zauważ, że musisz uruchomić polecenie po uzyskaniu .bashrc b / c każda sesja ssh jest inna - każde polecenie ansible działa w oddzielnej transakcji ssh.

Drugą opcją jest zmuszenie powłoki Ansible do korzystania z bash, a następnie możesz użyć polecenia „source”:

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

Na koniec zauważę, że możesz chcieć faktycznie pobrać plik „/ etc / profile”, jeśli używasz systemu Ubuntu lub podobnego, co w pełni symuluje logowanie lokalne.


3
Zwróć również uwagę, że ten problem został zgłoszony (i skomentowany przeze mnie) jako zgłoszenie błędu / funkcji w rdzeniu Ansible. Ale Ansible zamknął go i powiedział „napisz wtyczkę”. Bah. github.com/ansible/ansible/issues/4854
Steve Midgley

1
Czytasz w moich myślach? Odpowiedziałeś na to 3 miesiące temu, a ja myślałem o edycji tego .-> source- i od razu to zrobiłeś :)
warvariuc

Próbowałem source "/etc/profile"- to mi się nie udało. To zadziałało:source "~/.profile"
warvariuc

5
Mam kilka funkcji basha zdefiniowanych w .bashrc i po pobraniu .bashrc. jak mogę wykonać / wywołać te funkcje? Staram shell: . ~/.bashrc && nvm install {{ node_version }}i to mówiąc nvm command not found. Jak mogę to rozwiązać?
RaviTezu

1
@RaviTezu: Problem w moim przypadku był spowodowany następującymi wierszami w .bashrc: # Jeśli nie działa interaktywnie, nie rób nic case $ - in i ) ;; *) powrót;; esac Jest to przynajmniej problem na ubuntu-16.04 xenial64, gdzie .bashrc nie jest uruchamiany na nieinteraktywnych powłokach, co ma miejsce w przypadku uruchamiania poleceń przez ssh. Aby to wypróbować, ustaw jakąś PATH w ~ / .bashrc i uruchom (zakładając, że ustawiłeś port 2222 przekierowany na 22 na systemie gościa): ssh -p 2222 ubuntu@127.0.0.1 'echo $ PATH' Jeśli powyższe polecenie nie działa ' t pokaż
ŚCIEŻKĘ

24

Więc commandbędzie uruchamiać tylko pliki wykonywalne. sourceper se nie jest plikiem wykonywalnym. (To wbudowana komenda powłoki). Czy jest jakiś powód, dla którego chcesz sourcemieć pełną zmienną środowiskową?

Istnieją inne sposoby dołączania zmiennych środowiskowych do Ansible. Na przykład environmentdyrektywa:

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

Innym sposobem jest użycie shellmodułu Ansible:

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

lub

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

W takich przypadkach instancja / środowisko powłoki zostanie zakończone po uruchomieniu kroku Ansible.


2
prawie dobrze, niestety / bin / sh nie ma tylko polecenia źródła. tak shell source /home/username/.bashrcsię stanieshell . /home/username/.bashrc
b1r3k

Zadanie powłoki przyjmuje parametr jako taki: executable=/usr/bin/bashktóry następnie uruchomi je w bash, jeśli jest dostępny jako taki.
fgysin przywraca Monikę

16

Wiem, że ta odpowiedź nadeszła za późno, ale widziałem wystarczająco dużo kodu, że możesz użyć opcji sudo, -i więc:

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

Jak wspomniano w dokumentacji

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

Miałem ten sam problem, gdy próbowałem uruchomić virtualenvwrapper na serwerze Ubuntu. Używałem Ansible w ten sposób:

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

ale polecenie źródła nie działało.

W końcu odkryłem, że plik .bashrc ma kilka wierszy na górze pliku, które uniemożliwiają działanie źródła po wywołaniu przez Ansible:

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

Skomentowałem te linie w .bashrc i po tym wszystko działało zgodnie z oczekiwaniami.


To całkiem rozsądny i standardowy nagłówek dla większości .bashrcplików. Prawdopodobnie chcesz pobrać inny plik powłoki lub użyć go BASH_ENVzgodnie z opisem w dokumentacji bash.

2

Cóż, wypróbowałem wymienione odpowiedzi, ale te nie zadziałały podczas instalowania Ruby przez rbenv . Musiałem znaleźć poniżej linii z/root/.bash_profile

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

W końcu to wymyśliłem

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

Można tego użyć z każdym poleceniem.

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

1
To klasyczne podejście działa z Ansible 2.2.0.0. Jednak szkodzi, że powinienem użyć become, become_methoda become_userzamiast tego ... Nie mogłem wymyślić kombinacji tych parametrów „metody”, które i tak by działały.
Jurij

2

Znalazłem najlepsze rozwiązanie:

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

Możesz zmienić użytkownika dodając (domyślnie: root):

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

Więcej informacji tutaj: Ansible staje się


2

Wiele odpowiedzi poleca source ~ / .bashrc, ale głównym problemem jest to, że powłoka ansible nie jest interaktywna, a implementacja ~ / .bashrc domyślnie ignoruje powłokę nieinteraktywną (sprawdź jej początek).

Najlepszym rozwiązaniem do wykonywania poleceń jako użytkownik po jego interaktywnym logowaniu przez ssh, które znalazłem, jest:

- 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” oznacza powłokę interaktywną, więc .bashrc nie będzie ignorowane „-l” oznacza powłokę logowania, która pobiera pełny profil użytkownika


0

Wypróbowałem wszystkie powyższe opcje z ansiblem 2.4.1.0 i nikt nie działa do następnych dwóch, a oto szczegóły ponownego odtworzenia sprawy.

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

A to jest test ansibli :

- 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

A oto wynik:

$ 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  

Dostępne są dwie opcje:

  • shell: /bin/bash -ic 'ta'
  • shell: ssh -tt localhost /bin/bash -ci 'ta' ale ten wymaga wprowadzenia hasła lokalnie.

0

Moje 2 centy, i obejście problemu zaopatrzenia ~/.nvm/nvm.shw ~/.profilea następnie przy użyciu sudo -iujak zasugerowano w innej odpowiedzi.

Próbowano w styczniu 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    

-3

Właściwy sposób powinien być:

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

Uwaga: jest to test w ansible 2.0.2wersji

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.