需求
搭建etcd集群,設置版本,發現ansible寫不了環境變量,所以查了一下。
結論
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調用playbook遠程mvn執行打包時發現執行出錯,找不到JAVA_HOME。
我們的exporter JAVA_HOME=/usr/java/jdk1.8.0寫在/etc/profile中,登錄時可以正常執行打包並打印JAVA_HOME。
排查過程
- 在playbook中執行echo $JAVA_HOME > /tmp/test.log,為空
- 在playbook中添加echo $PATH > /tmp/test.log,同時在遠端服務器登錄執行echo $PATH > /tmp/test.log,結果不同,ansible執行的要少很多路徑
- 在~/.bash_profile中添加環境變量,與/etc/profile 結果一致
- 考慮ansible執行的環境變量與登錄時使用的環境變量不同,所以將JAVA_HOME寫在/etc/bashrc中,再次測試echo $JAVA_HOME > /tmp/test.log,正常打印
至此,確定ansible執行過程中並未調用/etc/profile和~/.bash_profile
原因
login shell 和 non-login shell
查閱相關文檔,以及咨詢大佬后,得出如下結果。
- 我們登錄執行的是login shell,會加載/etc/profile,~/.bash_profile
ansible這類ssh遠程執行是non-login shell,不會加載etc/profile,~/.bash_profile,而是加載etc/bashrc和~/.bashrc
首先了解一下login shell 與 non-login shell
《鳥哥的Linux私房菜基礎學習篇》里這樣描述/etc/profile及/etc/bashrc的區別:
- login shell:取得bash時需要完整的登入流程的,就稱為login shell。舉例來說,你要由tty1~tty6登入,需要輸入用戶的賬號和密碼,此時取得的bash就稱為『login shell』啰;
- non-login shell:取得bash接口的方法不需要重復登入的舉動,舉例來說,
- (1)你以Xwindow登入Linux后,再以X的圖形化接口啟動終端機,此時那個終端接口並沒有需要再次的輸入賬號和密碼,那個bash的環境就稱為non-login shell了。
- (2)你在原本的bash環境下再次下達bash這個命令,同樣的也沒有輸入賬號密碼,那第二個bash (子程序)也是non-login shell 。
我們查看~/.bash_profile,發現里面有這樣一段內容:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
當~/.bashrc存在時,login shell 會引入~/.bashrc的環境變量
我們再看~/.bashrc,發現一段類似的內容:
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
當/etc/bashrc存在時,login shell會引入/etc/bashrc內的環境變量
也就是說:
- login shell加載環境變量的順序是:
① /etc/profile ② ~/.bash_profile ③ ~/.bashrc ④ /etc/bashrc
- 而non-login shell加載環境變量的順序是:
① ~/.bashrc ② /etc/bashrc