登陆shell和非登陆shell区别
定义
1 登陆shell
login shell 通过输入用户名和密码后取得的shell
输入echo $0后显示“-bash”
2 非登陆shell
non-login shell 指没有通过输入用户名和密码得到的shell
输入echo $0 后显示“bash”
登陆shell
读取的文件
首先,登陆shell首先会读取/etc/profile文件,这个文件通常会调用/etc/sysconfig/i18n来设置终端的语言信息,调用/etc/inputrc来设置终端的输入方式,还会调用/etc/profile.d/目录下的脚本文件。
其次,系统会读取用户家目录下的.bash_profile、.bash_login、.profile这三个文件。一般来说,系统只执行这三个文件中的一个。如果这些文件中存在~/.bashrc,那么在登录时,系统会读取这个文件。
因此,当用户登录shell时,主要会读取/etc/profile和~/.bashrc这两个配置文件。
读取文件顺序
非登陆shell
读取的文件
非登陆shell不会读取/etc/profile 文件
无论是登陆shell还是非登陆shell,/etc/bashrc是重要文件。
读取文件顺序
配置文件
/etc/profile
与bash有关代码
1 for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
2 if [ -r "$i" ]; then
3 if [ "${-#*i}" != "$-" ]; then
4 . "$i"
5 else
6 . "$i" >/dev/null
7 fi
8 fi
9 done
.....
10 if [ -n "${BASH_VERSION-}" ] ; then
11 if [ -f /etc/bashrc ] ; then
# Bash login shells run only /etc/profile
# Bash non-login shells run only /etc/bashrc
# Check for double sourcing is done in /etc/bashrc.
12 . /etc/bashrc
13 fi
14 fi
代码详解
第一部分
- 第一行:遍历/etc/profile.d/目录下所有以.sh结尾的文件和/etc/profile.d/sh.local文件,并赋值给i
- 第二行:判断i所代表的文件是否存在并且可读
- 第三行:检查shell选项标志是否包含i。
${-#*i}
会从$-
的开头开始删除最长的与模式*i
匹配的子字符串,如果结果不是$-
,则说明当前的shell选项标志包含“i” - 第四行:i指向的脚本存在并且可读,执行i所指向的脚本
- 第六行:否则执行脚本,丢弃输出
总的来说,这段脚本会遍历/etc/profile.d/
目录下的所有以.sh
结尾的文和/etc/profile.d/sh.local
文件,并根据当前的shell选项标志决定是否执行这些脚本。如果shell选项标志包含“i”,则脚本会直接执行;否则,脚本的输出会被丢弃。这通常用于系统启动时自动加载一系列配置脚本
第二部分
- 第十行:判断BASH_VERSION变量是否被设置,被设置执行11行
- 第十一行:文件/etc/bashrc是否存在,存在执行12行
- 第十二行:执行/etc/bashrc文件
作用:主要用于bash shell的环境初始化。在登录shell中,通常会运行/etc/profile
来进行全局的环境变量设置。而在非登录shell中,通常会运行~/.bashrc
来设置用户级别的环境变量。这段代码的作用就是在非登录shell中避免重复加载和运行/etc/bashrc
。
补充
1、bash的-i选项表示强制shell以交互方式运行
2、$-:表示当前shell的选项标志
3、${#}:模式匹配截断,不改变原变量,
用法:${var#pattern},在var中查找给定的模式pattern,把 var 中的内容去掉左边最短的匹配模式。
示例:var=testcase; echo ${var#*s}
输出 tcase
4、if [ ]条件判断
-r:文件是否存在并且可读
-n:变量长度,非零返回true
-f:文件存在返回true
/etc/profile.d/*.sh文件
/etc/bashrc
bash的主要配置文件,主要设置如下内容:
-
终端显示bash提示符样式
-
打开并行历史记录功能
-
将当前的历史记录写入到历史文件中
-
根据终端窗口变化自动调整bash窗口
-
在非登录shell中设置环境变量和权限掩码,并执行一些初始化脚本。
-
计算OMP_NUM_THREADS的值
代码
1 if [ -z "$BASHRCSOURCED" ]; then
2 BASHRCSOURCED="Y"
# are we an interactive shell?
3 if [ "$PS1" ]; then
4 if [ -z "$PROMPT_COMMAND" ]; then
5 case $TERM in
6 xterm*|vte*)
7 if [ -e /etc/sysconfig/bash-prompt-xterm ]; then
8 PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm
9 else
10 PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
11 fi
12 ;;
13 screen*)
14 if [ -e /etc/sysconfig/bash-prompt-screen ]; then
15 PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen
16 else
17 PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
18 fi
19 ;;
20 *)
21 [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default
22 ;;
esac
23 fi
# Turn on parallel history
24 shopt -s histappend
25 history -a
# Turn on checkwinsize
26 shopt -s checkwinsize
27 [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
# You might want to have e.g. tty in prompt (e.g. more virtual machines)
# and console windows
# If you want to do so, just add e.g.
# if [ "$PS1" ]; then
# PS1="[\u@\h:\l \W]\\$ "
# fi
# to your custom modification shell script in /etc/profile.d/ directory
28 fi
29 if ! shopt -q login_shell ; then # We're not a login shell
# Need to redefine pathmunge, it gets undefined at the end of /etc/profile
30 pathmunge () {
31 case ":${PATH}:" in
32 *:"$1":*)
33 ;;
34 *)
35 if [ "$2" = "after" ] ; then
36 PATH=$PATH:$1
37 else
38 PATH=$1:$PATH
39 fi
40 esac
41 }
# By default, we want umask to get set. This sets it for non-login shell.
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
42 if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
43 umask 002
44 else
45 umask 022
46 fi
47 SHELL=/bin/bash
# Only display echos from profile.d scripts if we are no login shell
# and interactive - otherwise just process them to set envvars
48 for i in /etc/profile.d/*.sh; do
49 if [ -r "$i" ]; then
50 if [ "$PS1" ]; then
51 . "$i"
52 else
53 . "$i" >/dev/null
54 fi
55 fi
56 done
57 unset i
58 unset -f pathmunge
59 fi
60 fi
# vim:ts=4:sw=4
61 if [ -n "$(lscpu | grep 'Cluster(s):')" ]; then
NewLANG=`echo $LANG` &&
LANG=en_US.UTF-8 &&
NewLANGUAGE=`echo $LANGUAGE` &&
LANGUAGE=en_US &&
export OMP_NUM_THREADS=$[ `lscpu | grep "Cluster(s):" | awk -F": " '{print $2}'` * `lscpu | grep "Core(s) per cluster:" | awk -F": " '{print $2}'` * `lscpu | grep "Thread(s) per core:" | awk -F": " '{print $2}'`] &&
LANG=`echo $NewLANG` &&
unset NewLANG &&
unset $NewLANG &&
LANGUAGE=`echo $NewLANGUAGE` &&
unset NewLANGUAGE &&
unset $NewLANGUAGE;
else
NewLANG=`echo $LANG` &&
LANG=en_US.UTF-8 &&
NewLANGUAGE=`echo $LANGUAGE` &&
LANGUAGE=en_US &&
export OMP_NUM_THREADS=$[ `lscpu | grep "Socket(s):" | awk -F": " '{print $2}'` * `lscpu | grep "Core(s) per socket:" | awk -F ": " '{print $2}'` * `lscpu | grep "Thread(s) per core:" | awk -F": " '{print $2}'`] &&
LANG=`echo $NewLANG` &&
unset NewLANG &&
unset $NewLANG &&
LANGUAGE=`echo $NewLANGUAGE` &&
unset NewLANGUAGE &&
unset $NewLANGUAGE ;
fi
代码详解
第一部分
-
行1~2:判断BASHRCSOURCED变量是否存在,不存在,将BASHRCSOURCED值设置为true。如果存在,则1~60行则不会被执行。
-
行4:这个条件判断检查
$PROMPT_COMMAND
是否为空。$PROMPT_COMMAND
用于定义在bash提示符显示之前执行的命令。 -
行5~22:根据不同的终端类型,设置不同的提示符
-
6~12:
xterm*|vte*
:如果终端类型是xterm或vte,则检查是否存在/etc/sysconfig/bash-prompt-xterm
文件,如果存在,则将其设置为PROMPT_COMMAND
,否则使用一个自定义的printf命令来设置提示符。KaTeX parse error: Undefined control sequence: \0 at position 92: …AND的值为:printf "\̲0̲33]0;%s@%s:%s\0…{USER}" “KaTeX parse error: Expected '}', got 'EOF' at end of input: …OSTNAME%%.*}" "{PWD/#$HOME/~}”
-
**printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"含义**
- \033:转义字符,代表ESC键
- ]0:用于设置终端的标题。
- %s@%s:%s:这是要显示在终端标题中的文本。
- ${USER}:这是一个环境变量,代表当前登录用户的用户名。
- ${HOSTNAME%%.*}:这是一个bash命令,用于提取主机名(不包括域名部分)。
- ${PWD/#$HOME/\~}:这是一个bash命令,用于将当前工作目录的路径替换为家目录的简写(`~`)。
综合起来,这个命令将当前用户的用户名、主机名(不包括域名部分)和当前工作目录的路径组合成一个字符串,并将其设置为终端的标题。例如,如果用户名为"john",主机名为"myhost",当前目录为"/home/john/Documents",则终端标题将被设置为"[john@myhost:/home/john/Documents]"。
-
13~19:
screen*
:如果终端类型是screen,则检查是否存在/etc/sysconfig/bash-prompt-screen
文件,如果存在,则将其设置为PROMPT_COMMAND
,否则使用一个自定义的printf命令来设置提示符。 -
20~22:
*
:对于其他类型的终端,检查是否存在/etc/sysconfig/bash-prompt-default
文件,如果存在,则将其设置为PROMPT_COMMAND
。
-
行24~26:
shopt -s histappend
:这个命令打开并行历史记录功能,这样所有的命令历史都会被写入到文件中,而不是在退出时一次性写入。history -a
:这个命令将当前的历史记录写入到历史文件中。shopt -s checkwinsize
:这个命令打开checkwinsize选项,这样当终端窗口大小改变时,bash会自动更新窗口大小。
-
行27:
[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
:这个条件判断检查当前的提示符是否是默认的提示符格式,如果是,则将其修改为包含用户名、主机名、工作目录和当前命令的提示符格式。PS1的默认显示形式
\\s-\\v\\\$
是一个字符串,其中\s-\v
和\$
都是特殊的转义序列。\s-\v
:这个转义序列表示当前终端的窗口标题。\$
:这个转义序列表示当前的用户身份,如果是root用户,则会显示#
,否则会显示$
。
第二部分
- 行29:判断当前shell是否是登陆shell,如果当前shell是登陆shell,不会执行29~59行代码。
- 行30~41:自定义函数,用于管理
$PATH
环境变量。$PATH
是一个由冒号分隔的目录列表,用于指定shell在查找可执行文件时应该搜索哪些目录。- 行31~33: 这个
case
语句检查$PATH
是否已经包含了$1
(即要添加到$PATH
的路径)。如果已经包含,则什么都不做;否则,将其添加到$PATH
。 - 行34~39: 这行代码根据第二个参数(
$2
)决定是将$1
添加到$PATH
的前面还是后面。
- 行31~33: 这个
- 行42~46:这行代码根据用户的UID和组ID设置umask。
/usr/bin/id -gn
返回当前用户的组名。/usr/bin/id -un
返回当前用户的用户名。
- 行47:将环境变量
SHELL
设置为bash的路径。 - 行48~56:遍历
/etc/profile.d/
目录下的所有以.sh
结尾的文件,并执行它们。如果当前shell是登录shell或交互式shell,则直接执行这些脚本;否则,将脚本的输出重定向到null。 - 行57~58:分别取消变量
i
和函数pathmunge
的定义。
总结:这段代码主要用于在非登录shell中设置环境变量和权限掩码,并执行一些初始化脚本。
第三部分
主要功能是计算OMP_NUM_THREADS的值
- 检查
lscpu
命令的输出中是否包含’Cluster(s):'。如果包含,执行以下操作:- 保存当前的
LANG
和LANGUAGE
环境变量。 - 设置
LANG
为en_US.UTF-8
,并设置LANGUAGE
为en_US
。 - 计算
OMP_NUM_THREADS
的值。这是通过lscpu
命令获取的CPU集群、核心和线程信息计算得出的。 - 恢复原始的
LANG
和LANGUAGE
值。 - 清除之前设置的临时变量。
- 保存当前的
- 如果
lscpu
的输出中不包含’Cluster(s):',则执行以下操作:- 保存当前的
LANG
和LANGUAGE
环境变量。 - 设置
LANG
为en_US.UTF-8
,并设置LANGUAGE
为en_US
。 - 计算
OMP_NUM_THREADS
的值。这次是通过获取的CPU插槽、每个插槽的核心和每个核心的线程信息计算得出的。 - 恢复原始的
LANG
和LANGUAGE
值。 - 清除之前设置的临时变量。
- 保存当前的
总结:这个脚本的主要目的是根据CPU的架构信息设置环境变量,特别是与OpenMP线程数相关的变量
注意:这段代码可能不会在所有系统上正常工作,因为它依赖于特定版本的lscpu
命令的输出格式。此外,使用这种方式动态设置环境变量可能不是最佳实践,因为它可能会导致其他程序的行为变得不可预测。在设置这些环境变量之前,最好先理解它们对系统的影响。
补充
-
BASHRCSOURCED是一个内部变量,该变量在bash源码中定义,并且只有在bash正在运行的时候才会被设置,用于避免重复加载/etc/bashrc文件。具体来说,当bash启动时,它会检查
$BASHRCSOURCED
的值。如果$BASHRCSOURCED
为真,则不会再次源/etc/bashrc
文件。否则,bash会执行/etc/bashrc
文件,并将$BASHRCSOURCED
设置为真,以避免重复加载。 -
PS1被设置,交互式运行bash
-
Bash提示符:Bash shell中用于显示在命令行界面上的文本信息。它通常包括用户名称、主机名、当前目录和命令提示符等信息。Bash提示符可以根据用户的配置和偏好进行自定义。在默认情况下,Bash提示符是
$
符号,但用户可以通过修改环境变量或配置文件来设置其他字符或字符串作为提示符。 修改bash提示符可以修改PS1变量,PS1是bash提示符的占位符。如果你将
PS1
设置为\u@\h:\w\$
,那么提示符将显示为username@hostname:/current_directory$
。 -
lscpu命令 - 获取CPU架构信息
它从伪文件系统(sysfs)、/proc/cpuinfo 和任何可用的特定体系架构库(如 Powerpc 上的 librtas)收集信息。
-
if [ ]条件判断
-z:字符串空,返回true
-e:判断文件是否存在
-gt:大于
~/.bash_profile
代码
1 if [ -f ~/.bashrc ]; then
2 . ~/.bashrc
3 fi
# User specific environment and startup programs
4 PATH=$PATH:$HOME/bin
5 export PATH
6 . "$HOME/.cargo/env"
代码详解
- 行1~3:判断~/.bashrc文件是否存在,存在->执行
- 行4:将
$HOME/bin
添加到环境变量PATH
的末尾。 - 行5:将
PATH
环境变量导出到子进程。这样,任何新启动的进程都可以访问到PATH
中的路径。
~/.bashrc
代码
# User specific aliases and functions
1 alias rm='rm -i'
2 alias cp='cp -i'
3 alias mv='mv -i'
# Source global definitions
4 if [ -f /etc/bashrc ]; then
5 . /etc/bashrc
6 fi
代码详解
- 行1~3:设置别名
- 行4~6:文件/etc/bashrc是否存在,存在->执行
~/.bash_logout
没有任何内容