Không thể tìm nguồn .bashrc bằng Ansible


85

Tôi có thể chuyển đến máy chủ từ xa và thực hiện source /home/username/.bashrc- mọi thứ hoạt động tốt. Tuy nhiên nếu tôi làm:

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

Tôi có:

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

Tôi không biết mình đang làm gì sai ...


sourcechỉ có ý nghĩa khi bạn chạy nó bên trong một trình bao hiện có - nó chạy các lệnh trong trình bao đó và do đó chỉ hữu ích / hữu ích khi có một trình bao hiện có có trạng thái hoặc cấu hình bạn muốn thay đổi. Khi bạn chạy một hành động ansible, hành động đó sẽ tạo ra một trình bao hoàn toàn mới và chạy một lệnh bên trong trình bao đó - vì vậy bạn sẽ không cập nhật các biến môi trường trong bất kỳ ngữ cảnh nào khác, vì vậy nó sẽ không thực sự có bất kỳ hiệu quả hữu ích / lâu dài , ngay cả khi bạn có cái này để chạy mà không có lỗi.
Charles Duffy

@CharlesDuffy Nếu bạn muốn thực thi một lệnh yêu cầu các biến môi trường được xác định thì việc cố gắng tìm nguồn như .bashrc hoặc .bash_profile để xác định các biến như vậy có phải là một trường hợp sử dụng hợp lệ không?
htellez

@htellez, chạy sourcechỉ xác định các biến trong thời gian của trình bao mà nó chạy trong đó . Và trình bao đó đã thoát (và các biến mà nó xác định đã bị mất) vào thời điểm lệnh ansible thoát ra và lệnh tiếp theo bắt đầu.
Charles Duffy

@htellez, ... do đó, câu trả lời duy nhất ở đây thực sự hữu ích theo bất kỳ cách nào có ý nghĩa là câu trả lời của Steve Midgley , vì nó cho phép bạn làm điều gì đó khác trong cùng một trình bao đã chạy source, trước khi nó thoát ra.
Charles Duffy

Đó chính xác là trường hợp sử dụng mà tôi đã cố gắng mô tả, tôi xin lỗi nếu tôi không rõ. Tôi đã cố gắng mô tả một kịch bản trong đó bạn muốn chạy thứ gì đó mà mong đợi một môi trường cụ thể được xác định. Tôi đến chủ đề này vì tôi gặp phải lỗi tương tự và khi đọc câu trả lời của Steve , tôi nhận ra rằng tác vụ shell của ansible sử dụng sh theo mặc định thay vì bash. Việc đặt lệnh trở thành lệnh bash rõ ràng làm cho sourcecông việc theo cách bạn thường làm.
htellez

Câu trả lời:


88

Bạn có hai tùy chọn để sử dụng nguồn có thể trả được. Một là với lệnh "shell:" và / bin / sh (mặc định không thể trả lời). "nguồn" được gọi là "." trong / bin / sh. Vì vậy, lệnh của bạn sẽ là:

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

Lưu ý rằng bạn phải chạy một lệnh sau khi tìm nguồn .bashrc b / c mỗi phiên ssh là khác biệt - mọi lệnh ansible chạy trong một giao dịch ssh riêng biệt.

Tùy chọn thứ hai của bạn là buộc Ansible shell sử dụng bash và sau đó bạn có thể sử dụng lệnh "source":

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

Cuối cùng, tôi sẽ lưu ý rằng bạn có thể thực sự muốn nguồn "/ etc / profile" nếu bạn đang sử dụng Ubuntu hoặc tương tự, mô phỏng hoàn toàn hơn một đăng nhập cục bộ.


3
Cũng lưu ý rằng vấn đề này đã được gửi (và được tôi nhận xét) như một yêu cầu về lỗi / tính năng trong lõi Ansible. Nhưng Ansible đã đóng nó lại và nói "viết một plugin." Bah. github.com/ansible/ansible/issues/4854
Steve Midgley

1
Bạn đang đọc suy nghĩ của tôi? Bạn đã trả lời này 3 bướm đêm trước, và tôi đã suy nghĩ để chỉnh sửa này .-> source- và bạn ngay lập tức đã làm :) này
warvariuc

Tôi đã thử source "/etc/profile"- nó không hiệu quả với tôi. Điều này đã hoạt động:source "~/.profile"
warvariuc

5
Tôi có một số hàm bash được định nghĩa bên trong .bashrc và sau khi tìm nguồn .bashrc. làm cách nào để thực thi / gọi các hàm đó? Tôi đang cố gắng shell: . ~/.bashrc && nvm install {{ node_version }}và nó đang nói nvm command not found,. Làm sao tôi có thể giải quyết việc này?
RaviTezu

