无法使用Ansible来源.bashrc


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动作时,它将创建一个全新的shell并在shell中运行命令-这样您就不会在任何其他上下文中更新环境变量,因此它实际上没有任何有用/持久的功效,即使您运行此程序也没有错误。
查尔斯·达菲

@CharlesDuffy如果您想执行一个期望定义环境变量的命令,则尝试使用.bashrc或.bash_profile之类的资源来定义此类变量是有效的用例,不是吗?
htellez

@htellez,source在其运行的shell持续时间内定义变量。并且在ansible命令退出并启动下一个命令时,该shell已退出(并且定义的变量已丢失)。
查尔斯·达菲

@htellez,...因此,这里唯一以任何有意义的方式实际上有用的答案是Steve Midgley的答案,因为它让您在source退出之前在同一运行的shell中执行了其他操作。
查尔斯·达菲

那正是我试图描述的用例,如果不清楚,对不起。我试图描述一种情况,在这种情况下,您需要运行需要定义特定环境的内容。我进入这个线程是因为我遇到了同样的错误,通过阅读史蒂夫的答案,我意识到ansible的shell任务默认情况下使用sh而不是bash。将命令设置为bash命令可以显式地使source您像以前那样工作。
htellez19年

Answers:


88

您可以通过两种方式将ansible与source一起使用。一种是使用“ shell:”命令和/ bin / sh(默认为ans)。“源”称为“”。在/ bin / sh中。因此,您的命令将是:

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

请注意,您必须在采购.bashrc b / c之后运行命令,每个ssh会话都是不同的-每个ansible命令都在单独的ssh事务中运行。

第二种选择是强制Ansible shell使用bash,然后可以使用“ source”命令:

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

最后,我要指出的是,如果您使用的是Ubuntu或类似版本,则可能希望实际获取“ / etc / profile”的源代码,而后者更完全地模拟了本地登录。


3
另请注意,此问题已作为Ansible核心中的错误/功能请求提交(并由我评论)。但是Ansible关闭了它并说“编写插件”。呸。github.com/ansible/ansible/issues/4854
Steve Midgley,

1
你在读我的想法吗?您在3个月前回答了这个问题,而我当时正想编辑它.-> source-,然后您立即进行了:)
warvariuc

我尝试过source "/etc/profile"-对我不起作用。这起作用了:source "~/.profile"
warvariuc

5
我在.bashrc内部和采购.bashrc之后定义了一些bash函数。如何执行/调用这些功能?我正在尝试shell: . ~/.bashrc && nvm install {{ node_version }},它是说nvm command not found。我该如何解决?
RaviTezu

1
@RaviTezu:我的问题是由于.bashrc中的以下几行引起的:#如果不是交互式运行,则不要在$情况下进行任何操作 i);; *)返回;esac这至少在ubuntu-16.04 xenial64上是一个问题,其中.bashrc不在非交互式shell上运行,这是通过ssh运行命令时的情况。要进行尝试,请在〜/ .bashrc中设置一些PATH并运行(假设您已将端口2222设置为在来宾os上转发到22):ssh -p 2222 ubuntu@127.0.0.1'echo $ PATH'如果以上命令没有执行, t显示您在.bashrc中设置的PATH,然后修复.bashrc
Divick

24

因此command只会运行可执行文件。 source本身不是可执行文件。(这是内置的shell命令)。有什么理由要source使用完整的环境变量?

还有其他方法可以在Ansible中包含环境变量。例如,environment指令:

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

另一种方法是使用shellAnsible模块:

- 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步骤,shell实例/环境将终止。


2
几乎不错,不幸的是/ bin / sh仅没有源命令。所以shell source /home/username/.bashrc变成shell . /home/username/.bashrc
b1r3k

shell任务采用这样的参数:executable=/usr/bin/bash如果可用,它将在bash中运行它。
fgysin恢复莫妮卡2015年

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

好吧,我尝试了列出的答案,但是通过rbenv安装ruby时,这些方法对我没有。我不得不从以下来源/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。然而,耿耿于怀,我应该使用becomebecome_methodbecome_user不是...我无法弄清楚这些“法” PARAMS这将反正工作的组合。
尤里(Yuri)2013年

2

我发现成为最好的解决方案:

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

您可以通过添加(默认值:root)来更改用户:

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

更多信息在这里:Ansible成为


2

许多响应建议使用源〜/ .bashrc,但主要问题是ansible shell不是交互式的,并且〜/ .bashrc实现默认情况下会忽略非交互式shell(检查其开始)。

我发现以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'";

这是Ansible测试

- 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年1月相对于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版本测试

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.