在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.”
- 首先我們設置become爲True,表示遠程執行需要進行用戶切換。如果是用命令則加上
--become
選項(或-b
) - 設置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 ]
- 設置become_user爲當前task/play要求的遠程主機上的用戶,命令選項爲
--become-user
- 達成我們的目標最重要的一點來了:設置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_USER
爲False
,且登錄用戶和become_user相同,則become操作會被跳過,所以得把它改成True。
以上方法基於Ansible 2.7在目標系統Linux上測試有效,各類Unix應該也是有效的(偷懶了沒有測,只要su命令的選項定義相同其實並沒有區別)
另外,如果become_method不想用su,sudo也是可以的,只不過become_flags需要設置爲-i
,想用什麼命令查詢一下手冊就好了