文章目錄
SSH遠程執行腳本報錯command not found和環境變量問題
SSH遠程執行腳本報錯
SSH遠程執行腳本報錯"command not found",且環境變量不生效,執行env
命令後發現打印出來的環境變量少了很多。
原因是之前將環境變量配置在了/etc/profile
中,但是SSH遠程執行腳本時實際上執行的是non-login shell,而non-login shell不會讀取/etc/profile
配置文件。
login shell和non-login shell
簡單來說,用SSH客戶端(比如Putty)登陸Linux系統時,要求輸入用戶名/密碼登錄或根據SSH key登錄時,就是login shell。
而在A機器上再用SSH免密碼登錄B機器,在B機器上執行Shell腳本,就是non-login shell。
ssh -o StrictHostKeyChecking=no -l root ${server} "~/test.sh"
用Ansible在目標機器上遠程執行Shell腳本時,也是non-login shell,因爲Ansible是基於SSH的。
Linux的環境配置文件
運行man bash
可以查看環境配置文件的說明:
CentOS 7上的示例:
/etc/profile
The systemwide initialization file, executed for login shells
/etc/bash.bash_logout
The systemwide login shell cleanup file, executed when a login shell exits
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
~/.inputrc
Individual readline initialization file
補充說明:
Classically,
~/.profile
is used by Bourne Shell, and is probably supported by Bash as a legacy measure. Again,~/.login
and~/.cshrc
were used by C Shell - I’m not sure that Bash uses them at all.The
~/.bash_profile
would be used once, at login. The~/.bashrc
script is read every time a shell is started. This is analogous to/.cshrc
for C Shell.One consequence is that stuff in
~/.bashrc
should be as lightweight (minimal) as possible to reduce the overhead when starting a non-login shell.I believe the
~/.environment
file is a compatibility file for Korn Shell.
小結:
-
/etc
下的是系統環境配置,對所有用戶有效,但是/etc/profile
只對login shell有效,而/etc/bashrc
對login shell和non-login shell都有效。 -
~
下的是當前用戶環境配置,當前用戶環境配置會繼承·/etc
系統環境配置。
login shell和non-login shell讀取的環境變量配置文件
login-shell讀取環境變量配置文件:
-
/etc/profile
-
~/.bash_profile
-
~/.profile
-
~/.bashrc
-
/etc/bashrc
注意:~/.bash_profile
中已經引入了~/.bashrc
,而~/.bashrc
引入了/etc/bashrc
,因此login shell可以讀取到~/.bashrc
和/etc/bashrc
的配置。
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
non-login shell讀取環境變量配置文件:
/etc/bashrc
~/.bashrc
解決non-login shell的環境配置問題
方法一:
將login-shell和non-login shell都需要的環境配置放在~/.bashrc
中,其它配置放在~/.bash_profile
中。
方法二:
如果環境配置只放在~/.bash_profile
中,需要執行non-login shell時先source ~/.bash_profile
再執行命令。
Linux Shell Sebang的注意事項
雖然大多數情況下,在Shell開頭用#!/usr/bin/env bash
比#!/bin/bash
更有通用性,但是在通過SSH遠程執行Shell腳本時,Shell開頭要用#!/bin/bash
。
參考文檔
- https://unix.stackexchange.com/questions/38175/difference-between-login-shell-and-non-login-shell
- https://stackoverflow.com/questions/415403/whats-the-difference-between-bashrc-bash-profile-and-environment
- https://www.thegeekstuff.com/2008/10/execution-sequence-for-bash_profile-bashrc-bash_login-profile-and-bash_logout/
- 關於ansible遠程執行的環境變量問題(login shell & nonlogin shelll)
- ssh連接遠程主機執行腳本的環境變量問題