bash shell用一个叫作环境变量(environment variable)的特性来存储有关shell会话和工作环境的信息(这也是它们被称作环境变量的原因)。这项特性允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。

 

在bash shell中,环境变量分为两类:

  全局变量

  局部变量

 

全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只对创建它们的shell可见。

局部环境变量顾名思义,局部环境变量只能在定义它们的进程中可见。

 

命令 env 、 printenv 和 set 之间的差异很细微。 set 命令会显示出全局变量、局部变量以及用户定义变量。它还会按照字母顺序对结果进行排序。 env 和 printenv 命令同 set 命令的区别在于前两个命令不会对变量排序,也不会输出局部变量和用户定义变量。在这种情况下, env 和 printenv 的输出是重复的。

 

所有的环境变量名均使用大写字母,这是bash shell的标准惯例。如果是你自己创建的局部变量或是shell脚本,请使用小写字母。变量名区分大小写。在涉及用户定义的局部变量时坚持使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。

变量名、等号和值之间没有空格,这一点非常重要。如果在赋值表达式中加上了空格,bash shell就会把值当成一个单独的命令:

[root@jerry ~]# my_variabe = "Hello World"

-bash: my_variabe: command not found

 

设置局部环境变量后,只能在当前shell进程使用,新创建的shell是无法使用的:

[root@jerry ~]# my_variable="Hello World"

[root@jerry ~]# bash

[root@jerry ~]# echo $my_variable

 

[root@jerry ~]# exit

exit

[root@jerry ~]# echo $my_variable

Hello World

在这个例子中生成了一个子shell。在子shell中无法使用用户定义变量 my_variable 。通过命令 echo $my_variable 所返回的空行就能够证明这一点。当你退出子shell并回到原来的shell时,这个局部环境变量依然可用。

 

设置全局变量,在设定全局环境变量的进程所创建的子进程中,该变量都是可见的。创建全局环境变量的方法是先创建一个局部环境变量,然后再把它导出到全局环境中。这个过程通过 export 命令来完成,变量名前面不需要加 $ 。

# my_variable="I am Global now"

#

# export my_variable

#

# echo $my_variable

I am Global now

# bash

#

# echo $my_variable

I am Global now

# exit

exit

# echo $my_variable

I am Global now

#

 

修改子shell中全局环境变量并不会影响到父shell中该变量的值。

$ my_variable="I am Global now"

$ export my_variable

$

$ echo $my_variable

I am Global now

$

$ bash

$

$ echo $my_variable

I am Global now

$

$ my_variable="Null"

$

$ echo $my_variable

Null

$

$ exit

exit

$

$ echo $my_variable

I am Global now

$

 

删除变量,可以用 unset 命令完成这个操作。在 unset 命令中引用环境变量时,记住不要使用 $ 。

[root@jerry ~]# echo $my_variable

I am Global now

[root@jerry ~]#

[root@jerry ~]# echo $my_variable

I am Global now

[root@jerry ~]# unset my_variable

[root@jerry ~]# echo $my_variable

 

注意:如果要用到变量,使用 $ ;如果要操作变量,不使用 $ 。这条规则的一个例外就是使用 printenv 显示某个变量的值。

 

如果你是在子进程中删除了一个全局环境变量,这只对子进程有效。该全局环境变量在父进程中依然可用。

和修改变量一样,在子shell中删除全局变量后,你无法将效果反映到父shell中。

 

设置PATH环境变量

# echo $PATH

/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

# PATH=$PATH:/root/id

# echo $PATH

/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/id

 

程序员通常的办法是将单点符也加入 PATH 环境变量。该单点符代表当前目录。

$ PATH=$PATH:.

对 PATH 变量的修改只能持续到退出或重启系统。

 

启动bashshell有3种方式:

  登录时作为默认登录shell

  作为非登录shell的交互式shell

  作为运行脚本的非交互shell

 

登录shell会从5个不同的启动文件里读取命令:

  /etc/profile

  $HOME/.bash_profile

  $HOME/.bashrc

  $HOME/.bash_login

  $HOME/.profile

1. /etc/profile文件

/etc/profile文件是bash shell默认的的主启动文件。只要你登录了Linux系统,bash就会执行/etc/profile 启动文件中的命令。

 

2.$HOME/.bash_profile

$HOME/.bashrc

$HOME/.bash_login

$HOME/.profile

注意,这四个文件都以点号开头,这说明它们是隐藏文件(不会在通常的 ls 命令输出列表中出现)。它们位于用户的HOME目录下,所以每个用户都可以编辑这些文件并添加自己的环境变量,这些环境变量会在每次启动bash shell会话时生效。

 

交互式 shell 进程

如果你的bash shell不是登录系统时启动的(比如是在命令行提示符下敲入 bash 时启动),那么你启动的shell叫作交互式shell。交互式shell不会像登录shell一样运行,但它依然提供了命令行提示符来输入命令。

如果bash是作为交互式shell启动的,它就不会访问/etc/profile文件,只会检查用户HOME目录中的.bashrc文件。

