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


(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) 其它

echo $PATH # 查看環境變量PATH

 

(6) 寫在后面

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

此次總結大致理順了一下整個環境變量的“流通過程”,理解這個過程之后思路應該清晰了很多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM