Linux set、env、declare、export显示shell变量的区别

时间:2021-12-28 04:40:08

Linux中 set、env、declare、export显示shell变量的区别

shell变量包括两种变量

1. shell局部变量

局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。

通过赋值语句定义好的变量,可以通过如下方法定义shell变量

A1="1234"
delcare A2="2345"

2. 用户的环境变量

所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。

通过export语法导出的shell私有变量,可以通过如下方法导出用户环境变量

A1="1234"
export A1 #先定义再导出
export A3="34"

显示shell变量

env 这是一个工具,或者说一个Linux命令,显示用户的环境变量。

set 显示用户的局部变量和用户环境变量。

export 显示导出成用户变量的shell局部变量,并显示变量的属性;就是显示由局部变量导出成环境变量的那些变量 (比如可以 export WWC导出一个环境变量,也可通过 declare -X LCY导出一个环境变量)

declare 跟set一样,显示用户的shell变量 (局部变量和环境变量)

declare 命令

declare命令用于声明 shell 变量。

declare WWC="wangwenchao"

也可以省略declare

WWC="wangwenchao"

用法

declare [+/-][rxi][变量名称=设置值] 或 declare -f

  1. +/-  "-"可用来指定变量的属性,"+"则是取消变量所设的属性。
  2. -f  仅显示函数。
  3. r  将变量设置为只读。
  4. x  指定的变量会成为环境变量,可供shell以外的程序来使用。
  5. i  [设置值]可以是数值,字符串或运算式。

export 命令

export命令用于设置或显示环境变量。用于将局部变量导出成环境变量。

用法

export [-fnp][变量名称]=[变量设置值]

  1. -f  代表[变量名称]中为函数名称。
  2. -n  删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
  3. -p  列出所有的shell赋予程序的环境变量。

**PS: export命令的功能跟 declare功能部分重合;export WWC="wangwenchao" 相当于 declare -x WWC="wangwenchao"; 功能export -n WWC 相当于 declare +x WWC; 功能export查看导出的环境变量

source 命令

source命令用法:

source FileName

作用:在当前bash环境下读取并执行FileName中的命令。

注:该命令通常用命令“.”来替代。

如:source .bash_rc 与 . .bash_rc 是等效的。

source命令与shell scripts的区别是,source在当前bash环境下执行命令,而scripts是启动一个子shell来执行命令。这样如果把设置环境变量(或alias等等)的命令写进scripts中,就只会影响子shell,无法改变当前的BASH,所以通过文件(命令列)设置环境变量时,要用source 命令。

source跟./xxx.sh或bash xxx.sh最大的不同就是前者在文件中设置的变量对当前shell是可见的,而后者设置的变量对当前shell是不可见的。要知道./xxx.sh和bash xxx.sh都是在当前shell的子shell中执行的,子shell中的变量不会影响父shell,而source是把文件中的命令都读出来一个个执行,所有的变量其实就是在父shell中设置的。

nohup 命令

nohup 命令是 no hanp up 的缩写。

Unix/Linux下一般想让某个程序在后台运行,很多都是使用&在程序结尾来让程序自动运行;但如果要想在退出终端后,程序依然还在后台运行,则要用nohup与&组合来实现。

nohup用法

nohup Command [ Arg ... ] [&]

nohup 命令运行由 Command参数和任何相关的Arg参数指定的命令,同时忽略所有的挂起 (SIGHUP) 信号,或者修改用 -p 选项指定的进程来忽略所有的挂起 (SIGHUP) 信号(关闭终端、注销用户等,但是注意 ctrl + c 不是挂起信号)。

在注销后还可以使用 nohup 命令运行后台中的程序。要运行后台中的 nohup 命令,添加 &(表示“and”的符号)到命令的尾部。输出将附加到当前目录的nohup.out 文件中

注: -p pid 和 Command 不能一起指定。

使用 -p pid 时,指定进程的输出将不会重定向到 nohup.out。

ctrl + c nohup bash wwc.sh 会停止运行,但是 bash wwc.sh & 会正常运行;直接关闭终端 nohup bash wwc.sh 会正常运行,bash wwc.sh & 会停止;所以要 nohup 跟 & 结合使用。

杀死由nohup执行的进程

ps -ef | grep commond | grep -v grep
例如:
ps -ef | grep "bash wwc.sh" | grep -v grep

找到进程id

kill -9 id

参考链接:https://www.ibm.com/support/knowledgecenter/zh/ssw_aix_72/com.ibm.aix.cmds4/nohup.htm

type 命令