# cat .bashrc

# .bashrc

 

# User specific aliases and functions

 

alias rm='rm -i'

alias cp='cp -i'

alias mv='mv -i'

 

# Source global definitions

if [ -f /etc/bashrc ]; then

    . /etc/bashrc

fi

.bashrc文件有两个作用:一是查看/etc目录下通用的bashrc文件,二是为用户提供一个定制自己的命令别名和私有脚本函数的地方。

 

非交互式 shell

最后一种shell是非交互式shell。系统执行shell脚本时用的就是这种shell。不同的地方在于它没有命令行提示符。但是当你在系统上运行脚本时,也许希望能够运行一些特定启动的命令。

脚本能以不同的方式执行。只有其中的某一些方式能够启动子shell。

 

环境变量持久化:

对全局环境变量来说(Linux系统中所有用户都需要使用的变量),可能更倾向于将新的或修改过的变量设置放在/etc/profile文件中,但如果你升级了所用的发行版,这个文件也会跟着更新,那你所有定制过的变量设置可就都没有了。最好是在/etc/profile.d目录中创建一个以.sh结尾的文件。把所有新的或修改过的全局环境变量设置放在这个文件中。

在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。这一点适用于所有类型的shell进程。但如果设置了 BASH_ENV 变量,那么记住,除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放在别的地方。

 

alias 命令设置是不能持久。你可以把自己的 alias 设置放在$HOME/.bashrc启动文件中,使其效果永久化。

 

数组变量

环境变量有一个很酷的特性就是,它们可作为数组使用。数组是能够存储多个值的变量。这些值可以单独引用,也可以作为整个数组来引用。

 

要给某个环境变量设置多个值,可以把值放在括号里,值与值之间用空格分隔。

$ mytest=(one two three four five)

$

没什么特别的地方。如果你想把数组像普通的环境变量那样显示,你会失望的。

$ echo $mytest

one

$

只有数组的第一个值显示出来了。要引用一个单独的数组元素,就必须用代表它在数组中位

置的数值索引值。索引值要用方括号括起来。

$ echo ${mytest[2]}

three

要显示整个数组变量,可用星号作为通配符放在索引值的位置。

$ echo ${mytest[*]}

one two three four five

$

也可以改变某个索引值位置的值。

$ mytest[2]=seven

$

$ echo ${mytest[*]}

one two seven four five

$

甚至能用 unset 命令删除数组中的某个值,但是要小心,这可能会有点复杂。看下面的例子。

$ unset mytest[2]

$

$ echo ${mytest[*]}

one two four five

$

$ echo ${mytest[2]}

$ echo ${mytest[3]}

four

$

在 unset 命令后跟上数组名来删除整个数组。

$ unset mytest

$

$ echo ${mytest[*]}

$

 

每次登录Linux系统,bash shell都会访问/etc/profile启动文件以及3个针对每个用户的本地启动文件:$HOME/.bash_profile、$HOME/.bash_login和$HOME/.profile。用户可以在这些文件中定制自己想要的环境变量和启动脚本。

 

添加新用户

系统默认值被设置在/etc/default/useradd文件中。可以使用加入了 -D 选项的 useradd命令查看所用Linux系统中的这些默认值。

[root@jerry ~]# /usr/sbin/useradd -D

GROUP=100

HOME=/home

INACTIVE=-1

EXPIRE=

SHELL=/bin/bash

SKEL=/etc/skel

CREATE_MAIL_SPOOL=yes

这个例子列出的默认值如下:

  新用户会被添加到GID为 100 的公共组;

  新用户的HOME目录将会位于/home/loginname;

  新用户账户密码在过期后不会被禁用;

  新用户账户未被设置过期日期;

  新用户账户将bash shell作为默认shell;

  系统会将/etc/skel目录下的内容复制到用户的HOME目录下;

  系统为该用户账户在mail目录下创建一个用于接收邮件的文件。

 

删除用户

如果你想从系统中删除用户, userdel 可以满足这个需求。默认情况下, userdel 命令会只删除/etc/passwd文件中的用户信息,而不会删除系统中属于该账户的任何文件。

如果加上 -r 参数, userdel 会删除用户的HOME目录以及邮件目录。然而,系统上仍可能存有已删除用户的其他文件。这在有些环境中会造成问题。

 

                      用户账户修改工具


   命 令                                                       描 述

usermod                    修改用户账户的字段,还可以指定主要组以及附加组的所属关系

passwd                      修改已有用户的密码

chpasswd                  从文件中读取登录名密码对,并更新密码

chage                        修改密码的过期日期

chfn                          修改用户账户的备注信息

chsh                          修改用户账户的默认登录shell


 

1.  usermod是用户账户修改工具中最强大的一个。它能用来修改/etc/passwd文件中的大部分字段,只需用与想修改的字段对应的命令行参数就可以了。

  -l 修改用户账户的登录名。

  -L 锁定账户,使用户无法登录。

  -p 修改账户的密码。

  -U 解除锁定,使用户能够登录。

2.  passwd 和 chpasswd

改变用户密码的一个简便方法就是用 passwd 命令。

-e 选项能强制用户下次登录时修改密码。你可以先给用户设置一个简单的密码,之后再强制在下次登录时改成他们能记住的更复杂的密码。

 

如果需要为系统中的大量用户修改密码, chpasswd 命令可以事半功倍。 chpasswd 命令能从标准输入自动读取登录名和密码对(由冒号分割)列表,给密码加密,然后为用户账户设置。你也可以用重定向命令来将含有userid:passwd 对的文件重定向给该命令。

# chpasswd < users.txt

 

3.  chsh 、 chfn 和 chage

chsh 、 chfn 和 chage 工具专门用来修改特定的账户信息。 chsh 命令用来快速修改默认的用户登录shell。使用时必须用shell的全路径名作为参数,不能只用shell名。

 

使用 Linux 组

用户账户在控制单个用户安全性方面很好用,但涉及在共享资源的一组用户时就捉襟见肘了。为了解决这个问题,Linux系统采用了另外一个安全概念——组(group)。

组权限允许多个用户对系统中的对象(比如文件、目录或设备等)共享一组共用的权限。

 

/etc/group 文件

与用户账户类似,组信息也保存在系统的一个文件中。/etc/group文件包含系统上用到的每个组的信息。下面是一些来自Linux系统上/etc/group文件中的典型例子。

[root@jerry ~]# cat /etc/group

root:x:0:

bin:x:1:bin,daemon

daemon:x:2:bin,daemon

sys:x:3:bin,adm

adm:x:4:adm,daemon

tty:x:5:

disk:x:6:

lp:x:7:daemon

mem:x:8:

kmem:x:9:

wheel:x:10:

和UID一样,GID在分配时也采用了特定的格式。系统账户用的组通常会分配低于500的GID值,而用户组的GID则会从500开始分配。/etc/group文件有4个字段:

  组名

  组密码

  GID

  属于该组的用户列表

 

创建新组

groupadd命令可在系统上创建新组

#groupadd ceshi

在创建新组时,默认没有用户被分配到该组。 groupadd 命令没有提供将用户添加到组中的选项,但可以用 usermod 命令来弥补这一点。

# /usr/sbin/usermod -G shared rich

 

为用户账户分配组时要格外小心。如果加了 -g 选项,指定的组名会替换掉该账户的默认组。 -G 选项则将该组添加到用户的属组的列表里,不会影响默认组。

 

修改组

在/etc/group文件中可以看到,需要修改的组信息并不多。 groupmod 命令可以修改已有组的GID(加 -g 选项)或组名(加 -n 选项)。

 

理解文件权限

drwxr-xr-x. 2 root  root    4096 Nov 17 21:07 monitor

第一个字段就是描述文件和目录权限的编码。这个字段的第一个字符代表了对象

的类型:

  - 代表文件

  d 代表目录

  l 代表链接

  c 代表字符型设备

  b 代表块设备

  n 代表网络设备

之后有3组三字符的编码。每一组定义了3种访问权限:

 r代表可读

 w代表可写

 x代表可执行

若没有某种权限,在该权限位会出现单破折线。这3组权限分别对应对象的3个安全级别:

  对象的属主:U

  对象的属组:G

  系统其他用户:O

 

默认文件权限

你可能会问这些文件权限从何而来,答案是 umask 。 umask 命令用来设置所创建文件和目录的默认权限。

touch 命令用分配给我的用户账户的默认权限创建了这个文件。 umask 命令可以显示和设置这个默认权限。

$ umask

0022

 

                 Linux文件权限码

权 限      二进制值     八进制值     描 述

---            000               0           没有任何权限

--x            001               1           只有执行权限

-w-           010               2           只有写入权限

-wx           011               3           有写入和执行权限

r--             100              4            只有读取权限

r-x             101              5            有读取和执行权限

rw-            110              6            有读取和写入权限

rwx           111               7            有全部权限

 

改变安全性设置

如果你已经创建了一个目录或文件,需要改变它的安全性设置,在Linux系统上有一些工具能够完成这项任务。本节将告诉你如何更改文件和目录的已有权限、默认文件属主以及默认属组。

改变权限

chmod 命令用来改变文件和目录的安全性设置

改变所属关系

chown 命令用来改变文件的属主,

chgrp 命令用来改变文件的默认属组。

 

vim编辑器使用:

替换命令允许你快速用另一个单词来替换文本中的某个单词。必须进入命令行模式才能使用替换命令。替换命令的格式是:

:s/old/new/

vim编辑器会跳到 old 第一次出现的地方,并用 new 来替换。可以对替换命令作一些修改来替换多处文本。

  :s/old/new/g :一行命令替换所有 old 。

  :n,ms/old/new/g :替换行号 n 和 m 之间所有 old 。

  :%s/old/new/g :替换整个文件中的所有 old 。

  :%s/old/new/gc :替换整个文件中的所有 old ,但在每次出现时提示。