Неможливо отримати .bashrc за допомогою Ansible


85

Я можу ssh на віддалений хост і зробити source /home/username/.bashrc- все працює нормально. Однак якщо я це зроблю:

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

Я отримав:

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

Я не уявляю, що я роблю не так ...


sourceмає сенс лише тоді, коли ви запускаєте його всередині існуючої оболонки - він запускає команди в цій оболонці , і, отже, корисний / корисний лише тоді, коли існує існуюча оболонка, стан чи конфігурацію якої ви хочете змінити. Коли ви запускаєте дію ansible, це створює цілу нову оболонку і запускає команду всередині цієї оболонки - так ви не будете оновлювати змінні середовища в будь-якому іншому контексті, тому це насправді не матиме корисного / тривалого ефекту , навіть якщо у вас це працює без помилок.
Чарльз Даффі

@CharlesDuffy Якщо ви хочете виконати команду, яка очікує визначення змінних середовища, тоді спроба створити щось на зразок .bashrc або .bash_profile для дефініції таких змінних є правильним варіантом використання, чи не так?
htellez

@htellez, запуск sourceвизначає змінні лише протягом тривалості оболонки, в якій він працює . І ця оболонка вийшла (і змінні, які вона визначає, були втрачені) до моменту виходу команди ansible та запуску наступної.
Чарльз Даффі

@htellez, ... отже, тут єдина відповідь, яка насправді корисна будь-яким значущим чином, - це відповідь Стіва Мідглі , оскільки вона робить щось інше в тій самій оболонці, яка працювала sourceдо її виходу.
Чарльз Даффі

Це саме той випадок використання, який я намагався описати, вибачте, якщо я не зрозумів. Я спробував описати сценарій, в якому ви хочете запустити щось, що очікує визначеного конкретного середовища. Я дійшов до цього потоку, тому що маю ту саму помилку, і прочитавши відповідь Стіва , я зрозумів, що завдання оболонки ansible використовує sh за замовчуванням замість bash. Якщо зробити команду командою bash, явно робить sourceроботу так, як ви, швидше за все, звикли.
htellez

Відповіді:


88

У вас є два варіанти використання джерела з ansible. Один - за допомогою команди "shell:" та / bin / sh (за замовчуванням ansible). "джерело" називається "." в / bin / sh. Отже, ваша команда буде такою:

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

Зауважте, що вам потрібно запустити команду після пошуку .bashrc b / c, кожен сеанс ssh відрізняється - кожна команда ansible виконується в окремій транзакції ssh.

Вашим другим варіантом є примусити оболонку Ansible використовувати bash, а потім ви можете скористатися командою "source":

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

Нарешті, я зауважу, що вам може знадобитися створити джерело "/ etc / profile", якщо ви працюєте в Ubuntu або подібному, що більш повно імітує локальний логін.


3
Також зверніть увагу, що ця проблема була подана (і прокоментована мною) як запит на помилку / функцію в ядрі Ansible. Але Ansible закрив це і сказав "напишіть плагін". Бах. github.com/ansible/ansible/issues/4854
Стів Мідглі

1
Ти читаєш мої думки? Ви відповіли на це 3 місяці тому, і я думав це відредагувати .-> source- і ви відразу це зробили :)
warvariuc

Я спробував source "/etc/profile"- у мене не вийшло. Це спрацювало:source "~/.profile"
warvariuc

5
У мене є деякі функції bash, визначені всередині .bashrc та після пошуку .bashrc. як я можу виконувати / викликати ці функції? Я намагаюся , shell: . ~/.bashrc && nvm install {{ node_version }}і це говорить, nvm command not found. Як я можу це вирішити?
RaviTezu