type命令用来显示指定命令的类型,判断给出的指令是内部指令还是外部指令。

用法

  1. -t:输出“file”、“alias”或者“builtin”,分别表示给定的指令为“外部指令”、“命令别名”或者“内部指令”;
  2. -p:如果给出的指令为外部指令,则显示其绝对路径;
  3. -a:在环境变量“PATH”指定的路径中,显示给定指令的信息,包括命令别名。

结果

alias:别名。

keyword:关键字,Shell保留字。

function:函数,Shell函数。

builtin:内建命令,Shell内建命令。

file:文件,磁盘文件,外部命令。

unfound:没有找到。

内建命令和外部命令

内建命令

内部命令实际上是shell程序的一部分,其中包含的是一些比较简单的linux系统命令,这些命令由shell程序识别并在shell程序内部完成运行,通常在linux系统加载运行时shell就被加载并驻留在系统内存中。内部命令是写在bashy源码里面的,其执行速度比外部命令快,因为解析内部命令shell不需要创建子进程。比如:exit,history,cd,echo等。

有些命令是由于其必要性才内建的,例如cd用来改变目录,read会将来自用户(和文件)的输入数据传给Shell外亮。

另一种内建命令的存在则是为了效率,其中最典型的就是test命令,编写脚本时经常会用到它。另外还有I/O命令,例如echo于printf.

外部命令

外部命令是linux系统中的实用程序部分,因为实用程序的功能通常都比较强大,所以其包含的程序量也会很大,在系统加载时并不随系统一起被加载到内存中,而是在需要时才将其调用内存。通常外部命令的实体并不包含在shell中,但是其命令执行过程是由shell程序控制的。shell程序管理外部命令执行的路径查找、加载存放,并控制命令的执行。外部命令是在bash之外额外安装的,通常放在/bin,/usr/bin,/sbin,/usr/sbin......等等。可通过“echo $PATH”命令查看外部命令的存储路径,比如:ls、vi等。

外部命令就是由Shell副本(新的进程)所执行的命令,基本的过程如下:

  1. 建立一个新的进程。此进程即为Shell的一个副本。
  2. 在新的进程里,在PATH变量内所列出的目录中,寻找特定的命令。

    /bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin为PATH变量典型的默认值。

    当命令名称包含有斜杠(/)符号时,将略过路径查找步骤。
  3. 在新的进程里,以所找到的新程序取代执行中的Shell程序并执行。
  4. 程序完成后,最初的Shell会接着从终端读取下一条命令,和执行脚本里的下一条命令。

用户在命令行输入命令后,一般情况下Shell会fork并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程.

PS:为了实现强大的功能,有些内建命令也有了外部命令实现的版本,这些外部命令往往比对应的内部命令功能更强大,但是相对效率可能会低(例如:cd、echo等);同样一些外部命令为了执行效力的问题,在内建命令中也有了实现(例如:printf);如果一个命令既有内部实现又有外部实现,直接使用使用的是其内部版本,要想使用其外部实现,可以使用绝对路径,比如:echo是使用的其内部命令,/bin/echo是使用的其外部命令,查看一个外部命令的路径,可以使用 which 命令,例如which echo

设置环境变量永久有效和临时有效

永久有效

对所有用户有效

/etc/profile 是每个用户登录时都会运行的环境变量设置文件,当用户第一次登录时,该文件被执行。对所有用户有效。

一个例子:

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi if [ "${BASH-no}" != "no" ]; then
[ -r /etc/bashrc ] && . /etc/bashrc
fi export THEOS=/opt/theos
export WWC=wangwenchao_lcy
对当前用户有效

你可以把你要添加的环境变量添加到你主目录下面的.profile或者.bash_profile,如果该文件存在添加进去即可,如果该文件不存在,就在用户主目录下创建一个。

总结:

  1. /etc/profile (建议不修改这个文件 )

    全局(公有)配置,不管是哪个用户,登录时都会读取该文件。

  2. /etc/bashrc (一般在这个文件中添加系统级环境变量)

    全局(公有)配置,bash shell执行时,不管是何种方式,都会读取此文件。可以设置系统提示符 PS1等。比如 PS1=\h:\W \u$,那么提示符的格式就是:主机:当前目录 用户名$

  3. ~/.bash_profile 或者 ~/.profile (一般在这个文件中添加用户级环境变量)

    每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!

PS: MAC下环境变量的加载顺序/etc/profile /etc/paths ~/.bash_profile ~/.bash_login ~/.profile,并且这几个文件~/.bash_profile ~/.bash_login ~/.profile是互斥的关系,如果前面的文件存在,后面的文件就不会加载

