ubuntu下關於profile和bashrc中環境變數的理解

来源:http://www.cnblogs.com/liaohuiqiang/archive/2017/07/18/7197581.html
-Advertisement-
Play Games

大致理順了一下ubuntu整個環境變數的“流通過程”,如有錯誤,歡迎指正。 ...


(0) 寫在前面

有些名詞可能需要解釋一下。(也可以先不看這一節,在後面看到有疑惑再上來看相關解釋)

$PS1和互動式運行(running interactively): 簡單地來說,互動式運行就是在終端上輸入指令運行,非互動式運行就是執行sh文件。互動式運行的時候echo $PS1會輸出一長串字元,非互動式運行echo $PS1會輸出#或$,,$代表普通用戶,#代表root。非互動式運行是不會執行bashrc文件的配置內容的,這點需要註意一下,因為平常都在終端上執行指令,很容易忽略這一點:在bashrc中配置的東西,在執行sh文件的時候就失效了。

啟動bash shell:就是啟動一個bash shell進程,通常可以理解為打開一個終端。需要註意的是如果你在終端輸入sh後會發現自己又進入另一個shell命令行(註意這不是互動式運行,可以echo $PS1驗證),這個時候其實fork了一個shell 子進程(會複製一份原終端shell進程的全局變數),如果你在這個shell命令行又輸入了一次sh,那麼相當於fork的shell子進程又fork了一個shell子進程,這個時候就啟動了三個bash shell進程。

輸入exit或者ctrl-d可以退出當前shell,這裡需要連續exit兩次才可以回到原來的終端shell進程(這個時候就變回一個shell進程了)。

source profile或source bashrc:source一個sh文件,就是把sh文件的內容載入到本shell環境中執行。可以理解為:執行sh是非互動式運行;在終端source sh文件,相當於在終端執行sh文件的指令,就是互動式運行了。

 

(1) profile和bashrc

配置環境變數一般在這兩種文件中。先講講什麼時候執行,後面再介紹這兩種文件做了什麼。

profile在系統登錄後執行,只在登錄系統時執行一次,包括針對系統的/etc/profile針對用戶的~/.profile。

bashrc在每次啟動bash shell(打開終端或者在終端輸入sh)後執行,包括針對系統的/etc/bash.bashrc針對用戶的~/.bashrc(這裡註意一下我的ubuntu里是/etc/bash.bashrc,其它系統可能是/etc/bashrc)

cat /etc/profile
cat /etc/bash.bashrc
cat ~/.profile
cat ~/.bashrc

 

(2) 環境變數

因為要配置環境變數,所以要對環境變數有所瞭解。shell中的環境變數分為全局變數和局部變數。

blogger="piligrimHui"  這樣定義的為局部變數
export blogger="pilgrimHui" 這樣定義的為全局變數(export這個變數,則升級為全局變數)

 

2.1 局部變數:父進程定義的局部變數,子進程無法訪問;子進程定義的局部變數,父進程無法訪問。

# parent.sh
#!/bin/bash

pid="parent"
sh child.sh
echo "父shell訪問子shell的cid:$cid"
# child.sh
#!/bin/bash

echo "子shell訪問父shell的pid:$pid"
cid="child"
sh parent.sh

子shell訪問父shell的pid:
父shell訪問子shell的cid:

 

2.2 全局變數:父shell定義的全局變數,子shell自身會複製一份父shell的全局變數,所以子shell對全局變數的操作不影響父shell的全局變數。子shell定義的全局變數,父shell不可用。

# parent.sh
#!/bin/bash

export name="parent"
echo "父shell的name:$name"
sh child.sh
echo "子shell修改name之後,父shell的name:$name"
echo "父shell訪問子shell定義的nickName:$nickName"
# child.sh
#!/bin/bash

echo "子shell的name:$name"
name="child"
echo "子shell修改name後,子shell的name:$name"
nickName="baby"
sh parent.sh

父shell的name:parent
子shell的name:parent
子shell修改name後,子shell的name:child
子shell修改name之後,父shell的name:parent
父shell訪問子shell定義的nickName:

 

(3) profile做了什麼

登錄shell隨著用戶的登錄而啟動,可以看作是第一個shell,後續的shell都是登錄shell的子shell。

登錄shell會執行針對系統的/etc/profile針對用戶的~/.profile。為了讓環境變數在後續的所有shell都能訪問到,可以在這裡配置全局的環境變數,但是註意profile只會在登錄的時候執行一次,所以一般配置完後需要重新登錄才能生效。(雖然可以自行source profile但是只在當前shell進程有效,這裡的shell進程可以理解為在一個終端里,但是如果在終端里輸入sh其實相當於開了兩個shell進程,一個父進程一個子進程)

