Невозможно получить .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имеет смысл только тогда, когда вы запускаете его внутри существующей оболочки - он запускает команды в этой оболочке и, таким образом, полезен только тогда, когда есть существующая оболочка, состояние или конфигурацию которой вы хотите изменить. Когда вы запускаете доступное действие, которое создает совершенно новую оболочку и запускает команду внутри этой оболочки - поэтому вы не будете обновлять переменные среды в любом другом контексте, поэтому на самом деле это не будет иметь никакого полезного / длительного эффекта. , даже если вам удалось это запустить без ошибок.
Чарльз Даффи

@CharlesDuffy Если вы хотите выполнить команду, которая ожидает определения переменных среды, то попытка получить что-то вроде .bashrc или .bash_profile для определения таких переменных является допустимым вариантом использования, не так ли?
htellez

@htellez, running sourceопределяет переменные только на время работы оболочки, в которой он работает . И эта оболочка завершилась (и переменные, которые она определяет, были потеряны) к моменту выхода команды ansible и запуска следующей.
Чарльз Даффи

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

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

Ответы:


88

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

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

Обратите внимание, что вы должны запустить команду после получения .bashrc b / c, каждый сеанс ssh отличается - каждая доступная команда выполняется в отдельной транзакции 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: # Если не работает в интерактивном режиме, ничего не делайте case $ - в 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 05

Задача оболочки принимает параметр как таковой: 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 стать


2

Многие ответы рекомендуют использовать источник ~ / .bashrc, но основная проблема заключается в том, что доступная оболочка не является интерактивной, а реализация ~ / .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.