解决Ansible远程执行无法加载环境变量的问题

在18年冬天的一篇关于编写Action Plugin的文章中讨论过关于Ansible远程执行无法加载环境变量的问题(Ansible开发实战: 基于command模块的Oracle Listener控制模块(附趟雷过程及样例))其中引用了 huangwjwork的一篇文章关于ansible远程执行的环境变量问题(login shell & nonlogin shelll)。这篇文章讨论了login shell和nonlogin shell的区别,在此再次引用其结论:

ansible这类远程执行的non-login shell 并不会加载/etc/profile和/.bash_profile下的环境变量,只是加载/.bashrc和/etc/bashrc
如果需要在ansible中执行需要特定环境变量的命令,可以在执行前source一下~/.bash_profile, 或者将环境变量写在~/.bashrc
————————————————
版权声明:本文为CSDN博主「huangwjwork」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010871982/article/details/78525367

事实上我们还可以使用其他的手段来使Ansible远程执行的会话加载环境变量,原理说穿了不值一文钱:既然nonlogin shell不加载全部的环境变量,那么我们就再开启一个login shell好了~这种方法的好处是既不用对目标环境进行修改(移动环境变量),也不用笨拙地显式加载bash_profile了,只是充分利用ansible以及目标环境提供给我们的功能。

我们知道,Ansible提供了become以及其他一些相关的选项来提供远程执行过程中进行用户切换的功能,它们分别是:

  • become: Boolean that controls if privilege escalation is used or not on :term:Task execution.

  • become_flags: A string of flag(s) to pass to the privilege escalation program when :term:become is True.

  • become_method: Which method of privilege escalation to use (such as sudo or su).

  • become_user: “User that you ‘become’ after using privilege escalation. The remote/login user must have permissions to become this
    user.”

  1. 首先我们设置become为True,表示远程执行需要进行用户切换。如果是用命令则加上--become选项(或-b
  2. 设置become_method为su(默认是sudo,本文以su举例),命令选项是--become-method

–become-method=BECOME_METHOD
privilege escalation method to use (default=sudo),
valid choices: [ sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl ]

  1. 设置become_user为当前task/play要求的远程主机上的用户,命令选项为--become-user
  2. 达成我们的目标最重要的一点来了:设置become_flags为--l。这两者是等效的,或者说--l的一种简写,意为切换用户后开启的是login shell。让我们看一下su命令的手册中是怎么描述的:
   -, -l, --login
          Starts the shell as login shell with an environment similar to a real login:

上文中become_flags的说明中讲了,become_flags是传递给become_method的选项的列表。所以设置become_flag为--l相当于远程执行su - [remoteuser] -c 'blablabla...',即以remoteuser用户身份开启login shell来执行你需要执行的命令,自然就可以加载环境变量了。

但是,此处有个但是——你会惊奇地发现你无法使用命令选项设置become_flags的值……这也是个人十分无法理解ansible的设计的一点,既然其他的become相关参数都可以通过命令选项设置,为啥单单这个不可以?只能通过修改Ansible的配置文件、增加环境变量或在playbook中定义become_flags来设置。
我们来看看base.yml:

DEFAULT_BECOME_FLAGS:
  name: Set 'become' executable options
  default: ''
  description: Flags to pass to the privilege escalation executable.
  env: [{name: ANSIBLE_BECOME_FLAGS}]
  ini:
  - {key: become_flags, section: privilege_escalation}

我们可以修改base.yml,将DEFAULT_BECOME_FLAGS的默认值设置为--l,也可以给执行ansible命令的用户添加环境变量ANSIBLE_BECOME_FLAGS,或者干脆在playbook中指定become_flags

还有人说了,如果我登录的用户就是我希望用来执行命令的用户呢?这个其实没关系,该切换还切换,无非是自己切换到自己,毕竟我们的目标是开启一个login shell而已。不过这里涉及到ansible的另外一个配置:

BECOME_ALLOW_SAME_USER:
  name: Allow becoming the same user
  default: False
  description: This setting controls if become is skipped when remote user and become user are the same. I.E root sudo to root.
  env: [{name: ANSIBLE_BECOME_ALLOW_SAME_USER}]
  ini:
  - {key: become_allow_same_user, section: privilege_escalation}
  type: boolean
  yaml: {key: privilege_escalation.become_allow_same_user}

如果BECOME_ALLOW_SAME_USERFalse,且登录用户和become_user相同,则become操作会被跳过,所以得把它改成True。

以上方法基于Ansible 2.7在目标系统Linux上测试有效,各类Unix应该也是有效的(偷懒了没有测,只要su命令的选项定义相同其实并没有区别)

另外,如果become_method不想用su,sudo也是可以的,只不过become_flags需要设置为-i,想用什么命令查询一下手册就好了

你可能感兴趣的:(Ansible)