其他配置文件

/etc/paths (全局建议修改这个文件)

编辑 paths,设置PATH环境变量

/etc/hosts

主机名和IP配置文件

hosts文件是Linux系统中一个负责IP地址与域名快速解析的文件,以ASCII格式保存在“/etc”目录下,文件名为“hosts”(不同的linux版本,这个配置文件也可能不同。比如Debian的对应文件是/etc/hostname)。hosts文件包含了IP地址和主机名之间的映射,还包括主机名的别名。在没有域名服务器的情况下,系统上的所有网络程序都通过查询该文件来解析对应于某个主机名的IP地址,否则就需要使用DNS服务程序来解决。通常可以将常用的域名和IP地址映射加入到hosts文件中,实现快速方便的访问。

hosts文件的格式如下:

IP地址 主机名/域名 主机别名(optional)

第一部份:网络IP地址;

第二部份:主机名或域名;

第三部份:主机名别名;

系统目录

usr目录

usr 是 unix system resources 的缩写

曾经的 /usr 还是用户的家目录,存放着各种用户文件 —— 现在已经被 /home 取代了(例如 /usr/someone 已经改为 /home/someone)。现代的 /usr 只专门存放各种程序和数据,用户目录已经转移。虽然 /usr 名称未改,不过其含义已经从“用户目录”变成了“unix 系统资源”目录。值得注意的是,在一些 unix 系统上,仍然把 /usr/someone 当做用户家目录,如 Minix。

/sbin、/bin、/usr/sbin、/usr/bin的区别

/sbin 主要放置一些系统管理的必备程式,如 reboot、shutdown等;/sbin 下的命令属于基本的系统命令

/bin 存放一些普通的基本命令,如ls,chmod等,这些命令在Linux系统里的配置文件脚本里经常用到

/usr/sbin 放置一些用户安装的系统管理程式,存放的一些非必须的系统命令

/usr/bin 存放一些用户命令

综述:如果这是用户和管理员必备的二进制文件,就会放在/bin。如果这是系统管理员必备,但是一般用户根本不会用到的二进制文件,就会放在 /sbin。相对而言。如果不是用户必备的二进制文件,多半会放在/usr/bin;如果不是系统管理员必备的工具,多半会放在/usr/sbin。

从历史看Unix目录结构

话说1969年,Ken Thompson和Dennis Ritchie在小型机PDP-7上发明了Unix。1971年,他们将主机升级到了PDP-11。

没过多久,操作系统(根目录)变得越来越大,一块盘已经装不下了。于是,他们加上了第二盘RK05,并且规定第一块盘专门放系统程序,第二块盘专门放用户自己的程序,因此挂载的目录点取名为/usr。也就是说,根目录"/"挂载在第一块盘,"/usr"目录挂载在第二块盘。除此之外,两块盘的目录结构完全相同,第一块盘的目录(/bin, /sbin, /lib, /tmp...)都在/usr目录下重新出现一次。

后来,第二块盘也满了,他们只好又加了第三盘RK05,挂载的目录点取名为/home,并且规定/usr用于存放用户的程序,/home用于存放用户的数据。

从此,这种目录结构就延续了下来。随着硬盘容量越来越大,各个目录的含义进一步得到明确。

  1. /:存放系统程序,也就是At&t开发的Unix程序。
  2. /usr:存放Unix系统商(比如IBM和HP)开发的程序。
  3. /usr/local:存放用户自己安装的程序。
  4. /opt:在某些系统,用于存放第三方厂商开发的程序,所以取名为option,意为"选装"。

/usr/bin用于分发包管理器(如Ubuntu apt等)存放它所管理的应用的路径, /usr/sbin与/usr/bin的关系类似与/bin和/sbin的关系

/usr/local/bin用于存放用户自己的程序(如自己编译出来的包等),不受分发包管理器的控制。如果用户把自己的程序放在/usr/bin下,则有可能在未来被包管理器给修改、删除或覆盖了同名文件。

通常/usr/bin下面的都是系统预装的可执行程序,会随着系统升级而改变

/usr/local/bin目录是给用户放置自己的可执行程序的地方,推荐放在这里,不会被系统升级而覆盖同名文件

一般环境变量PATH都设置为 /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin,注意设置的顺序问题,如果在前面的目录找到了命令,就不会再搜索后边的目录。

参考链接:Unix目录结构的来历——阮一峰的网络日志

问题

Linux环境变量的加载顺序?