Linux笔记:2-认识与学习BASH

Posted 、妤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux笔记:2-认识与学习BASH相关的知识,希望对你有一定的参考价值。

@

认识与学习BASH

操作系统其实是一组软件, 由于这组软件在控制整个硬件与管理系统的活动监测。
壳程序的功能只是提供使用者操作系统的一个接口, 因此这个壳程序需要可以调用其他软件才行。
之前学习的指令都是独立的应用程序, 但是我们可以通过壳程序 ( 就是命令行界面) 来操作这些应用程序, 让这些应用程序调用核心来运行所需的工作。
 
只要能够操作应用程序的接口都能够称为壳程序。
狭义的壳程序指的是命令行方面的软件, 包括 bash 等。
广义的壳程序则包括图形接口的软件! 因为图形接口其实也能够操作各种应用程序来调用核心工作。

关于Bash

系统的合法 shell 与 /etc/shells 功能

目前我们的 Linux ( 以 CentOS 7.x 为例);
你可以检查一下 /etc/shells 这个文件, 至少就有下面这几个可以用的 shells

  • /bin/sh ( 已经被 /bin/bash 所取代)
  • /bin/bash ( 就是 Linux 默认的 shell)
  • /bin/tcsh ( 整合 C Shell , 提供更多的功能)
  • /bin/csh ( 已经被 /bin/tcsh 所取代)

系统上合法的 shell 需要写入 /etc/shells 这个文件;
因为系统某些服务在运行过程中, 会去检查使用者能够使用的 shells , 而这些shell 的查询就是借由 /etc/shells 这个文件。
 
当用户登陆的时候, 系统就会给我一个 shell 让用户来工作;
而这个登陆取得的 shell 就记录在 /etc/passwd 这个文件内。

[dmtsai@study ~]$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....( 下面省略) .....

Bash shell 的功能

  • 命令记忆能力 ( history) :
    他能记忆使用过的指令;保存在用户的主文件夹内的 .bash_history中;
    ~/.bash_history 记录的是前一次登陆以前所执行过的指令, 而至于这一次登陆所执行的指令都被暂存在内存中, 当你成功的登出系统后, 该指令记忆才会记录到 .bash_history 当中 。
  • 命令与文件补全功能: ( [tab] 按键的好处)
  • 命令别名设置功能: ( alias)
  • 工作控制、 前景背景控制: ( job control, foreground, background)
  • 程序化脚本: ( shell scripts)
    Linux 下面的 shellscripts, 可以将你平时管理系统常需要下达的连续指令写成一个文件, 该文件并且可以通过对谈互动式的方式来进行主机的侦测工作。
  • 模糊字符匹配:
    例如:想要知道 /usr/bin 下面有多少以 X 为开头的文件? 使用: “ ls -l /usr/bin/X* ”。

查询指令是否为 Bash shell 的内置命令: type

为了方便 shell 的操作, 其实 bash 已经“内置”了很多指令;
为了区分指令是来自于外部指令( 指的是其他非 bash 所提供的指令) 或是内置在bash ;利用 type 这个指令来观察即可

[dmtsai@study ~]$ type [-tpa] name
选项与参数:
		: 不加任何选项与参数时, type 会显示出 name 是外部指令还是 bash 内置指令
-t 		: 当加入 -t 参数时, type 会将 name 以下面这些字眼显示出他的意义:
file 	: 表示为外部指令;
alias 	: 表示该指令为命令别名所设置的名称;
builtin : 表示该指令为 bash 内置的指令功能;
-p 		: 如果后面接的 name 为外部指令时, 才会显示完整文件名;
-a 		: 会由 PATH 变量定义的路径中, 将所有含 name 的指令都列出来, 包含 alias

范例一: 查询一下 ls 这个指令是否为 bash 内置?
[dmtsai@study ~]$ type ls
ls is aliased to `ls --color=auto\' <==未加任何参数, 列出 ls 的最主要使用情况
[dmtsai@study ~]$ type -t ls
alias                              <==仅列出 ls 执行时的依据
[dmtsai@study ~]$ type -a ls
ls is aliased to `ls --color=auto\' <==最先使用 aliase
ls is /usr/bin/ls                  <==还有找到外部指令在 /bin/ls

范例二: 那么 cd 呢?
[dmtsai@study ~]$ type cd
cd is a shell builtin              <==看到了吗? cd 是 shell 内置指令

通过 type 这个指令我们可以知道每个指令是否为 bash 的内置指令
此外, 由于利用 type 搜寻后面的名称时, 如果后面接的名称并不能以可执行文件的状态被找到, 那么该名称是不会被显示出来的。
也就是说, type 主要在找出“可执行文件”而不是一般文件文件名
所以, 这个 type 也可以用来作为类似 which 指令的用途

指令的下达与快速编辑按钮

当指令过长时,可以使用 \\ + [Enter] 来换行输入;
 
另外, 当你所需要下达的指令特别长, 或者是你输入了一串错误的指令时, 你想要快速的将这串指令整个删除掉, 一般来说, 我们都是按下删除键的来删除;也可以使用下面的快捷键:

组合键 功能与示范
[ctrl]+u/[ctrl]+k 分别是从光标处向前删除指令串 ( [ctrl]+u) 及向后删除指令串( [ctrl]+k) 。
[ctrl]+a/[ctrl]+e 分别是让光标移动到整个指令串的最前面 ( [ctrl]+a) 或最后面( [ctrl]+e) 。

Shell 的变量功能

Linux 是多用户多任务的环境, 每个人登陆系统都能取得一个 bash shell;
不同用户的shell有自己的shell环境,不同环境是通过变量来设置。

在 Linux System 下面, 所有的线程都是需要一个执行码;
你“真正以 shell 来跟 Linux 沟通, 是在正确的登陆 Linux 之后! ”这个时候你就有一个 bash 的执行程序, 也才可以真正的经由 bash 来跟系统沟通;
而在进入 shell之前,由于系统需要一些变量来提供shell数据的存取 ( 或者是一些环境的设置参数值, 例如是否要显示彩色等等的) , 所以就有一些所谓的“环境变量” 需要来读入系统中了!
这些环境变量例如 PATH、 HOME、 MAIL、 SHELL 等等, 都是很重要的;
为了区别与自订变量的不同, 环境变量通常以大写字符来表示。

变量的取用与设置: echo, 变量设置规则, unset

你可以利用 echo 这个指令来取用变量, 但是, 变量在被取用时,前面必须要加上钱字号“ $ ”才行。