1
@RaviTezu: Проблема в моєму випадку була пов’язана з такими рядками в .bashrc: # Якщо інтерактивний запуск не виконується, нічого не робіть $ - in i ) ;; *) повернення ;; esac Це принаймні проблема в ubuntu-16.04 xenial64, де .bashrc не запускається на неінтерактивних оболонках, що має місце при запуску команд через ssh. Щоб спробувати, встановіть трохи PATH у ~ / .bashrc і запустіть (припускаючи, що ви встановили порт 2222, переадресований на 22 на гостьовій ОС): ssh -p 2222 ubuntu@127.0.0.1 'echo $ PATH' Якщо вказана команда не працює ' t показати ШЛЯХ, який ви встановили в .bashrc, потім виправте .bashrc
Divick

24

Так commandбудуть запускатися лише виконувані файли. sourceсам по собі не є виконуваним файлом. (Це вбудована команда оболонки). Чи є якась причина, чому ви хочете sourceотримати повну змінну середовища?

Існують інші способи включення змінних середовища в Ansible. Наприклад, environmentдиректива:

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

Інший спосіб - використовувати shellмодуль Ansible:

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

або

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

У цих випадках екземпляр / середовище оболонки припиняється після запуску кроку Ansible.


2
майже добре, на жаль / bin / sh не має лише команди джерела. так shell source /home/username/.bashrcстаєshell . /home/username/.bashrc
b1r3k

Завдання оболонки приймає параметр як такий: executable=/usr/bin/bashякий потім буде запускати його в bash, якщо він доступний як такий.
fgysin відновив Моніку

16

Я знаю, що ця відповідь прийшла занадто пізно, але я бачив, що в достатній кількості коду ви можете використовувати опцію sudo -i так:

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

Як сказано в документації

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

Я стикався з цією ж проблемою, намагаючись змусити virtualenvwrapper працювати на сервері Ubuntu. Я використовував Ansible так:

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

але команда джерела не працювала.

Зрештою я виявив, що файл .bashrc має кілька рядків у верхній частині файлу, які заважають джерелу працювати, коли його викликає Ansible:

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

Я прокоментував ці рядки в .bashrc, і після цього все запрацювало як слід.


Це цілком розумно і є стандартним заголовком для більшості .bashrcфайлів. Ви, мабуть, хочете створити інший файл оболонки або використати його, BASH_ENVяк обговорювалося в документах bash.

2

Ну, я спробував перелічені відповіді, але вони не працювали для мене під час встановлення ruby ​​через rbenv . Мені довелося взяти джерело нижче рядків з/root/.bash_profile

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

Нарешті, я це придумав

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

Це можна використовувати з будь-якою командою.

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

1
Цей класичний підхід працює з Ansible 2.2.0.0. Однак мені це неприємно become, become_methodі become_userнатомість ... Я не міг зрозуміти комбінацію тих параметрів "методу", які б так чи інакше працювали.
Юрій

2

Я знайшов, що став найкращим рішенням:

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

Ви можете змінити користувача, додавши (за замовчуванням: root):

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

Більше інформації тут: Ansible become


2

Багато відповідей рекомендують джерело ~ / .bashrc, але головна проблема полягає в тому, що оболонка ansible не є інтерактивною, а реалізація ~ / .bashrc за замовчуванням ігнорує неінтерактивну оболонку (перевірте її початок).

Найкраще рішення для виконання команд як користувач після його ssh-інтерактивного входу, який я знайшов, це:

- 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' означає інтерактивну оболонку, тому .bashrc не буде ігноруватися '-l' означає оболонку входу, яка дає повний профіль користувача


0

Я спробував усі наведені вище варіанти з ansible 2.4.1.0, і ніхто не працює до наступних двох, і ось деталі для повторного створення справи.

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

І це тест ансиблі :

- 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

І ось результат:

$ 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  

Працювали два варіанти:

  • shell: /bin/bash -ic 'ta'
  • shell: ssh -tt localhost /bin/bash -ci 'ta' але для цього потрібно ввести пароль локально.

0

Мій 2 цента, я плавав проблему пошуку ~/.nvm/nvm.shв ~/.profileі потім використовувати , sudo -iuяк це пропонується в іншому відповідь.

Випробувано в січні 2018 року проти 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

Правильним шляхом має бути:

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

Примітка: це тест у ansible 2.0.2версії

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.