bash啟動時載入配置文件過程

来源:http://www.cnblogs.com/f-ck-need-u/archive/2017/08/23/7417651.html
-Advertisement-
Play Games

本文目錄: 1.1 判斷是否互動式、是否登錄式 1.2 幾種常見的bash啟動方式 1.3 載入bash環境配置文件 當用戶登錄系統時,會載入各種bash配置文件,還會設置或清空一系列變數,有時還會執行一些自定義的命令。這些行為都算是啟動bash時的過程。 另外,有些時候登錄系統是可以交互的(如正常 ...



本文目錄:

1.1 判斷是否互動式、是否登錄式

1.2 幾種常見的bash啟動方式

1.3 載入bash環境配置文件


當用戶登錄系統時,會載入各種bash配置文件,還會設置或清空一系列變數,有時還會執行一些自定義的命令。這些行為都算是啟動bash時的過程。

另外,有些時候登錄系統是可以交互的(如正常登錄系統),有些時候是無交互的(如執行一個腳本),因此總的來說bash啟動類型可分為互動式shell和非互動式shell。更細分一層,互動式shell還分為互動式的登錄shell和互動式非登錄shell,非交互的shell在某些時候可以在bash命令後帶上"--login"或短選項"-l",這時也算是登錄式,即非交互的登錄式shell。

1.1 判斷是否互動式、是否登錄式

判斷是否為互動式shell有兩種簡單的方法:

方法一:判斷變數"-",如果值中含有字母"i",表示互動式。

[root@xuexi ~]# echo $-
himBH

[root@xuexi ~]# vim a.sh
#!/bin/bash
echo $-

[root@xuexi ~]# bash a.sh
hB

方法二:判斷變數PS1,如果值非空,則為互動式,否則為非互動式,因為非互動式會清空該變數。

[root@xuexi ~]# echo $PS1
[\u@\h \W]\$

判斷是否為登錄式的方法也很簡單,只需執行"shopt login"即可。值為"on"表示為登錄式,否則為非登錄式。

[root@xuexi ~]# shopt login_shell  
login_shell     on
[root@xuexi ~]# bash

[root@xuexi ~]# shopt login_shell
login_shell     off

所以,要判斷是互動式以及登錄式的情況,可簡單使用如下命令:

echo $PS1;shopt login_shell
或者
echo $-;shopt login_shell

1.2 幾種常見的bash啟動方式

(1).正常登錄(偽終端登錄如ssh登錄,或虛擬終端登錄)時,為互動式登錄shell。

[root@xuexi ~]# echo $PS1;shopt login_shell 
[\u@\h \W]\$
login_shell     on

(2).su命令,不帶"--login"時為互動式、非登錄式shell,帶有"--login"時,為互動式、登錄式shell。

[root@xuexi ~]# su root

[root@xuexi ~]# echo $PS1;shopt login_shell 
[\u@\h \W]\$
login_shell     off
[root@xuexi ~]# su -
Last login: Sat Aug 19 13:24:11 CST 2017 on pts/0

[root@xuexi ~]# echo $PS1;shopt login_shell
[\u@\h \W]\$
login_shell     on

(3).執行不帶"--login"選項的bash命令時為互動式、非登錄式shell。但指定"--login"時,為互動式、登錄式shell。

[root@xuexi ~]# bash

[root@xuexi ~]# echo $PS1;shopt login_shell
[\u@\h \W]\$
login_shell     off
[root@xuexi ~]# bash -l

[root@xuexi ~]# echo $PS1;shopt login_shell
[\u@\h \W]\$
login_shell     on

(4).使用命令組合(使用括弧包圍命令列表)以及命令替換進入子shell時,繼承父shell的交互和登錄屬性。

[root@xuexi ~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell)
1
[\u@\h \W]\$
login_shell     on
[root@xuexi ~]# su

[root@xuexi ~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell)
1
[\u@\h \W]\$
login_shell     off

(5).ssh執行遠程命令,但不登錄時,為非交互、非登錄式。

[root@xuexi ~]# ssh localhost 'echo $PS1;shopt login_shell'
 
login_shell     off

(6).執行shell腳本時,為非交互、非登錄式shell。但指定了"--login"時,將為非交互、登錄式shell。

例如,腳本內容如下:

[root@xuexi ~]# vim b.sh
#!/bin/bash
echo $PS1
shopt login_shell

不帶"--login"選項時,為非交互、非登錄式shell。

[root@xuexi ~]# bash b.sh
 
login_shell     off

帶"--login"選項時,為非交互、登錄式shell。

[root@xuexi ~]# bash -l b.sh
 
login_shell     on

(7).在圖形界面下打開終端時,為互動式、非登錄式shell。

 

但可以設置為使用互動式、登錄式shell。

 

1.3 載入bash環境配置文件

無論是否交互、是否登錄,bash總要配置其運行環境。bash環境配置主要通過載入bash環境配置文件來完成。但是否交互、是否登錄將會影響載入哪些配置文件,除了交互、登錄屬性,有些特殊的屬性也會影響讀取配置文件的方法。

bash環境配置文件主要有/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc和/etc/profile.d/*.sh,為了測試各種情形讀取哪些配置文件,先分別向這幾個配置文件中寫入幾個echo語句,用以判斷該配置文件是否在啟動bash時被讀取載入了。

echo "echo '/etc/profile goes'" >>/etc/_profile
echo "echo '~/.bash_profile goes'" >>~/.bash_profile
echo "echo '~/.bashrc goes'" >>~/.bashrc
echo "echo '/etc/bashrc goes'" >>/etc/bashrc
echo "echo '/etc/profile.d/test.sh goes'" >>/etc/profile.d/test.sh
chmod +x /etc/profile.d/test.sh

①.互動式登錄shell或非互動式但帶有"--login"(或短選項"-l",例如在shell腳本中指定"#!/bin/bash -l"時)的bash啟動時,將先讀取/etc/profile,再依次搜索~/.bash_profile、~/.bash_login和~/.profile,並僅載入第一個搜索到且可讀的文件。當退出時,將執行~/.bash_logout中的命令。

但要註意,在/etc/profile中有一條載入/etc/profile.d/*.sh的語句,它會使用source載入/etc/profile.d/下所有可執行的sh尾碼的腳本。

[root@xuexi ~]# grep -A 8 \*\.sh /etc/profile  
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

內層if語句中的【"${-#*i}" != "$-"】表示將"$-"從左向右模式匹配"*i"並將匹配到的內容刪除(即進行變數切分),如果"$-"切分後的值不等於"$-",則意味著是互動式shell,於是怎樣怎樣,否則怎樣怎樣。

同樣的,在~/.bash_profile中也一樣有載入~/.bashrc的命令。

[root@xuexi ~]# grep -A 1 \~/\.bashrc ~/.bash_profile
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

而~/.bashrc中又有載入/etc/bashrc的命令。

[root@xuexi ~]# grep -A 1 /etc/bashrc ~/.bashrc
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

其實/etc/bashrc中還有載入/etc/profile.d/*.sh的語句,但前提是非登錄式shell時才會執行。以下是部分語句:

if ! shopt -q login_shell ; then   # We're not a login shell
...
    for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            if [ "$PS1" ]; then
                . "$i"
            else
                . "$i" >/dev/null 2>&1
            fi
        fi
    done
...
fi

從內層if語句和/etc/profile中對應的判斷語句的作用是一致的,只不過判斷方式不同,寫法不同。

因此,互動式的登錄shell載入bash環境配置文件的實際過程如下圖:

 

以下結果驗證了結論:

Last login: Mon Aug 14 04:49:29 2017     # 新開終端登錄時
/etc/profile.d/*.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
 [root@xuexi ~]# ssh localhost        # ssh遠程登錄時
root@localhost's password:
Last login: Mon Aug 14 05:05:50 2017 from 172.16.10.1
/etc/profile.d/*.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
[root@xuexi ~]# bash -l        # 執行帶有"--login"選項的login時
/etc/profile.d/*.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
[root@xuexi ~]# su -          # su帶上"--login"/etc/profile.d/*.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
[root@xuexi ~]# vim a.sh    # 執行shell腳本時帶有"--login"#!/bin/bash -l
echo haha

[root@xuexi ~]# ./a.sh 
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
haha

之所以執行shell腳本時沒有顯示執行/etc/profile.d/*.sh,是因為它是非互動式的,根據/etc/profile中的【if [ "${-#*i}" != "$-" ]】判斷,它將會把/etc/profile.d/*.sh的執行結果重定向到/dev/null中。也就是說,即使是shell腳本(帶"--login "選項),它也載入了所有bash環境配置文件。

②.互動式非登錄shell的bash啟動時,將讀取~/.bashrc,不會讀取/etc/profile和~/.bash_profile、~/.bash_login和~/.profile。

因此,互動式非登錄shell載入bash環境配置文件的實際過程為下圖內方框中所示:

例如,執行不帶"--login"的bash命令或su命令時。

[root@xuexi ~]# bash
/etc/profile.d/*.sh goes
/etc/bashrc goes
~/.bashrc goes
[root@xuexi ~]# su
/etc/profile.d/*.sh goes
/etc/bashrc goes
~/.bashrc goes

③.非互動式、非登錄式shell啟動bash時,不會載入前面所說的任何bash環境配置文件,但會搜索變數BASH_ENV,如果搜索到了,則載入其所指定的文件。但有並非所有非互動式、非登錄式shell啟動時都會如此,見情況④。

它就像是這樣的語句:

if [ -n "$BASH_ENV" ];then
    . "$BASH_ENV"
fi

幾乎執行所有的shell腳本都不會特意帶上"--login"選項,因此shell腳本不會載入任何bash環境配置文件,除非手動配置了變數BASH_ENV。

④.遠程shell方式啟動的bash,它雖然屬於非交互、非登錄式,但會載入~/.bashrc,所以還會載入/etc/bashrc,由於是非登錄式,所以最終還會載入/etc/profile.d/*.sh,只不過因為是非互動式而使得執行的結果全部重定向到了/dev/null中。

如果瞭解rsync,就知道它有一種遠程shell連接方式。所謂的遠程shell方式,是指通過網路的方式啟動bash並將bash的標準輸出關聯起來,就像它連接了一個遠程的shell守護進程一樣。一般由sshd實現這樣的連接方式,老版的rshd也一樣支持。

事實也確實如此,使用ssh連接但不登錄遠程主機時(例如只為了執行遠程命令),就是遠程shell的方式,但它卻是非交互、非登錄式的shell。

[root@xuexi ~]# ssh localhost echo haha
root@localhost's password:
/etc/bashrc goes
~/.bashrc goes
haha

正如上文所說,它同樣載入了/etc/profile.d/*.sh,只不過/etc/bashrc中的if判斷語句【if [ "$PS1" ]; then】使得非互動式的shell要將執行結果重定向到/dev/null中。

 

回到系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html

轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/7417651.html

註:若您覺得這篇文章還不錯請點擊下右下角的推薦,有了您的支持才能激發作者更大的寫作熱情,非常感謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 分析前準備 # 進入工作目錄 cd example_PE250 上一節回顧:我們的OTU獲得了物種註釋,並學習OTU表的各種操作————添加信息,格式轉換,篩選信息。 接下來我們學習對OTU序列的進化分析、同時計算Alpha和Beta多樣性值。 16. 進化樹構建 進化樹是基於多序列比對的結果,可展 ...
  • 本節課程,需要先完成《擴增子分析解讀》系列之前的操作 1質控 實驗設計 雙端序列合併 2提取barcode 質控及樣品拆分 切除擴增引物 3格式轉換 去冗餘 聚類 4去嵌合體 非細菌序列 生成代表性序列和OTU表 分析前準備 # 進入工作目錄 cd example_PE250 上一節回顧:我們學習了 ...
  • 1.1 shell解析命令行 shell讀取和執行命令時的大致操作過程如下圖: 以執行以下命令為例: echo -e "some files:" ~/i* "\nThe date:$(date +%F)\n$name's age is $((a+4))" >/tmp/a.log 假設在執行該命令前, ...
  • 本文介紹nf_conntrack故障導致的一些問題時,我們應該如何處理。 ...
  • 一. 啟動流程 BIOS --> MBR(Boot Code) --> 引導程式(GRUB) --> 載入內核 --> 執行Init --> runlevel 二. 內容詳解 BIOS: Basic Input Output System , 基本輸入輸出系統 ,負責檢查硬體,查找啟動設備, 可啟動 ...
  • 1 #導入IIS管理模塊 2 Import-Module WebAdministration 3 4 5 #新建應用程式池 api.dd.com 6 New-Item iis:\AppPools\api.dd.com 7 Set-ItemProperty iis:\AppPools\api.dd.c ...
  • 最近根據項目需要寫了一段power shell的代碼 ,主要功能是批量重啟IIS 具體的 Power shell 服務如下: write-output 'Restarting IIS servers ................ ' $servers= 'server1' ,'Server2' ...
  • 為什麼這樣的 JSON會解析失敗? 為什麼界面上韓文顯示亂碼? ASCII和ANSI有什麼區別? 帶著這些問題查看了網上的很多資料,整理出了下麵的文章。本文只是從程式員的角度說一說自己對字元編碼的理解,所以有點地方淺嘗輒止,說的並不深入。 1. ASCII及其擴展 1.1 什麼是ASCII字元集 字 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...