[dmtsai@study ~]$ echo $variable
[dmtsai@study ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
[dmtsai@study ~]$ echo $PATH  # 近年来, 鸟哥比较偏向使用这种格式喔!

在 bash 当中, 当一个变量名称尚未被设置时, 默认的内容是“空”的
另外, 变量在设置时, 还是需要符合某些规定的, 否则会设置失败:

  1. 变量与变量内容以一个等号“=”来链接, 如下所示:
    “myname=VBird”
  2. 等号两边不能直接接空白字符, 如下所示为错误:
    “myname = VBird”或“myname=VBirdTsai”
  3. 变量名称只能是英文字母与数字, 但是开头字符不能是数字, 如下为错误:
    “2myname=VBird”
  4. 变量内容若有空白字符可使用双引号“"”或单引号“\'”将变量内容结合起来, 但
  • 双引号内的特殊字符如 $ 等, 可以保有原本的特性, 如下所示:
    “var="lang is$LANG"”则“echo $var”可得“lang is zh_TW.UTF-8”
  • 单引号内的特殊字符则仅为一般字符 ( 纯文本) ,
    如下所示: “var=\'lang is$LANG\'”则“echo $var”可得“lang is $LANG”
  1. 可用跳脱字符“ \\ ”将特殊符号( 如 [Enter], $, , 空白字符, \'等) 变成一般字符, 如:
    “myname=VBird\\ Tsai”
  2. 在一串指令的执行中, 还需要借由其他额外的指令所提供的信息时, 可以使用反单引号“ ` ”或 “$( 指令)”。 特别注意, 那个 ` 是键盘上方的数字键 1 左边那个按键, 而不是单引号!
    例如想要取得核心版本的设置: “version=$( uname -r) ”再“echo$version”可得“3.10.0-229.el7.x86_64”
  3. 若该变量为扩增变量内容时, 则可用 "$变量名称" 或 $变量 累加内容, 如下所示
    “PATH="$PATH":/home/bin”或“PATH=$PATH:/home/bin”
  4. 若该变量需要在其他子程序执行, 则需要以 export 来使变量变成环境变量: “export PATH”
  5. 通常大写字符为系统默认变量, 自行设置变量可以使用小写字符, 方便判断 ( 纯粹依照使用者兴趣与嗜好);
  6. 取消变量的方法为使用 unset : “unset 变量名称”例如取消 myname 的设置: “unset myname”
范例一: 设置一变量 name , 且内容为 VBird
[dmtsai@study ~]$ 12name=VBird
bash: 12name=VBird: command not found... <==屏幕会显示错误! 因为不能以数字开头!
[dmtsai@study ~]$ name = VBird <==还是错误! 因为有空白!
[dmtsai@study ~]$ name=VBird <==OK 的啦!
范例二: 承上题, 若变量内容为 VBird\'s name 呢, 就是变量内容含有特殊符号时:
[dmtsai@study ~]$ name=VBird\'s name
# 单引号与双引号必须要成对, 在上面的设置中仅有一个单引号, 因此当你按下 enter 后,
# 你还可以继续输入变量内容。 这与我们所需要的功能不同, 失败啦!
# 记得, 失败后要复原请按下 [ctrl]-c 结束!
[dmtsai@study ~]$ name="VBird\'s name" <==OK 的啦!
# 指令是由左边向右找→, 先遇到的引号先有用, 因此如上所示, 单引号变成一般字符!
[dmtsai@study ~]$ name=\'VBird\'s name\' <==失败的啦!
# 因为前两个单引号已成对, 后面就多了一个不成对的单引号了! 因此也就失败了!
[dmtsai@study ~]$ name=VBird\\\'s\\ name <==OK 的啦!
# 利用反斜线 ( \\) 跳脱特殊字符, 例如单引号与空白键, 这也是 OK 的啦!
范例三: 我要在 PATH 这个变量当中“累加”:/home/dmtsai/bin 这个目录
[dmtsai@study ~]$ PATH=$PATH:/home/dmtsai/bin
[dmtsai@study ~]$ PATH="$PATH":/home/dmtsai/bin
[dmtsai@study ~]$ PATH=$PATH:/home/dmtsai/bin
# 上面这三种格式在 PATH 里头的设置都是 OK 的! 但是下面的例子就不见得啰!
范例四: 承范例三, 我要将 name 的内容多出 "yes" 呢?
[dmtsai@study ~]$ name=$nameyes
# 知道了吧? 如果没有双引号, 那么变量成了啥? name 的内容是 $nameyes 这个变量!
# 呵呵! 我们可没有设置过 nameyes 这个变量呐! 所以, 应该是下面这样才对!
[dmtsai@study ~]$ name="$name"yes
[dmtsai@study ~]$ name=$nameyes <==以此例较佳!
范例五: 如何让我刚刚设置的 name=VBird 可以用在下个 shell 的程序?
[dmtsai@study ~]$ name=VBird
[dmtsai@study ~]$ bash <==进入到所谓的子程序
[dmtsai@study ~]$ echo $name <==子程序: 再次的 echo 一下;
<==嘿嘿! 并没有刚刚设置的内容喔!
[dmtsai@study ~]$ exit <==子程序: 离开这个子程序
[dmtsai@study ~]$ export name
[dmtsai@study ~]$ bash <==进入到所谓的子程序
[dmtsai@study ~]$ echo $name <==子程序: 在此执行!
VBird <==看吧! 出现设置值了!
[dmtsai@study ~]$ exit <==子程序: 离开这个子程序

关于子程序:
在一般的状态下, 父程序的自订变量是无法在子程序内使用的。
但是通过 export 将变量变成环境变量后, 就能够在子程序下面应用。

范例六: 如何进入到您目前核心的模块目录?
[dmtsai@study ~]$ cd /lib/modules/`uname -r`/kernel
[dmtsai@study ~]$ cd /lib/modules/$( uname -r) /kernel # 以此例较佳!

每个 Linux 都能够拥有多个核心版本, 且几乎 distribution 的核心版本都不相同。 以 CentOS7.1 ( 未更新前) 为例, 他的默认核心版本是 3.10.0-229.el7.x86_64 , 所以核心模块目录在/lib/modules/3.10.0-229.el7.x86_64/kernel/ 内。 也由于每个 distributions 的这个值都不相同, 但是我们却可以利用 uname -r 这个指令先取得版本信息。
 
其实上面的指令可以说是作了两次动作, 亦即是:

  1. 先进行反单引号内的动作“uname -r”并得到核心版本为 3.10.0-229.el7.x86_64
  2. 将上述的结果带入原指令, 故得指令为: “cd /lib/modules/3.10.0-229.el7.x86_64/kernel/”

注意:
在一串指令中, 在反单引号之内的指令和$(指定)将会被先执行, 而其执行出来的结果将做为外部的输入信息。

环境变量的功能

环境变量的作用有:包括主文件夹的变换、 提示字符的显示、 可执行文件搜寻的路径等等。

用 env 观察环境变量 与 常见环境变量说明

范例一: 列出目前的 shell 环境下的所有环境变量与其内容。
[dmtsai@study ~]$ env
HOSTNAME=study.centos.vbird    <== 这部主机的主机名称
TERM=xterm                     <== 这个终端机使用的环境是什么类型
SHELL=/bin/bash                <== 目前这个环境下, 使用的 Shell 是哪一个程序?
HISTSIZE=1000                  <==  “记录指令的笔数”在 CentOS 默认可记录 1000 笔
OLDPWD=/home/dmtsai            <== 上一个工作目录的所在
LC_ALL=en_US.utf8              <== 由于语系的关系, 鸟哥偷偷丢上来的一个设置
USER=dmtsai                    <== 使用者的名称啊!
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:
or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:
*.tar=01...                    <== 一些颜色显示
MAIL=/var/spool/mail/dmtsai    <== 这个使用者所取用的 mailbox 位置
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
PWD=/home/dmtsai               <== 这个使用者所取用的 mailbox 位置
LANG=zh_TW.UTF-8               <== 这个与语系有关, 下面会再介绍!
HOME=/home/dmtsai              <== 这个使用者的主文件夹啊!
LOGNAME=dmtsai                 <== 登陆者用来登陆的帐号名称
_=/usr/bin/env                 <== 上一次使用的指令的最后一个参数( 或指令本身)
  • HOME 代表使用者的主文件夹。
    还记得我们可以使用 cd ~ 去到自己的主文件夹吗? 或者利用 cd 就可以直接回到使用者主文件夹了。 那就是取用这个变量啦~ 有很多程序都可能会取用到这个变量的值!
  • SHELL 告知我们, 目前这个环境使用的 SHELL 是哪支程序? Linux 默认使用 /bin/bash的啦!
  • HISTSIZE 这个与“历史命令”有关, 亦即是, 我们曾经下达过的指令可以被系统记录下来, 而记录的“笔数”则是由这个值来设置的。
  • MAIL 当我们使用 mail 这个指令在收信时, 系统会去读取的邮件信箱文件 ( mailbox) 。
  • PATH 就是可执行文件搜寻的路径啦~目录与目录中间以冒号( :) 分隔, 由于文件的搜寻是依序由 PATH 的变量内的目录来查询, 所以, 目录的顺序也是重要的喔。
  • LANG 这个重要! 就是语系数据啰~很多讯息都会用到他, 举例来说, 当我们在启动某些 perl 的程序语言文件时, 他会主动的去分析语系数据文件, 如果发现有他无法解析的编码语系, 可能会产生错误喔! 一般来说, 我们中文编码通常是 zh_TW.Big5 或者是zh_TW.UTF-8, 这两个编码偏偏不容易被解译出来, 所以, 有的时候, 可能需要修订一下语系数据。
  • RANDOM 这个玩意儿就是“随机乱数”的变量啦! 目前大多数的 distributions 都会有乱数产生器, 那就是 /dev/random 这个文件。 我们可以通过这个乱数文件相关的变量( $RANDOM) 来随机取得乱数值喔。 在 BASH 的环境下, 这个 RANDOM 变量的内容, 介于 0~32767 之间, 所以, 你只要 echo $RANDOM 时, 系统就会主动的随机取出一个介于 0~32767 的数值。

用 set 观察所有变量 ( 含环境变量与自订变量)

bash 可不只有环境变量还有一些与 bash 操作接口有关的变量, 以及使用者自己定义的变量存在的。
set 除了环境变量之外, 还会将其他在 bash 内的变量通通显示出来

[dmtsai@study ~]$ set
BASH=/bin/bash                        <== bash 的主程序放置路径
BASH_VERSINFO=([0]="4" [1]="2" [2]="46" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION=\'4.2.46(1)-release\'      <== 这两行是 bash 的版本啊!
COLUMNS=90                            <== 在目前的终端机环境下, 使用的字段有几个字符长度
HISTFILE=/home/dmtsai/.bash_history   <== 历史命令记录的放置文件, 隐藏文件
HISTFILESIZE=1000                     <== 存起来( 与上个变量有关) 的文件之指令的最大纪录笔数。
HISTSIZE=1000                         <== 目前环境下, 内存中记录的历史命令最大笔数。
IFS=$\' \\t\\n\'                          <== 默认的分隔符号
LINES=20                              <== 目前的终端机下的最大行数
MACHTYPE=x86_64-redhat-linux-gnu      <== 安装的机器类型
OSTYPE=linux-gnu                      <== 操作系统的类型!
PS1=\'[\\u@\\h \\W]\\$ \'                   <== PS1 就厉害了。 这个是命令提示字符, 也就是我们常见的
                                          [root@www ~]# 或 [dmtsai ~]$ 的设置值啦! 可以更动的!
PS2=\'> \'                              <== 如果你使用跳脱符号 ( \\) 第二行以后的提示字符也
$                                     <== 目前这个 shell 所使用的 PID
?                                     <== 刚刚执行完指令的回传值。
...
# 有许多可以使用的函数库功能被鸟哥取消啰! 请自行查阅!

一般来说, 不论是否为环境变量, 只要跟我们目前这个 shell 的操作接口有关的变量, 通常都会被设置为大写字符, 也就是说, “基本上, 在 Linux 默认的情况中, 使用大写的字母来设置的变量一般为系统内定需要的变量”。

变量大概说明:

  • PS1: ( 提示字符的设置)
    这是 PS1 ( 数字的 1 不是英文字母) , 这个东西就是我们的“命令提示字符”喔! 当我们每次按下 [Enter] 按键去执行某个指令后, 最后要再次出现提示字符时, 就会主动去读取这个变量值了。 上头 PS1 内显示的是一些特殊符号, 这些特殊符号可以显示不同的信息, 每个distributions 的 bash 默认的 PS1 变量内容可能有些许的差异, 不要紧, “习惯你自己的习惯”就好了。

相关提示说明
\\d : 可显示出“星期 月 日”的日期格式, 如: "Mon Feb 2"
\\H : 完整的主机名称。 举例来说, 鸟哥的练习机为“study.centos.vbird”
\\h : 仅取主机名称在第一个小数点之前的名字, 如鸟哥主机则为“study”后面省略
\\t : 显示时间, 为 24 小时格式的“HH:MM:SS”
\\T : 显示时间, 为 12 小时格式的“HH:MM:SS”
\\A : 显示时间, 为 24 小时格式的“HH:MM”
@ : 显示时间, 为 12 小时格式的“am/pm”样式
\\u : 目前使用者的帐号名称, 如“dmtsai”;
\\v : BASH 的版本信息, 如鸟哥的测试主机版本为 4.2.46( 1) -release, 仅取“4.2”显示
\\w : 完整的工作目录名称, 由根目录写起的目录名称。 但主文件夹会以 ~ 取代;
\\W : 利用 basename 函数取得工作目录名称, 所以仅会列出最后一个目录名。
# : 下达的第几个指令。
$ : 提示字符, 如果是 root 时, 提示字符为 # , 否则就是 $ 啰~

  • $: ( 关于本 shell 的 PID)
    钱字号本身也是个变量! 这个咚咚代表的是“目前这个 Shell 的线程代号”, 亦即是所谓的PID ( Process ID) 。 想要知道我们的 shell的 PID , 就可以用: “ echo $$ ”即可! 出现的数字就是你的 PID 号码。
  • ?: ( 关于上个执行指令的回传值)
    这个变量是: “上一个执行的指令所回传的值”, 当我们执行某些指令时, 这些指令都会回传一个执行后的代码。
    一般来说, 如果成功的执行该指令, 则会回传一个 0 值, 如果执行过程发生错误, 就会回传“错误代码”才对。
  • OSTYPE, HOSTTYPE, MACHTYPE: ( 主机硬件与核心的等级)

export: 自订变量转成环境变量

env 与 set 现在知道有所谓的环境变量与自订变量, 那么这两者之间有啥差异呢?
其实这两者的差异在于“ 该变量是否会被子程序所继续引用”。

当你登陆 Linux 并取得一个 bash 之后, 你的 bash 就是一个独立的程序, 这个程序的识别使用的是一个称为程序识别码, 被称为 PID 的就是。 接下来你在这个 bash 下面所下达的任何指令都是由这个 bash 所衍生出来的, 那些被下达的指令就被称为子程序了。 我们可以用下面的图示来简单的说明一下父程序与子程序的概念:

子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自订变量啦! 所以你在原本 bash 的自订变量在进入了子程序后就会消失不见, 一直到你离开子程序并回到原本的父程序后, 这个变量才会又出现。

export 指令就是将自订变量变成环境变量,可以让该变量值继续存在于子程序。

[dmtsai@study ~]$ export 变量名称

这东西用在“分享自己的变量设置给后来调用的文件或其他程序”。
像鸟哥常常在自己的主文件后面调用其他附属文件( 类似函数的功能) , 但是主文件与附属文件内都有相同的变量名称, 若一再重复设置时, 要修改也很麻烦, 此时只要在原本的第一个文件内设置好“ export变量 ”, 后面所调用的文件就能够使用这个变量设置了! 而不需要重复设置, 这非常实用于shell script 当中。
如果仅下达 export 而没有接变量时, 那么此时将会把所有的“环境变量”秀出来。

[dmtsai@study ~]$ export
declare -x HISTSIZE="1000"
declare -x HOME="/home/dmtsai"
declare -x HOSTNAME="study.centos.vbird"
declare -x LANG="zh_TW.UTF-8"
declare -x LC_ALL="en_US.utf8"

影响显示结果的语系变量 ( locale)

当我们使用 man command 的方式去查询某个数据的说明文档时, 该说明文档的内容可能会因为我们使用的语系不同而产生乱码。 另外, 利用 ls 查询文件的时间时, 也可能会有乱码出现在时间的部分。 那个问题其实就是语系
的问题。
可以由 locale 这个指令来查询 Linux 到底支持了多少的语系。

[dmtsai@study ~]$ locale -a
....( 前面省略) ....
zh_TW
zh_TW.big5 <==大五码的中文编码
zh_TW.euctw
zh_TW.utf8 <==万国码的中文编码
zu_ZA
zu_ZA.iso88591
zu_ZA.utf8

中文语系至少支持了两种以上的编码, 一种是目前还是很常见的 big5 , 另一种则是越来越热门的 utf-8 编码。
修订这些编码,可以通过下面这些变量:


[dmtsai@study ~]$ locale  	 <==后面不加任何选项与参数即可!
LANG=en_US                   <==主语言的环境
LC_CTYPE="en_US"             <==字符( 文字) 辨识的编码
LC_NUMERIC="en_US"           <==数字系统的显示讯息
LC_TIME="en_US"              <==时间系统的显示数据
LC_COLLATE="en_US"           <==字串的比较与排序等
LC_MONETARY="en_US"          <==币值格式的显示等
LC_MESSAGES="en_US"          <==讯息显示的内容, 如功能表、 错误讯息等
LC_ALL=                      <==整体语系的环境
....(後面省略)....

基本上, 你可以逐一设置每个与语系有关的变量数据, 但事实上, 如果其他的语系变量都未设置, 且你有设置 LANG 或者是 LC_ALL 时, 则其他的语系变量就会被这两个变量所取代

为什么在 Linux 主机的终端机接口 ( tty1 ~ tty6) 的环境下, 如果设置“ LANG=zh_TW.utf8 ”这个设置值生效后, 使用 man或者其他讯息输出时, 都会有一堆乱码, 尤其是使用 ls -l 这个参数时?
 
因为在 Linux 主机的终端机接口环境下是无法显示像中文这么复杂的编码文字, 所以就会产生乱码了。
也就是如此, 我们才会必须要在 tty1 ~ tty6 的环境下, 加装一些中文化接口的软件, 才能够看到中文。
不过, 如果你是在 MS Windows 主机以远端连线服务器的软件连线到主机的话, 那么, 其实命令行确实是可以看到中文的。 此时反而你得要在 LC_ALL设置中文编码。

整体系统默认的语系定义是在 /etc/locale.conf

[dmtsai@study ~]$ cat /etc/locale.conf
LANG=zh_TW.utf8
LC_NUMERIC=zh_TW.UTF-8
LC_TIME=zh_TW.UTF-8
LC_MONETARY=zh_TW.UTF-8
LC_PAPER=zh_TW.UTF-8
LC_MEASUREMENT=zh_TW.UTF-8

变量的有效范围

为什么环境变量的数据可以被子程序所引用呢? 这是因为内存配置的关系:

  • 当启动一个 shell, 操作系统会分配一记忆区块给 shell 使用, 此内存内之变量可让子程序取用
  • 若在父程序利用 export 功能, 可以让自订变量的内容写到上述的记忆区块当中( 环境变量) ;
  • 当载入另一个 shell 时 ( 亦即启动子程序, 而离开原本的父程序了) , 子 shell 可以将父shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。

变量键盘读取、 数组与定义: read, array, declare

上面提到的变量设置功能, 都是由命令行直接设置的。
变量设置可以让使用者能够经由键盘输入。及通过交互的方式设置变量。

read

要读取来自键盘输入的变量, 就是用 read 这个指令了。 这个指令最常被用在 shell script 的撰写当中

[dmtsai@study ~]$ read [-pt] variable
选项与参数:
-p : 后面可以接提示字符!
-t : 后面可以接等待的“秒数! ”这个比较有趣~不会一直等待使用者啦!

范例一: 让使用者由键盘输入一内容, 将该内容变成名为 atest 的变量
[dmtsai@study ~]$ read atest
This is a test          <==此时光标会等待你输入! 请输入左侧文字看看
[dmtsai@study ~]$ echo $atest
This is a test          <==你刚刚输入的数据已经变成一个变量内容!

范例二: 提示使用者 30 秒内输入自己的大名, 将该输入字串作为名为 named 的变量内容
[dmtsai@study ~]$ read -p "Please keyin your name: " -t 30 named
Please keyin your name: VBird Tsai   <==注意看, 会有提示字符喔!
[dmtsai@study ~]$ echo $named
VBird Tsai        <==输入的数据又变成一个变量的内容了!

declare / typeset

declare 或 typeset 是一样的功能, 就是在“定义变量的类型”。
如果使用 declare 后面并没有接任何参数, 那么 bash 就会主动的将所有的变量名称与内容通通叫出来, 就好像使用 set 一样。

[dmtsai@study ~]$ declare [-aixr] variable
选项与参数:
-a : 将后面名为 variable 的变量定义成为阵列 ( array) 类型
-i : 将后面名为 variable 的变量定义成为整数数字 ( integer) 类型
-x : 用法与 export 一样, 就是将后面的 variable 变成环境变量;
-r : 将变量设置成为 readonly 类型, 该变量不可被更改内容, 也不能 unset

范例一: 让变量 sum 进行 100+300+50 的加总结果
[dmtsai@study ~]$ sum=100+300+50
[dmtsai@study ~]$ echo $sum
100+300+50  <==咦! 怎么没有帮我计算加总? 因为这是文字体态的变量属性啊!
[dmtsai@study ~]$ declare -i sum=100+300+50
[dmtsai@study ~]$ echo $sum
450         <==知道了吗??

由于在默认的情况下面, bash 对于变量有几个基本的定义:

  • 变量类型默认为“字串”, 所以若不指定变量类型, 则 1+2 为一个“字串”而不是“计算式”。所以上述第一个执行的结果才会出现那个情况的;
  • bash 环境中的数值运算, 默认最多仅能到达整数形态, 所以 1/3 结果是 0;

数组( array) 变量类型

在 bash 里头, 数组的设置方式是:

范例: 设置 var[1] ~ var[3] 的变量。
[dmtsai@study ~]$ var[1]="small min"
[dmtsai@study ~]$ var[2]="big min"
[dmtsai@study ~]$ var[3]="nice min"
[dmtsai@study ~]$ echo "$var[1], $var[2], $var[3]"
small min, big min, nice min

与文件系统及程序的限制关系: ulimit

bash 是可以“限制使用者的某些系统资源”的, 包括可以打开的文件数量, 可以使用的 CPU 时间, 可以使用的内存总量等等。

[dmtsai@study ~]$ ulimit [-SHacdfltu] [配額]
选项与参数:
-H	 : hard limit , 严格的设置, 必定不能超过这个设置的数值;
-S	 : soft limit , 警告的设置, 可以超过这个设置值, 但是若超过则有警告讯息。
		在设置上, 通常 soft 会比 hard 小, 举例来说, soft 可设置为 80 而 hard
		设置为 100, 那么你可以使用到 90 ( 因为没有超过 100) , 但介于 80~100 之间时,
		系统会有警告讯息通知你!
-a	 : 后面不接任何选项与参数, 可列出所有的限制额度;
-c	 : 当某些程序发生错误时, 系统可能会将该程序在内存中的信息写成文件( 除错用) ,
		这种文件就被称为核心文件( core file) 。 此为限制每个核心文件的最大容量。
-f	 : 此 shell 可以创建的最大文件大小( 一般可能设置为 2GB) 单位为 KBytes
-d	 : 程序可使用的最大断裂内存( segment) 容量;
-l	 : 可用于锁定 ( lock) 的内存量
-t	 : 可使用的最大 CPU 时间 ( 单位为秒)
-u	 : 单一使用者可以使用的最大程序( process) 数量。

范例一: 列出你目前身份( 假设为一般帐号) 的所有限制数据数值
[dmtsai@study ~]$ ulimit -a
core file size          (blocks, -c) 0          <==只要是 0 就代表没限制
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited  <==可创建的单一文件的大小
pending signals                 (-i) 4903
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024       <==同时可打开的文件数量
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

范例二: 限制使用者仅能创建 10MBytes 以下的容量的文件
[dmtsai@study ~]$ ulimit -f 10240
[dmtsai@study ~]$ ulimit -a | grep \'file size\'
core file size          (blocks, -c) 0
file size               (blocks, -f) 10240 <==最大量为10240Kbyes, 相当10MBytes

[dmtsai@study ~]$ dd if=/dev/zero of=123 bs=1M count=20
File size limit exceeded (core dumped) <==尝试创建 20MB 的文件, 结果失败了!

[dmtsai@study ~]$ rm 123  <==赶快将这个文件删除啰! 同时你得要登出再次的登陆才能解开 10M 的限制

单一 filesystem 能够支持的单一文件大小与 block 的大小有关。 但是文件系统的限制容量都允许的太大了! 如果想要让使用者创建的文件不要太大时, 我们是可以考虑用 ulimit 来限制使用者可以创建的文件大小!
利用ulimit -f 就可以来设置了! 例如上面的范例二, 要注意单位! 单位是 KBytes。
若改天你一直无法创建一个大容量的文件, 记得瞧一瞧 ulimit 的信息

想要复原 ulimit 的设置最简单的方法就是登出再登陆, 否则就是得要重新以 ulimit 设置才行!
不过, 要注意的是, 一般身份使用者如果以 ulimit 设置了 -f 的文件大小, 那么他“只能继续减小文件大小, 不能增加文件大小。
另外, 若想要管控使用者的 ulimit 限值pam

变量内容的删除、 取代与替换 ( Optional)

变量除了可以直接设置来修改原本的内容之外,还可以通过简单的动作来将变量的内容进行微调。
如:进行变量内容的删除、 取代与替换等。

变量内容的删除与取代

从前面开始删除变量内容
范例一: 先让小写的 path 自订变量设置的与 PATH 内容相同
[dmtsai@study ~]$ path=$PATH
[dmtsai@study ~]$ echo $path
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
范例二: 假设我不喜欢 local/bin, 所以要将前 1 个目录删除掉, 如何显示?
[dmtsai@study ~]$ echo $path#/*local/bin:
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

# : 代表“从变量内容的最前面开始向右删除”, 且仅删除最短的那个。
/*local/bin: 代表要被删除的部分, 由于 # 代表由前面开始删除, 所以这里便由开始的 / 写起。需要注意的是, 这里通过万用字符 * 来取代 0 到无穷多个任意字符。

范例三: 我想要删除前面所有的目录, 仅保留最后一个目录
[dmtsai@study ~]$ echo $path#/*:
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 由于一个 # 仅删除掉最短的那个, 因此他删除的情况可以用下面的删除线来看:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
[dmtsai@study ~]$ echo $path##/*:
/home/dmtsai/bin
# 嘿! 多加了一个 # 变成 ## 之后, 他变成“删除掉最长的那个数据”! 亦即是:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin

# :匹配文字的『最短的』那一個;

:匹配文字的『最長的』那一個

从后面向前删除变量内容
范例四: 我想要删除最后面那个目录, 亦即从 : 到 bin 为止的字串
[dmtsai@study ~]$ echo $path%:*bin
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin
# 注意啊! 最后面一个目录不见去!
# 这个 % 符号代表由最后面开始向前删除! 所以上面得到的结果其实是来自如下:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
范例五: 那如果我只想要保留第一个目录呢?
[dmtsai@study ~]$ echo $path%%:*bin
/usr/local/bin
# 同样的, %% 代表的则是最长的符合字串, 所以结果其实是来自如下:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
取代
范例六: 将 path 的变量内容内的 sbin 取代成大写 SBIN:
[dmtsai@study ~]$ echo $path/sbin/SBIN
/usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 这个部分就容易理解的多了! 关键字在于那两个斜线, 两斜线中间的是旧字串
# 后面的是新字串, 所以结果就会出现如上述的特殊字体部分啰!
[dmtsai@study ~]$ echo $path//sbin/SBIN
/usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/SBIN:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 如果是两条斜线, 那么就变成所有符合的内容都会被取代喔!

总结说明:

变量设置方式说明
$变量#关键字
$变量##关键字
若变量内容从头开始的数据符合“关键字”, 则将符合的最短数据删除
若变量内容从头开始的数据符合“关键字”, 则将符合的最长数据删除
$变量%关键字
$变量%%关键字
若变量内容从尾向前的数据符合“关键字”, 则将符合的最短数据删除
若变量内容从尾向前的数据符合“关键字”, 则将符合的最长数据删除
$变量/旧字串/新字串
$变量//旧字串/新字串
若变量内容符合“旧字串”则“第一个旧字串会被新字串取代”
若变量内容符合“旧字串”则“全部的旧字串会被新字串取代”

变量的测试与内容替换

范例一: 测试一下是否存在 username 这个变量, 若不存在则给予 username 内容为 root
[dmtsai@study ~]$ echo $username  <==由于出现空白, 所以 username 可能不存在, 也可能是空字串
[dmtsai@study ~]$ username=$username-root
[dmtsai@study ~]$ echo $username
root <==因为 username 没有设置, 所以主动给予名为 root 的内容。
[dmtsai@study ~]$ username="vbird tsai" <==主动设置 username 的内容
[dmtsai@study ~]$ username=$username-root
[dmtsai@study ~]$ echo $username
vbird tsai <==因为 username 已经设置了, 所以使用旧有的设置而不以 root 取代

重点在于减号“ - ”后面接的关键字! 基本上你可以这样理解:
new_var=$old_var-content
新的变量, 主要用来取代旧变量。 新旧变量名称其实常常是一样的
new_var= $ old_var-content
这是本范例中的关键字部分! 必须要存在的!
new_var=$old_var-content
旧的变量, 被测试的项目!
new_var=$old_var-content
变量的“内容”, 在本范例中, 这个部分是在“给予未设置变量的内容”

因为 username 可能已经被设置为“空字串”。
果真如此的话, 那你还可以使用下面的方式来给予 username 的内容成为 root 。

范例二: 若 username 未设置或为空字串, 则将 username 内容设置为 root
[dmtsai@study ~]$ username=""
[dmtsai@study ~]$ username=$username-root
[dmtsai@study ~]$ echo $username
<==因为 username 被设置为空字串了! 所以当然还是保留为空字串!
[dmtsai@study ~]$ username=$username:-root
[dmtsai@study ~]$ echo $username
root <==加上“ : ”后若变量内容为空或者是未设置, 都能够以后面的内容替换!

加上冒号后, 被测试的变量未被设置或者是已被设置为空字串时,
都能够用后面的内容 ( 本例中是使用 root 为内容) 来替换与设置。

总结:
var 与 str 为变量, 我们想要针对 str 是否有设置来决定 var 的值;
str: 代表“str 没设置或为空的字串时”; 至于 str 则仅为“没有该变量”。

变量设置方式 str 没有设置 str 为空字串 str 已设置非为空字串
var=$ var=exp var= var=$str
var=$ var=exp var=expr var=$str
var=$ var= var=expr var=expr
var=$ var= var= var=expr
var=$ str=expr var=expr str 不变 var= str 不变 var=$str
var=$ str=expr var=expr str=expr var=expr str 不变 var=$str
var=$ expr 输出至 stderr var= var=$str
var=$ expr 输出至 stderr expr 输出至 stderr var=$str

例子:

测试: 先假设 str 不存在 ( 用 unset) , 然后测试一下减号 ( -) 的用法:
[dmtsai@study ~]$ unset str; var=$str-newvar
[dmtsai@study ~]$ echo "var=$var, str=$str"
var=newvar, str= <==因为 str 不存在, 所以 var 为 newvar
测试: 若 str 已存在, 测试一下 var 会变怎样? :
[dmtsai@study ~]$ str="oldvar"; var=$str-newvar
[dmtsai@study ~]$ echo "var=$var, str=$str"
var=oldvar, str=oldvar <==因为 str 存在, 所以 var 等于 str 的内容

关于减号 ( -) :
个减号的测试并不会影响到旧变量的内容。 如果你想要将旧变量内容也一起替换掉的话, 那么就使用等号( =)

测试: 先假设 str 不存在 ( 用 unset) , 然后测试一下等号 ( =) 的用法:
[dmtsai@study ~]$ unset str; var=$str=newvar
[dmtsai@study ~]$ echo "var=$var, str=$str"
var=newvar, str=newvar<==因为 str 不存在, 所以 var/str 均为 newvar
测试: 如果 str 已存在了, 测试一下 var 会变怎样?
[dmtsai@study ~]$ str="oldvar"; var=$str=newvar
[dmtsai@study ~]$ echo "var=$var, str=$str"
var=oldvar, str=oldvar<==因为 str 存在, 所以 var 等于 str 的内容

如果只是想知道, 如果旧变量不存在时, 整个测试就告知我“有错误”, 此时就能够使用问号“ ? ”的帮忙。

测试: 若 str 不存在时, 则 var 的测试结果直接显示 "无此变量"
[dmtsai@study ~]$ unset str; var=$str?无此变量
-bash: str: 无此变量 <==因为 str 不存在, 所以输出错误讯息
测试: 若 str 存在时, 则 var 的内容会与 str 相同!
[dmtsai@study ~]$ str="oldvar"; var=$str?novar
[dmtsai@study ~]$ echo "var=$var, str=$str"
var=oldvar, str=oldvar <==因为 str 存在, 所以 var 等于 str 的内容

命令别名与历史命令

命令别名设置: alias, unalias

指令别名设置
[dmtsai@study ~]$ alias lm=\'ls -al &#124; more\'
查看指令别名
[dmtsai@study ~]$ alias
alias egrep=\'egrep --color=auto\'
alias fgrep=\'fgrep --color=auto\'
alias grep=\'grep --color=auto\'
alias l.=\'ls -d .* --color=auto\'
alias ll=\'ls -l --color=auto\'
alias lm=\'ls -al | more\'
alias ls=\'ls --color=auto\'
alias rm=\'rm -i\'
alias vi=\'vim\'
alias which=\'alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde\'
取消别名
[dmtsai@study ~]$ unalias lm

历史命令: history

bash 有提供指令历史的服务

[dmtsai@study ~]$ history [n]
[dmtsai@study ~]$ history [-c]
[dmtsai@study ~]$ history [-raw] histfiles
选项与参数:
n  	: 数字, 意思是“要列出最近的 n 笔命令列表”的意思!
-c 	: 将目前的 shell 中的所有 history 内容全部消除
-a 	: 将目前新增的 history 指令新增入 histfiles 中, 若没有加 histfiles ,
则默认写入 ~/.bash_history
-r 	: 将 histfiles 的内容读到目前这个 shell 的 history 记忆中;
-w 	: 将目前的 history 记忆内容写入 histfiles 中!
范例一: 列出目前内存内的所有 history 记忆
[dmtsai@study ~]$ history
# 前面省略
1017 man bash
1018 ll
1019 history
1020 history
# 列出的信息当中, 共分两栏, 第一栏为该指令在这个 shell 当中的代码,
# 另一个则是指令本身的内容喔! 至于会秀出几笔指令记录, 则与 HISTSIZE 有关!
范例二: 列出目前最近的 3 笔数据
[dmtsai@study ~]$ history 3
1019 history
1020 history
1021 history 3
范例三: 立刻将目前的数据写入 histfile 当中
[dmtsai@study ~]$ history -w
# 在默认的情况下, 会将历史纪录写入 ~/.bash_history 当中!
[dmtsai@study ~]$ echo $HISTSIZE
1000

在正常的情况下, 历史命令的读取与记录是这样的:

  • 当我们以 bash 登陆 Linux 主机之后, 系统会主动的由主文件夹的 ~/.bash_history 读取以前曾经下过的指令, 那么 ~/.bash_history 会记录几笔数据呢? 这就与你 bash 的HISTFILESIZE 这个变量设置值有关了!
  • 假设我这次登陆主机后, 共下达过 100 次指令, “等我登出时, 系统就会将 101~1100 这总共 1000 笔历史命令更新到 ~/.bash_history 当中。 ” 也就是说, 历史命令在我登出时,会将最近的 HISTFILESIZE 笔记录到我的纪录档当中啦!
  • 当然, 也可以用 history -w 强制立刻写入的! 那为何用“更新”两个字呢? 因为~/.bash_history 记录的笔数永远都是 HISTFILESIZE 那么多, 旧的讯息会被主动的拿掉! 仅保留最新的!

history 这个历史命令不仅可以查询命令,还可以帮我们执行命令。

[dmtsai@study ~]$ !number
[dmtsai@study ~]$ !command
[dmtsai@study ~]$ !!
选项与参数:
number : 执行第几笔指令的意思;
command : 由最近的指令向前搜寻“指令串开头为 command”的那个指令, 并执行;
!! : 就是执行上一个指令( 相当于按↑按键后, 按 Enter)
[dmtsai@study ~]$ history
66 man rm
67 alias
68 man history
69 history
[dmtsai@study ~]$ !66 <==执行第 66 笔指令
[dmtsai@study ~]$ !! <==执行上一个指令, 本例中亦即 !66
[dmtsai@study ~]$ !al <==执行最近以 al 为开头的指令( 上头列出的第 67 个)

同一帐号同时多次登陆的 history 写入问题

bash 在同时以 同一个身份登陆,因此所有的 bash 都有自己的 1000 笔记录在内存中。
因为等到退出时才会更新记录文件, 所以, 最后登出的那个 bash 才会是最后写入的数据。
如此一来其他 bash 的指令操作就不会被记录下来了 ( 其实有被记录, 只是被后来的最后一个 bash 所覆盖更新) 。

无法记录时间

历史命令还有一个问题, 那就是无法记录指令下达的时间。 由于这 1000 笔历史命令是依序记录的, 但是并没有记录时间, 所以在查询方面会有一些不方便。

Bash Shell 的操作环境

路径与指令搜寻顺序

指令执行的顺序优先级)如下:
(以ls指令为例)

  1. 以相对/绝对路径执行指令, 例如“ /bin/ls ”或“ ./ls ”;
  2. 由 alias 找到该指令来执行
  3. 由 bash 内置的 ( builtin) 指令来执行
  4. 通过 $PATH 这个变量的顺序搜寻到的第一个指令来执行

如果想要了解指令搜寻的执行顺序, 其实通过 type -a ls 也可以查询得到。

[dmtsai@study ~]$ alias echo=\'echo -n\'
[dmtsai@study ~]$ type -a echo
echo is aliased to `echo -n\'
echo is a shell builtin
echo is /usr/bin/echo
## 可以清楚的看到先 alias 再 builtin(内建指令) 再由 $PATH 找到 /bin/echo

可以清楚的看到先 alias 再 builtin (内建指令)再由 $PATH 找到 /bin/echo

bash 的进站与欢迎信息: /etc/issue, /etc/motd

bash 可以设置登陆后进站画面与欢迎信息。
信息保存在 /etc/issue 里面

[dmtsai@study ~]$ cat /etc/issue
\\S
Kernel \\r on an \\m
## 默认登陆画面

如同 $PS1 这变量一样, issue 这个文件的内容也是可以使用反斜线作为变量取用

issue 内的各代码意义
\\d 本地端时间的日期;
\\l 显示第几个终端机接口;
\\m 显示硬件的等级 ( i386/i486/i586/i686...) ;
\\n 显示主机的网络名称;
\\O 显示 domain name;
\\r 操作系统的版本 ( 相当于 uname -r)
\\t 显示本地端时间的时间;
\\S 操作系统的名称;
\\v 操作系统的版本

除了 /etc/issue 之外还有个 /etc/issue.net ; 这个是提供给 telnet这个远端登陆程序用的。
当我们使用 telnet 连接到主机时, 主机的登陆画面就会显示/etc/issue.net 而不是 /etc/issue 。

至于如果您想要让使用者登陆后取得一些讯息, 例如您想要让大家都知道的讯息, 那么可以将讯息加入 /etc/motd 里面去。

[root@study ~]# vim /etc/motd
Hello everyone,
Our server will be maintained at 2015/07/10 0:00 ~ 24:00.
Please don\'t login server at that time. ^_^

那么当你的使用者( 包括所有的一般帐号与 root) 登陆主机后, 就会显示这样的讯息出来:

Last login: Wed Jul 8 23:22:25 2015 from 127.0.0.1
Hello everyone,
Our server will be maintained at 2015/07/10 0:00 ~ 24:00.
Please don\'t login server at that time. ^_^

bash 的环境配置文件

一进入 bash 就将取得一堆有用的变量
系统有一些环境设置文件的存在让 bash 在启动时直接读取这些配置文件,以规划好 bash 的操作环境
这些配置文件又可以分为全体系统的配置文件以及使用者个人偏好配置文件
要注意的是, 前几个小节谈到的命令别名、 自订的变量, 在你登出 bash 后就会失效, 所以你想要保留你的设置, 就得要将这些设置写入配置文件才行。

login 与 non-login shell

介绍 bash 的配置文件前, 我们一定要先知道的就是 login shellnon-login shell! 重点在于有没有登陆 ( login)
 

  • login shell取得 bash 时需要完整的登陆流程的, 就称为 login shell
    举例来说, 你要由tty1 ~ tty6 登陆, 需要输入使用者的帐号与密码, 此时取得的 bash 就称为“login shell”;
  • non-login shell: 取得 bash 接口的方法不需要重复登陆的举动;
    举例来说:
    ( 1) 你以 Xwindow 登陆 Linux 后, 再以 X 的图形化接口启动终端机, 此时那个终端接口并没有需要再次的输入帐号与密码, 那个 bash 的环境就称为 non-login shell了。
    ( 2) 你在原本的 bash 环境下再次下达 bash 这个指令, 同样的也没有输入帐号密码, 那第二个 bash( 子程序) 也是 non-login shell 。
     
    这两个取得 bash 的情况中, 读取的配置文件数据并不一样所致

一般来说, login shell 其实只会读取这两个配置文件:

  1. /etc/profile: 这是系统整体的设置, 你最好不要修改这个文件;
  2. ~/.bash_profile 或 ~/.bash_login 或 ~/.profile: 属于使用者个人设置, 你要改自己的数据, 就写入这里。

/etc/profile ( login shell 才会读):系统配置文件

这个配置文件可以利用使用者的识别码( UID) 来决定很多重要的变量数据, 这也是每个使用者登陆取得 bash 时一定会读取的配置文件! 所以如果你想要帮所有使用者设置整体环境, 那就是改这里。

  • PATH: 会依据 UID 决定 PATH 变量要不要含有 sbin 的系统指令目录;
  • MAIL: 依据帐号设置好使用者的 mailbox 到 /var/spool/mail/帐号名;
  • USER: 根据使用者的帐号设置此一变量内容;
  • HOSTNAME: 依据主机的 hostname 指令决定此一变量内容;
  • HISTSIZE: 历史命令记录笔数。 CentOS 7.x 设置为 1000 ;
  • umask: 包括 root 默认为 022 而一般用户为 002 等!
     

/etc/profile 可不止会做这些事而已, 他还会去调用外部的设置数据,在 CentOS 7.x 默认的情况下, 下面这些数据会依序的被调用进来:

  • /etc/profile.d/*.sh
    其实这是个目录内的众多文件!
    只要在 /etc/profile.d/ 这个目录内且扩展名为 .sh , 另外, 使用者能够具有 r 的权限, 那么该文件就会被 /etc/profile 调用进来。 在 CentOS 7.x 中, 这个目录下面的文件规范了 bash 操作接口的颜色、 语系、 ll 与 ls 指令的命令别名、 vi 的命令别名、 which 的命令别名等等。 如果你需要帮所有使用者设置一些共享的命令别名时, 可以在这个目录下面自行创建扩展名为 .sh 的文件, 并将所需要的数据写入即可
  • /etc/locale.conf
    这个文件是由 /etc/profile.d/lang.sh 调用进来的! 这也是我们决定 bash 默认使用何种语系的重要配置文件! 文件里最重要的就是 LANG/LC_ALL 这些个变量的设置。
  • /usr/share/bash-completion/completions/*
    记得我们上头谈过 [tab] 的妙用吧? 除了命令补齐、 文件名补齐之外, 还可以进行指令的选项/参数补齐功能! 那就是从这个目录里面找到相对应的指令来处理的! 其实这个目录下面的内容是由 /etc/profile.d/bash_completion.sh 这个文件载入的。
     

总结:反正你只要记得, bash 的 login shell 情况下所读取的整体环境配置文件其实只有/etc/profile但是 /etc/profile 还会调用出其他的配置文件, 所以让我们的 bash 操作接口变的非常的友善。

~/.bash_profile ( login shell 才会读):个人偏好的配置文件

bash 在读完了整体环境设置的 /etc/profile 并借此调用其他配置文件后, 接下来则是会读取使用者的个人配置文件。 在 login shell 的 bash 环境中, 所读取的个人偏好配置文件其实主要有三个, 依序分别是:

  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile

其实 bash 的 login shell 设置只会读取上面三个文件的其中一个, 而读取的顺序则是依照上面的顺序。
也就是说, 如果 ~/.bash_profile 存在, 那么其他两个文件不论有无存在, 都不会被读取。 如果 ~/.bash_profile 不存在才会去读取 ~/.bash_login, 而前两者都不存在才会读取~/.profile 的意思。 会有这么多的文件, 其实是因应其他 shell 转换过来的使用者的习惯而已。

[dmtsai@study ~]$ cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then    <==下面这三行在判断并读取 ~/.bashrc
        . ~/.bashrc  		 <== source指令 : 读入文件的指令
fi

# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin    <==下面这几行在处理个人化设置
export PATH

这个文件内有设置 PATH 这个变量;
而且还使用了 export 将 PATH 变成环境变量;
由于PATH 在 /etc/profile 当中已经设置过, 所以在这里就以累加的方式增加使

linux学习笔记——基础命令快捷键与认识虚拟机

虚拟机
[[email protected] Desktop]$ rht-vmctl start desktop     ###开启
Starting desktop.
[[email protected] Desktop]$ rht-vmctl view desktop    ##显示
[[email protected] Desktop]$ rht-vmctl stop desktop    ##正常关闭虚拟机
[[email protected] Desktop]$ rht-vmctl poweroff desktop    ###强行关闭

[[email protected] Desktop]$ rht-vmctl reset desktop    ###重置虚拟机
[[email protected] Desktop]$ rht-vmctl fullreset desktop    ####完全重置


gnome-terminal  gnome:linux系统下的桌面 terminal:终端


not list ----->  username :root --------->passwd: redhat



#############################shell############################
什么是shell? 解释器,用于保护内核。
bash(bource again shell)是shell很多类型的一种,是Bourne shell的扩展,特性加强版。
[[email protected] Desktop]$ gnome-terminal    ###用命令开启bash
[[email protected] Desktop]$ exit ###关闭当前的shell

[[email protected] Desktop]$
kioks        ##开启shell的用户
@        ##分隔符
foundation0    ##主机的短名称,表示shell开启在那台主机里
Desktop        ##表示你在系统的什么位置
$        ##身份提示符中的普通用户,超级用户的提示符为:#


###################切换用户#################
[[email protected] Desktop]$ su - 系统中已经存在用户名字  ####切换用户身份



######################虚拟控制台###################
ctrl+alt+f2-f6    ####进入虚拟控制台
ctrl+alt+F1|F7    ####回到图形
 


####################在shell中如何使用命令###################
1.命令一定要在提示符之后输入
2.命令的输入方式
命令    参数    目标
参数是命令功能的指定
-参数        ####单词的缩写
--参数        ####单词的全拼
3.帮助
命令    --help
【内容】    ###内容选加
<内容>    ###内容必加
内容...    ###内容个数任意
4.
ctrl +c    ###撤销未执行的命令



##############################gnome中的常规操作###########
1.login
for gui
for text

2.
ctrl+alt+上|下    ####切换工作界面

3.
ctrl+alt+L    ###锁屏

4.
shell打开方式
右健
applications-->常用---->shell
设定快捷键    gnome-terminal

5.系统从新初始化
关机
poweroff|init 0|shutdown -h now     ###-h 关闭电源
重启
reboot| init 6 |shutdown -r now     ###-r 关机后重启


###############################简单命令############33
date

watch -n 1 date            ##监测date命令每秒钟执行一次
 -n 间隔时间
 -d 变动的地方高亮显示

date 月月天天小时分钟.秒秒        ##更改时间


passwd

passwd  username    ###更改用户密码(只有超级用户root可以)

passwd            ####普通用户修改自己的密码

普通用户只能修改自己的密码,并且必须知道自己原始密码,修改密码必须大于8位,不能与原始密码字符重复

passwd -l    username        ###冻结普通用户
passwd -u    username        ###解锁冻结帐号



file    ###查看文件类型

cat        文件名称         ###查看文件所有内容到文件的最后,显示到当前终端
less        文件名称         ###查看文件所有内容从文件的开始,按Q退出
head -数字    文件名称      ###文件内容前多少
tail -数字    文件名称         ###文件内容后多少

wc    -l    ###行数
        -c    ###字节数
        -m    ###字符数
        -w    ###单词数
        -L    ###显示最长行的长度


tab键
补齐系统中存在的文件名称,命令,和命令参数

#####################历史调用#################
!数字                ###执行第多少条命令
!关键字            ###执行最近一条以关键字开头的命令
ctrl+R+关键字    ###调出最近一条含有关键字的命令
上下键            ###从最后一条命令开始向前查看或者向后查看
history            ###查看历史
history -c        ###清除历史

######################快捷键###################
ctrl    + a    光标移动到行首
    + e    光标移动到行尾
    + u    光标所在位置删除到行首
    + k    光标所在位置删除到行尾
    + r    调出最近一条含有关键字的命令
    + 左|右    光标移动以单词为单位
    + c    撤销以输入的命令
    + d    关闭当前环境
    + shift + t ##在现有shell中重新打开一个table     
    + shift + pageup|pagedown 切换table
    + alt + l    锁屏
    + alt +上|下    切换工作界面
    + alt + f1|f7    进入图形界面
    + alt + f2-f6    进入虚拟控制台

本文出自 “12148275” 博客,请务必保留此出处http://12158275.blog.51cto.com/12148275/1896940

以上是关于Linux笔记:2-认识与学习BASH的主要内容,如果未能解决你的问题,请参考以下文章

认识与学习BASH

认识与学习BASH

第十一章认识与学习 BASH

linux学习笔记——基础命令快捷键与认识虚拟机

linux学习笔记——IP网关DNS的认识与设定网络端口监测

Linux学习笔记:bash特性之多命令执行,shell脚本