1
@RaviTezu: Vấn đề trong trường hợp của tôi là do các dòng sau trong .bashrc: # Nếu không chạy tương tác, đừng làm gì cả $ - in i ) ;; *) trở về;; esac Đây ít nhất là một vấn đề trên ubuntu-16.04 xenial64 trong đó .bashrc không chạy trên shell không tương tác, đây là trường hợp khi chạy lệnh qua ssh. Để dùng thử, hãy đặt một số PATH trong ~ / .bashrc và chạy (giả sử bạn đã đặt cổng 2222 được chuyển tiếp thành 22 trên hệ điều hành khách): ssh -p 2222 ubuntu@127.0.0.1 'echo $ PATH' Nếu lệnh trên không ' t hiển thị PATH bạn đã đặt trong .bashrc sau đó sửa .bashrc
Divick

24

Vì vậy, commandsẽ chỉ chạy các tệp thực thi. sourceper se không phải là một tệp thực thi. (Đó là một lệnh shell nội trang). Có lý do gì khiến bạn muốn sourcemột biến môi trường đầy đủ không?

Có nhiều cách khác để đưa các biến môi trường vào Ansible. Ví dụ, environmentchỉ thị:

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

Một cách khác là sử dụng shellmô-đun Ansible:

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

hoặc là

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

Trong những trường hợp này, cá thể / môi trường shell sẽ kết thúc khi bước Ansible được chạy.


2
gần như tốt, tiếc là / bin / sh không có chỉ lệnh nguồn. so shell source /home/username/.bashrctrở thànhshell . /home/username/.bashrc
b1r3k

Tác vụ shell nhận một tham số như vậy: executable=/usr/bin/bashsau đó sẽ chạy nó trong bash nếu nó có sẵn như vậy.
fgysin Khôi phục Monica

16

Tôi biết câu trả lời này đến quá muộn nhưng tôi đã thấy đủ mã bạn có thể sử dụng tùy chọn sudo -i để:

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

Như đã nói trong tài liệu

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

Tôi đã gặp sự cố tương tự này khi cố gắng khiến virtualenvwrapper hoạt động trên máy chủ Ubuntu. Tôi đã sử dụng Ansible như thế này:

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

nhưng lệnh nguồn không hoạt động.

Cuối cùng tôi phát hiện ra rằng tệp .bashrc có một vài dòng ở đầu tệp ngăn nguồn hoạt động khi được gọi bởi Ansible:

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

Tôi đã nhận xét những dòng đó trong .bashrc và mọi thứ hoạt động như mong đợi sau đó.


Đó là tiêu đề hoàn toàn hợp lý và tiêu chuẩn cho hầu hết .bashrccác tệp. Bạn có thể muốn tạo nguồn một tệp shell khác hoặc sử dụng BASH_ENVnhư đã thảo luận trong tài liệu bash.

2

Tôi đã thử các câu trả lời được liệt kê nhưng những câu đó không hiệu quả với tôi khi cài đặt ruby ​​thông qua rbenv . Tôi đã phải dẫn nguồn dưới đây từ/root/.bash_profile

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

Cuối cùng, tôi đã nghĩ ra điều này

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

Người ta có thể sử dụng điều này với bất kỳ lệnh nào.

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

1
Cách tiếp cận cổ điển này hoạt động với Ansible 2.2.0.0. Tuy nhiên, nó nài nỉ rằng tôi nên sử dụng become, become_methodbecome_userthay vào đó ... tôi không thể tìm ra sự kết hợp của các tham số "phương thức" đó sẽ hoạt động như thế nào.
Yuri

2

Tôi thấy trở thành giải pháp tốt nhất:

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

Bạn có thể thay đổi người dùng bằng cách thêm (mặc định: root):

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

Thông tin thêm tại đây: Ansible trở thành


2

Nhiều phản hồi khuyên bạn nên sử dụng mã nguồn ~ / .bashrc nhưng vấn đề chính là trình bao ansible không tương tác và việc triển khai ~ / .bashrc theo mặc định bỏ qua trình bao không tương tác (kiểm tra phần đầu của nó).

Giải pháp tốt nhất để thực hiện các lệnh với tư cách người dùng sau khi đăng nhập tương tác ssh mà tôi tìm thấy là:

- 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' có nghĩa là trình bao tương tác, vì vậy .bashrc sẽ không bị bỏ qua '-l' có nghĩa là trình bao đăng nhập nguồn hồ sơ người dùng đầy đủ


0

Tôi đã thử tất cả các tùy chọn ở trên với ansible 2.4.1.0 và không ai hoạt động cho đến khi có hai tùy chọn khác và đây là chi tiết để sản xuất lại trường hợp.

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

Và đây là bài kiểm tra có thể nghe được :

- 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

Và đây là kết quả:

$ 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  

Có hai tùy chọn đã hoạt động:

  • shell: /bin/bash -ic 'ta'
  • shell: ssh -tt localhost /bin/bash -ci 'ta' nhưng cái này yêu cầu nhập mật khẩu cục bộ.

0

My 2 cents, tôi đi vòng quanh vấn đề nguồn ~/.nvm/nvm.shvào ~/.profilevà sau đó sử dụng sudo -iunhư đề xuất trong câu trả lời khác.

Đã thử vào tháng 1 năm 2018 so với 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

Cách đúng phải là:

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

Lưu ý: nó đang thử nghiệm trong ansible 2.0.2phiên bản

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.