對於/etc/profile,首先會檢查是否互動式運行(即$PS1不為空),如果不是則給PS1賦’#‘或'$','#'代表root用戶,'$'代表普通用戶。如果是互動式運行還要是否啟動了bash shell,如果是則執行/etc/bash.bashrc對bash進行相關配置。然後會執行/etc/profile.d目錄下的shell文件,有一些作為自啟動程式,有些用來定義一些全局環境變數。

對於~/.profile,首先檢查是否啟動了bash shell,如果是則執行~/.bashrc對bash進行相關配置。然後重新設置了PATH(所以導致不同用戶的環境變數PATH不一樣)。

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "$PS1" ]; then
  if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin directories
PATH="$HOME/bin:$HOME/.local/bin:$PATH"

 

(4) bashrc做了什麼

當啟動bash shell(打開終端)的時候會執行/etc/bash.bashrc和~/.bashrc。

在執行/etc/profile和~/.profile時如果檢查到bash shell執行的話(對於/etc/profile還要先檢查是否互動式運行),也會執行這兩個文件。

我們來看看這兩個bashrc做了什麼

對於/etc/bash.bashrc:首先檢查是否互動式運行,不是就什麼都不做。是的話,後面是一堆亂七八糟的操作。

對於~/.bashrc:首先檢查是否互動式運行,不是就什麼都不做。是的話,後面一堆亂七八糟的操作,其中有一些別名操作,我們平常用的ll就是在這裡設置了,是ls -alF的別名。

因為每次啟動shell進程這裡都會執行,所以一般也可以在這後面配置環境變數。

最常見的配置方法是vim ~/.bashrc然後在最後幾行加上環境變數的配置,然後source ~/.bashrc或者重啟終端即可。

# System-wide .bashrc file for interactive bash(1) shells.

# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

...
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

...

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

 

(5) 寫在後面

最後說一下,各個linux系統下的profile文件和bashrc文件都有所不同,我用的是ubuntu16.04,其它系統可能有所不同,可以自己看裡面的shell代碼進行理解和實踐驗證。

此次總結大致理順了一下整個環境變數的“流通過程”,理解這個過程之後思路應該清晰了很多,如有錯誤,歡迎指正。


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

-Advertisement-
Play Games
更多相關文章
  • `React Native iOS RN`是使用腳本語言編寫的,實現了“解釋執行”的方式,而這種執行方式的修改只需替換腳步即可,不需要重新發佈程式,熱更新的方式極大的方便了迭代開發。 今天我們選擇的熱更新組件是 ,這是國內開發的,功能類似 (`CodePush Pushy`支持增量更新,最大化的降低 ...
  • Redis是一個Key Value資料庫。Redis有5種數據類型:字元串、列表、哈希、集合、有序集合。而字元串的底層實現方法之一就是使用sds。以下描述中請讀者註意區分sds是指簡單動態字元串這一數據結構(用大寫表示)還是sdshdr頭部中buf數組的起始地址(用小寫表示)。 SDS源碼 如下源碼 ...
  • SQL圖書管理系 0.表設計 b_user_information 列名 數據類型 約束 auto_number bigint(20) auto_increment user_id varchar(20) not null unique key user_name varchar(50) not n ...
  • 市面上有一些初學者的誤解,他們拿spark和hadoop比較時就會說,Spark是記憶體計算,記憶體計算是spark的特性。請問在電腦領域,mysql,redis,ssh框架等等他們不是記憶體計算嗎?依據馮諾依曼體繫結構,有什麼技術的程式不是在記憶體中運行,需要數據從硬碟中拉取,然後供cpu進行執行?所有 ...
  • sync是Linux系統下的文件同步和數據傳輸工具,可用於同步文件、代碼發佈 1.安裝. yum install -y xinetd yum insatll -y rsync 2.配置 打開rsync功能vim /etc/xinetd.d/rsync uid = nobody #目錄或文件的屬主屬組 ...
  • 1、Makefile偽目標的格式: 2、Makefile偽目標的作用: 第一種情況: 如果我們需要書寫這樣的一個規則:規則所定義的命令不是去創建目標文件,而是通過make命令行明確指定它來執行一些特點的命令,就像例題中的clean。當文件夾中沒有clean這個文件的時候,我們輸入“make clea ...
  • 菜鳥的linux上手之路,由於最近要學習python,得有點linux的基本知識,所以......把這玩意兒裝上了到底該怎麼玩啊! 設置Ubuntu Nat連接: 1. 在虛擬機端輸入 如果進程列表裡有/user/sbin/sshd -D,則表明SSH守護進程已經啟動。 如果沒有該進程,需要手動安裝 ...
  • zookeeper安裝 單機模式 首先,下載zookeeper-3.4.8.tar.gz 創建/usr/zookeeper,解壓到zookeeper目錄 [root@localhost zookeeper]# tar -zxvf zookeeper-3.4.8.tar.gz 配置環境變數: 為了今後 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...