linux-basic(11)认识和学习bash

【11.1】认识bash这个shell
1)介绍:其实壳程序的功能只是提供用户操作系统的一个接口,因此这个壳程序需要可以呼叫其他软件才好。命令,包括 man, chmod, chown, vi, fdisk, mkfs 等等命令,这些命令都是独立的应用程序, 但是我们可以透过壳程序 (就是命令列模式) 来操作这些应用程序,让这些应用程序呼叫核心来运行所需的工作哩! 也就是说,只要能够操作应用程序的接口都能够称为shell,即壳程序。

【11.1.3】
1)那么目前我们的 Linux (以 CentOS 5.x 为例) 有多少我们可以使用的 shells 呢? 你可以检查一下 /etc/shells 这个文件,至少就有底下这几个可以用的 shells:

(1)
补充:bash == Bourne Again SHell, 这个shell是 Bourne Shell的增强版本,基于GNU的架构下发展出来的。
2)为什么我们系统上合法的 shell 要写入 /etc/shells 这个文件啊? 这是因为系统某些服务在运行过程中,会去检查使用者能够使用的 shells ,而这些 shell 的查询就是藉由 /etc/shells 这个文件啰!
3)我这个用户什么时候可以取得 shell 来工作呢?还有, 我这个使用者默认会取得哪一个 shell 啊?
看个荔枝:  当我登陆的时候,系统就会给我一个 shell 让我来工作了。 而这个登陆取得的 shell 就记录在 /etc/passwd 这个文件内!这个文件的内容是啥?

(2)
【11.1.4】bash shell的功能
1)bash 优点如下:
命令记忆功能;
命令与文件补全功能;
命令别名设置功能;
作用控制,前后台控制;
程序脚本;
通配符;
【11.1.5】bash shell的内置命令:type
【荔枝】type命令:怎么知道这个命令是来自于外部命令(指的是其他非 bash 所提供的命令) 或是内建在 bash 当中的呢。

(3)
(4)
总结:type 主要在找出执行文件而不是一般文件名!所以,这个 type 也可以用来作为类似 which 命令的用途啦;

【11.2】shell的变量功能
【11.2.1】什么是变量?

变量的可变性与方便性;
影响bash环境操作的变量;
脚本程序设计的帮手;

【11.2.2】变量的显示与设置:echo, unset 
1)变量显示 echo
(5)
【荔枝】变量设置与显示

(6)
(7)
(8)
补充:什么是『子程序』呢?就是说,在我目前这个 shell 的情况下,去激活另一个新的 shell ,新的那个 shell 就是子程序啦!在一般的状态下,父程序的自定义变量是无法在子程序内使用的。但是透过 export 将变量变成环境变量后,就能够在子程序底下应用了!

(9)
补充:其实上面的命令可以说是作了两次动作,亦即是:
  1. 先进行反单引号内的动作『uname -r』并得到核心版本为 2.6.18-128.el5
  2. 将上述的结果带入原命令,故得命令为:『cd /lib/modules/2.6.18-128.el5/kernel/』

【荔枝】在变量的配置当中,单引号与双引号的用途有何不同?
答:单引号与双引号的最大不同在于双引号仍然可以保有变量的内容,但单引号内仅能是一般字符 ,而不会有特殊符号。

(10)
【荔枝】反单引号 `(~破浪号的兄弟)代表何种意义?
在一串命令中,在 ` 之内的命令将会被先运行,而其运行出来的结果将做为外部的输入信息!例如 uname -r 会显示出目前的核心版本,而我们的核心版本在 /lib/modules 里面,因此,你可以先运行 uname -r 找出核心版本,然后再以『 cd 目录』到该目录下,当然也可以运行如同上面范例六的运行内容啰。

(11)
【注意】老实说,使用『 version=$(uname -r) 』来取代『 version=`uname -r` 』比较好,因为反单引号大家老是容易打错或看错! 所以现在鸟哥都习惯使用 $( 命令 ) 来介绍这个功能!

【11.2.3】环境变量的功能
1)目前我的 shell 环境中, 有多少默认的环境变量啊?我们可以利用两个命令来查阅,分别是 env 与 export 呢!
【荔枝】用 env 观察环境变量与常见环境变量说明

(12)
环境变量分析如下:
home:用户的主文件夹;
shell:目前这个环境使用的是哪个shell程序;
histsize:记录多少条历史命令;
mail:当我们使用 mail 这个命令在收信时,系统会去读取的邮件信箱文件 (mailbox)。
path:就是执行文件搜寻的路径啦~目录与目录中间以冒号(:)分隔, 由于文件的搜寻是依序由 PATH 的变量内的目录来查询,所以,目录的顺序也是重要的喔。
lang:语系数据;一般来说,我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,这两个编码偏偏不容易被解译出来,所以,有的时候,可能需要修订一下语系数据。 

RANDOM:随机数变量;目前大多数的 distributions 都会有随机数生成器,那就是 /dev/random 这个文件。 我们可以透过这个随机数文件相关的变量 ($RANDOM) 来随机取得随机数值喔。
在 BASH 的环境下,这个 RANDOM 变量的内容,介于 0~32767 之间,所以,你只要 echo $RANDOM 时,系统就会主动的随机取出一个介于 0~32767 的数值。万一我想要使用 0~9 之间的数值呢?呵呵~利用 declare 宣告数值类型, 然后这样做就可以了:

【荔枝】RANDOM随机数生成器

(13)
2)用set 查看所有变量(含有环境变量与自定义变量)
2.1)bash 可不只有环境变量喔,还有一些与 bash 操作接口有关的变量,以及用户自己定义的变量存在的。
2.2)set 除了环境变量之外, 还会将其他在 bash 内的变量通通显示出来哩!
[root@server-2 ~]# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="1" [2]="2" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu")
BASH_VERSION='4.1.2(1)-release'
COLORS=/etc/DIR_COLORS
COLUMNS=102
DIRSTACK=()
EUID=0
GROUPS=()
G_BROKEN_FILENAMES=1
HISTCONTROL=ignoredups
HISTFILE=/root/.bash_history
HISTFILESIZE=1000
HISTSIZE=1000
HOME=/root
HOSTNAME=server-2
HOSTTYPE=i386
ID=0
IFS=$' \t\n'
JAVA_HOME=/usr/local/software/java/jdk1.8.0_162
JRE_HOME=/usr/local/software/java/jdk1.8.0_162/jre
KAFKA_HOME=/usr/local/software/kafka/kafka_2.12-1.1.0
LANG=zh_CN.UTF-8
LESSOPEN='|/usr/bin/lesspipe.sh %s'
LINES=29
LOGNAME=root
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;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:'
MACHTYPE=i386-redhat-linux-gnu
MAIL=/var/spool/mail/root
MAILCHECK=60
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/nginx/sbin:/usr/local/git/bin:/usr/local/software/java/jdk1.8.0_162/bin:/usr/local/software/java/jdk1.8.0_162/jre/bin:/usr/local/software/zookeeper/zookeeper-3.4.11/bin:/usr/local/software/kafka/kafka_2.12-1.1.0/bin:/sbin:/root/bin
PIPESTATUS=([0]="0")
PPID=1285
PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
PS1='[\u@\h \W]\$ '
PS2='> '
PS4='+ '
PWD=/root
SELINUX_LEVEL_REQUESTED=
SELINUX_ROLE_REQUESTED=
SELINUX_USE_CURRENT_RANGE=
SHELL=/bin/bash
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
SHLVL=1
SSH_CLIENT='192.168.186.1 50886 22'
SSH_CONNECTION='192.168.186.1 50886 192.168.186.103 22'
SSH_TTY=/dev/pts/0
TERM=xterm
UID=0
USER=root
ZOOKEEPER_HOME=/usr/local/software/zookeeper/zookeeper-3.4.11
_=clear
colors=/etc/DIR_COLORS
【荔枝】几个重要的变量如下:
环境变量1)PS1:(提示字符的配置): 是 PS1 (数字的 1 不是英文字母),这个东西就是我们的『命令提示字符』喔! 当我们每次按下 [Enter] 按键去运行某个命令后,最后要再次出现提示字符时, 就会主动去读取这个变量值了。
你可以用 man bash (注3)去查询一下 PS1 的相关说明,以理解底下的一些符号意义。
  ● \d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"
  ● \H :完整的主机名。举例来说,鸟哥的练习机为『www.vbird.tsai』
  ● \h :仅取主机名在第一个小数点之前的名字,如鸟哥主机则为『www』后面省略
  ● \t :显示时间,为 24 小时格式的『HH:MM:SS』
  ● \T :显示时间,为 12 小时格式的『HH:MM:SS』
  ● \A :显示时间,为 24 小时格式的『HH:MM』
  ● \@ :显示时间,为 12 小时格式的『am/pm』样式
  ● \u :目前使用者的账号名称,如『root』;
  ● \v :BASH 的版本信息,如鸟哥的测试主板本为 3.2.25(1),仅取『3.2』显示
  ● \w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;
  ● \W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。
  ● \# :下达的第几个命令。
  ● \$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ 啰~
环境变量2)$:(关于本 shell 的 PID): 钱字号本身也是个变量喔!这个咚咚代表的是『目前这个 Shell 的线程代号』,亦即是所谓的 PID (Process ID)。
环境变量3)问号?: 表示上一个执行命令的回传值;

(14)
3)export:自定义变量转换为环境变量
3.1)介绍: 这两者的差异在于 该变量是否被子进程所继续引用;
3.2)这个程序概念与变量有啥关系啊?  因为子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量啦!所以你在原本 bash 的自定义变量在进入了子程序后就会消失不见, 一直到你离开子程序并回到原本的父程序后,这个变量才会又出现!
3.3)export 变量名称, 把自定义变量转换为环境变量
3.4)如果仅下达 export 而没有接变量时,那么此时将会把所有的『环境变量』秀出来喔!例如:
[root@server-2 ~]# export
declare -x G_BROKEN_FILENAMES="1"
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="server-2"
declare -x JAVA_HOME="/usr/local/software/java/jdk1.8.0_162"
declare -x JRE_HOME="/usr/local/software/java/jdk1.8.0_162/jre"
declare -x KAFKA_HOME="/usr/local/software/kafka/kafka_2.12-1.1.0"
declare -x LANG="zh_CN.UTF-8"
declare -x LESSOPEN="|/usr/bin/lesspipe.sh %s"
declare -x LOGNAME="root"
declare -x 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;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:"
declare -x MAIL="/var/spool/mail/root"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/nginx/sbin:/usr/local/git/bin:/usr/local/software/java/jdk1.8.0_162/bin:/usr/local/software/java/jdk1.8.0_162/jre/bin:/usr/local/software/zookeeper/zookeeper-3.4.11/bin:/usr/local/software/kafka/kafka_2.12-1.1.0/bin:/sbin:/root/bin"
declare -x PWD="/root"
declare -x SELINUX_LEVEL_REQUESTED=""
declare -x SELINUX_ROLE_REQUESTED=""
declare -x SELINUX_USE_CURRENT_RANGE=""
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_CLIENT="192.168.186.1 50886 22"
declare -x SSH_CONNECTION="192.168.186.1 50886 192.168.186.103 22"
declare -x SSH_TTY="/dev/pts/0"
declare -x TERM="xterm"
declare -x USER="root"
declare -x ZOOKEEPER_HOME="/usr/local/software/zookeeper/zookeeper-3.4.11"
【11.2.4】影响显示结果的语系变量 locale
1)查看 locale 变量

(15)
补充1: 事实上,如果其他的语系变量都未配置, 且你有配置 LANG 或者是 LC_ALL 时,则其他的语系变量就会被这两个变量所取代! 这也是为什么我们在 Linux 当中,通常说明仅配置 LANG 这个变量而已,因为他是最主要的配置变量!
补充2:那么你应该要觉得奇怪的是,为什么在 Linux 主机的终端机接口 (tty1 ~ tty6) 的环境下,如果配置『 LANG=zh_TW.big5 』这个配置值生效后,使用 man 或者其他信息输出时, 都会有一堆乱码,尤其是使用 ls -l 这个参数时?
因为在 Linux 主机的终端机接口环境下是无法显示像中文这么复杂的编码文字, 所以就会产生乱码了。也就是如此,我们才会必须要在 tty1 ~ tty6 的环境下, 加装一些中文化接口的软件,才能够看到中文啊!

3)整体系统默认的语系定义在 /etc/sysconfig/i18n
(16 )
【11.2.5】变量的有效范围
1)环境变量 == 全局变量; 自定义变量 == 局部变量;

【11.2.6】变量键盘读取、数组与宣告: read, array, declare
1)read:读取键盘输入;
(17)
【荔枝】

(18)

(19)
2)declare/typeset:等同于typeset,声明变量类型;

(20)
【荔枝】

(21)
2.1)由于在默认的情况底下, bash 对于变量有几个基本的定义:
  ● 变量类型默认为『字符串』,所以若不指定变量类型,则 1+2 为一个『字符串』而不是『计算式』。 所以上述第一个运行的结果才会出现那个情况的;
  ● bash 环境中的数值运算,默认最多仅能到达整数形态,所以 1/3 结果是 0;

【其他荔枝】
(22)
3)数组类型
(23)
【11.2.7】与文件系统及程序的限制关系:ulimit
1)ulimit作用: bash 是可以『限制用户的某些系统资源』的,包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等。如何配置?用 ulimit 吧!
(24)
【荔枝】ulimit
(25)
(26)
补充:想要复原 ulimit 的配置最简单的方法就是注销再登陆,否则就是得要重新以 ulimit 配置才行!

【11.2.8】变量内容的删除,替代与替换
1)变量内容的删除
1.1)从头到右删除
(27)
【注意】更正提示:第2个注释改为“从头到右删除匹配 /*bin: 的最长字符串”;
补充:# 与 ## 就分别代表:
  ● # :符合取代文字的『最短的』那一个;
  ● ##:符合取代文字的『最长的』那一个
1.2)从尾到左删除
(28)
【注意】更正提示:第2个注释改为“从头到右删除匹配 :*bin: 的最长字符串”;
2)变量替换
(29)
3)变量的删除,替换总结如下:
(30)
4)变量测试:判断某个变量是否存在?
(31)
补充:在大括号内有没有冒号『 : 』的差别是很大的!加上冒号后,被测试的变量未被配置或者是已被配置为空字符串时, 都能够用后面的内容 (本例中是使用 root 为内容) 来替换与配置!
(32)
4.1)其他测试方法,如下: 
底下的例子当中,那个 var 与 str 为变量,我们想要针对 str 是否有配置来决定 var 的值喔! 一般来说, str: 代表『str 没配置或为空的字符串时』;至于 str 则仅为『没有该变量』。
(33)
4.2)根据上表给出荔枝如下:
(34)
5)关于减号 (-) 其实上面我们谈过了!这里的测试只是要让你更加了解,这个减号的测试并不会影响到旧变量的内容。 如果你想要将旧变量内容也一起替换掉的话,那么就使用等号 (=) 吧!
(35)
6)如果旧变量不存在时,整个测试就告知我『有错误』,此时就能够使用问号『 ? 』的帮忙啦!
(36)
【11.3】命令别名与历史命令
【11.3.1】命令别名设置:alias, unalias

(37)
注意1:alias 的定义规则与变量定义规则几乎相同。

【荔枝】如何知道别名列表
(38)
【11.3.2】历史命令:history
(39)
1)history命令介绍
(40)
【荔枝如下】
(41)
2)在正常的情况下,历史命令的读取与记录是这样的:
  ● 当我们以 bash 登陆 Linux 主机之后,系统会主动的由家目录的 ~/.bash_history 读取以前曾经下过的命令,那么 ~/.bash_history 会记录几笔数据呢?这就与你 bash 的 HISTFILESIZE 这个变量配置值有关了!
  ● 假设我这次登陆主机后,共下达过 100 次命令,『等我注销时, 系统就会将 101~1100 这总共 1000 笔历史命令升级到 ~/.bash_history 当中。』 也就是说,历史命令在我注销时,会将最近的 HISTFILESIZE 笔记录到我的纪录文件当中啦!
  ● 当然,也可以用 history -w 强制立刻写入的!那为何用『升级』两个字呢? 因为 ~/.bash_history 记录的笔数永远都是 HISTFILESIZE 那么多,旧的信息会被主动的拿掉! 仅保留最新的!
3)history的其他作用
(42)
(43)
【11.4】bash shell 的操作环境
【11.4.1】路径与命令查找顺序

1)命令运行的顺序可以这样看:
  1. 以相对/绝对路径运行命令,例如『 /bin/ls 』或『 ./ls 』;
  2. 由 alias 找到该命令来运行;
  3. 由 bash 内建的 (builtin) 命令来运行;
  4. 透过 $PATH 这个变量的顺序搜寻到的第一个命令来运行。
(上面的顺序貌似不正确的,应该 先通过 alias查找,再通过 相对或绝对路径查找)

【荔枝1】你可以下达 /bin/ls 及单纯的 ls 看看,会发现使用 ls 有颜色但是 /bin/ls 则没有颜色。 因为 /bin/ls 是直接取用该命令来下达,而 ls 会因为『 alias ls='ls --color=tty' 』这个命令别名而先使用!
(44)
【荔枝】如果想要了解命令搜寻的顺序,其实透过 type -a ls 也可以查询的到啦!上述的顺序最好先了解喔!
(45)
【11.4.2】bash的登录与欢迎信息: /etc/issue, /etc/motd
1)还记得在终端机接口 (tty1 ~ tty6) 登陆的时候,会有几行提示的字符串吗?那就是进站画面啊! 那个字符串写在哪里啊?呵呵!在 /etc/issue 里面。
(46)
(47)
注意:更改上述注释为登录界面,而不是欢迎信息;

2)可以 man issue 配合 man mingetty 得到底下的结果:
(48)
(49)
【11.4.3】bash的环境配置文件
1)你是否会觉得奇怪,怎么我们什么动作都没有进行,但是一进入 bash 就取得一堆有用的变量了? 这是因为系统有一些环境配置文件的存在,让 bash 在启动时直接读取这些配置文件,以规划好 bash 的操作环境啦!
2)如果想保留用户我自己的命令别名,自定义变量,就需要把这些设置信息写入到配置文件, 如下:
2.1)login 与 non-login shell:
2.2)/etc/profile (login shell 才会读)
2.2.1)这个文件配置的变量主要有:
  ● PATH:会依据 UID 决定 PATH 变量要不要含有 sbin 的系统命令目录;
  ● MAIL:依据账号配置好使用者的 mailbox 到 /var/spool/mail/账号名;
  ● USER:根据用户的账号配置此一变量内容;
  ● HOSTNAME:依据主机的 hostname 命令决定此一变量内容;
  ● HISTSIZE:历史命令记录笔数。CentOS 5.x 配置为 1000 ;
2.2.2)/etc/profile 可不止会做这些事而已,他还会去呼叫外部的配置数据喔!在 CentOS 5.x 默认的情况下, 底下这些数据会依序的被呼叫进来:
/etc/inputrc:不建议修改;
/etc/profile.d/*.sh: 只要在 /etc/profile.d/ 这个目录内且扩展名为 .sh ,另外,使用者能够具有 r 的权限, 那么该文件就会被 /etc/profile调用。在 CentOS 5.x 中,这个目录/etc/profile 底下的文件规范了 bash 操作接口的颜色、 语系、ll 与 ls 命令的命令别名、vi 的命令别名、which 的命令别名等等。如果你需要帮所有使用者配置一些共享的命令别名时, 可以在这个目录底下自行创建扩展名为 .sh 的文件,并将所需要的数据写入即可喔!
(50)
/etc/sysconfig/i18n: 这个文件是由 /etc/profile.d/lang.sh 调用的!这也是我们决定 bash 默认使用何种语系的重要配置文件! 文件里最重要的就是 LANG 这个变量的配置啦!
[root@localhost ~]# cat /etc/sysconfig/i18n
LANG="zh_CN.UTF-8"
总结:反正你只要记得,bash 的 login shell 情况下所读取的整体环境配置文件其实只有 /etc/profile;

2.3)~/.bash_profile (login shell 才会读): bash 在读完了整体环境配置的 /etc/profile 并藉此调用其他配置文件后,接下来则是会读取使用者的个人配置文件。 在 login shell 的 bash 环境中,所读取的个人偏好配置文件其实主要有三个,依序分别是:
  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile
2.3.1)注意:其实 bash 的 login shell 配置只会读取上面三个文件的其中一个, 而读取的顺序则是依照上面的顺序。也就是说,如果 ~/.bash_profile 存在,那么其他两个文件不论有无存在,都不会被读取。 如果 ~/.bash_profile 不存在才会去读取 ~/.bash_login,而前两者都不存在才会读取 ~/.profile 的意思。 会有这么多的文件,其实是因应其他 shell 转换过来的使用者的习惯而已。

【荔枝】~/.bash_profile 的文件内容
(51)
2.3.2)bash 配置文件的读入方式比较有趣,主要是透过一个命令『 source 』来读取的!也就是说 ~/.bash_profile 其实会再调用 ~/.bashrc 的配置内容喔!
2.4)最后,我们来看看整个 login shell 的读取流程:
(52)
2.4.1)source命令:读入环境配置文件的命令。修改参数配置,如/etc/profile 文件后,通常情况下,需要重启后才生效;而输入 source /etc/profile 可以将修改内容立即生效;
(53)
2.5)~/.bashrc (non-login shell 会读):
(54)
2.5.1)CentOS 5.x 还会主动调用 /etc/bashrc 这个文件喔!为什么需要调用 /etc/bashrc 呢? 因为 /etc/bashrc 帮我们的 bash 定义出底下的数据:
  ● 依据不同的 UID 规范出 umask 的值;
  ● 依据不同的 UID 规范出提示字符 (就是 PS1 变量);
  ● 调用 /etc/profile.d/*.sh 的配置
【注意】你要注意的是,这个 /etc/bashrc 是 CentOS 特有的 (其实是 Red Hat 系统特有的),其他不同的 distributions 可能会放置在不同的档名就是了。由于这个 ~/.bashrc 会呼叫 /etc/bashrc 及 /etc/profile.d/*.sh , 所以,万一你没有 ~/.bashrc (可能自己不小心将他删除了),那么你会发现你的 bash 提示字符可能会变成这个样子:
-bash-3.2$  

【11.4.4】终端机的环境设置: stty, set
1)那么如何查阅目前的一些按键内容呢?可以利用 stty (setting tty 终端机的意思) 呢! stty 也可以帮助配置终端机的输入按键代表意义喔!
(55)
(56)
[root@localhost ~]# stty -a
speed 38400 baud; rows 45; columns 102; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel
-iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
分析1)如果出现 ^ 表示 [Ctrl] 那个按键的意思。举例来说, intr = ^C 表示利用 [ctrl] + c 来达成的。
分析2)几个重要的代表意义是:
  ● eof   : End of file 的意思,代表『结束输入』。
  ● erase : 向后删除字符,
  ● intr  : 送出一个 interrupt (中断) 的讯号给目前正在 run 的程序;
  ● kill  : 删除在目前命令列上的所有文字;
  ● quit  : 送出一个 quit 的讯号给目前正在 run 的程序;
  ● start : 在某个程序停止后,重新启动他的 output
  ● stop  : 停止目前屏幕的输出;
  ● susp  : 送出一个 terminal stop 的讯号给正在 run 的程序。
【荔枝】如果你想要用 [ctrl]+h 来进行字符的删除,那么可以下达: stty erase ^h

2)set的设置功能:我们之前提到一些变量时,可以利用 set 来显示,除此之外,其实 set 还可以帮我们配置整个命令输出/输入的环境。 例如记录历史命令、显示错误内容等等。

(57)
(58)
(59)
(60)
【补充】/etc/inputrc 文件中存储了其他按键设置功能:
[root@localhost ~]# cat /etc/inputrc
# do not bell on tab-completion
#set bell-style none


set meta-flag on
set input-meta on
set convert-meta off
set output-meta on


# Completed names which are symbolic links to
# directories have a slash appended.
set mark-symlinked-directories on


$if mode=emacs


# for linux console and RH/Debian xterm
"\e[1~": beginning-of-line
"\e[4~": end-of-line
# commented out keymappings for pgup/pgdown to reach begin/end of history
#"\e[5~": beginning-of-history
#"\e[6~": end-of-history
"\e[5~": history-search-backward
"\e[6~": history-search-forward
"\e[3~": delete-char
"\e[2~": quoted-insert
"\e[5C": forward-word
"\e[5D": backward-word
"\e[1;5C": forward-word
"\e[1;5D": backward-word


# for rxvt
"\e[8~": end-of-line
"\eOc": forward-word
"\eOd": backward-word


# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
"\eOH": beginning-of-line
"\eOF": end-of-line


# for freebsd console
"\e[H": beginning-of-line
"\e[F": end-of-line
$endif
【总结】bash 默认的组合键汇总如下:
(61)
【11.4.5】通配符与特殊符号
1)常用通配符如下:
(62)
2)通配符荔枝
2.1)利用通配符配合 ls 查找文件看看:荔枝如下:
(63)
(64)
(65)
(66)
2.2)bash 环境中的特殊符号有哪些呢?
(67)
【注意】以上为 bash 环境中常见的特殊符号汇整!理论上,你的文件名尽量不要使用到上述的字符啦。

【11.5】数据流重定向
【11.5.1】什么是数据流重定向?

1)数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!
2)数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:
  1. 标准输入  (stdin) :代码为 0 ,使用 < 或 << ;
  2. 标准输出  (stdout):代码为 1 ,使用 > 或 >> ;
  3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;
(68)
【补充】
补充1)符号 > 表示覆盖文件内容; 符号 >> 表示追加内容到文件;
补充2)rootfile文件的创建方式是:
  1. 该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他创建起来,但是
  2. 当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入!
  3. 也就是若以 > 输出到一个已存在的文件中,那个文件就会被覆盖掉啰!

3)上面谈到的是 standard output 的正确数据,那如果是 standard error output 的错误数据呢?那就透过 2> 及 2>> 啰!同样是覆盖 (2>) 与累加 (2>>) 的特性!详情如下:
  ● 1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
  ● 1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
  ● 2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
  ● 2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;

【荔枝】将 stdout 与 stderr 分存到不同的文件去
(69)
4)/dev/null 垃圾桶黑洞设备与特殊写法: 如果我知道错误信息会发生,所以要将错误信息忽略掉而不显示或储存呢? 这个时候黑洞装置 /dev/null 就很重要了!这个 /dev/null 可以吃掉任何导向这个装置的信息喔!
【荔枝】 /dev/null 黑洞设备
(70)
【荔枝】将正确与错误数据通通写入同一个文件去呢?
(71)
5)标准输入: < 与 <<
< 表示 将原本需要由键盘输入的数据,改由文件内容来取代;
【荔枝】通过 cat 命令操作来了解一下什么叫做『键盘输入』吧
(72)
【荔枝】用某个文件的内容来取代键盘的敲击呢: 用 stdin 取代键盘的输入以创建新文件的简单流程

(73)
【荔枝】 << 代表的是结束的输入字符的意思! 举例来讲:我要用 cat 直接将输入的信息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束。

(74)
6)总结:为何要使用命令输出重导向呢?我们来说一说吧!
  ● 屏幕输出的信息很重要,而且我们需要将他存下来的时候;
  ● 背景运行中的程序,不希望他干扰屏幕正常的输出结果时;
  ● 一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的运行结果,希望他可以存下来时;
  ● 一些运行命令的可能已知错误信息时,想以『 2> /dev/null 』将他丢掉时;
  ● 错误信息与正确信息需要分别输出时。

【11.5.2】命令执行的判断依据: 分号; , 双and符号&&,双竖线 ||;
1)背景:在某些情况下,很多命令我想要一次输入去运行,而不想要分次运行时,该如何是好?基本上你有两个选择, 一个是透过第十三章要介绍的 shell script 撰写脚本去运行,一种则是透过底下的介绍来一次输入多重命令喔。
2)cmd ; cmd (不考虑命令相关性的连续命令下达)
【荔枝】例如在关机的时候我希望可以先运行两次 sync 同步化写入磁盘后才 shutdown 计算机,那么可以怎么作呢?
(75)
3)$? (命令回传值) 与 && 或 ||
3.1)复习:若前一个命令运行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值;怎么透过这个回传值来判断后续的命令是否要运行呢?这就得要藉由『 && 』及『 || 』的帮忙了! 注意喔,两个 & 之间是没有空格的!
(76)
【荔枝】ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 创建 /tmp/abc/hehe:
(77)
【荔枝】测试 /tmp/abc 是否存在,若不存在则予以创建,若存在就不作任何事情:
(78)
(79)
(80)
结果分析如下:
  ● (1)若 /tmp/abc 不存在故回传 $?≠0,则 (2)因为 || 遇到非为 0 的 $? 故开始 mkdir /tmp/abc,由于 mkdir /tmp/abc 会成功进行,所以回传 $?=0 (3)因为 && 遇到 $?=0 故会运行 touch /tmp/abc/hehe,最终 hehe 就被创建了;
  ● (2)若 /tmp/abc 存在故回传 $?=0,则 (2)因为 || 遇到 0 的 $? 不会进行,此时 $?=0 继续向后传,故 (3)因为 && 遇到 $?=0 就开始创建 /tmp/abc/hehe 了!最终 /tmp/abc/hehe 被创建起来。

【荔枝】以 ls 测试 /tmp/vbirding 是否存在,若存在则显示 "exist" ,若不存在,则显示 "not exist"!
(81)
【11.6】管道命令
1)管线命令主要有两个比较需要注意的地方:
  ● 管线命令仅会处理 standard output,对于 standard error output 会予以忽略;
  ● 管线命令必须要能够接受来自前一个命令的数据成为 standard input 继续处理才行。

【11.6.1】选取命令: cut, grep
1)cut命令(筛选列):cut 不就是『切』吗?没错啦!这个命令可以将一段信息的某一段给他『切』出来。
(82)
【荔枝】
(83)
(84)
(85)
(86)
【cut命令总计】cut 主要的用途在于将『同一行里面的数据进行分解!』最常使用在分析一些数据或文字数据的时候! 这是因为有时候我们会以某些字符当作分割的参数,然后来将数据加以切割,以取得我们所需要的数据。

2)grep命令(筛选行):刚刚的 cut 是将一行信息当中,取出某部分我们想要的,而 grep 则是分析一行信息, 若当中有我们所需要的信息,就将该行拿出来;
【荔枝】
(87)
(88)
(89)
(90)
(91)
3)排序命令:sort, wc, uniq
3.1)sort命令:
注意:排序的字符与语系的编码有关,因此, 如果您需要排序时,建议使用 LANG=C 来让语系统一,数据排序比较好一些。
(92)
(93)
【荔枝】
(94)
(95)
(96)
3.2)uniq 命令:如果我排序完成了,想要将重复的数据仅列出一个显示;
(97)
(98)

(99)
补充: 这个命令用来将『重复的行删除掉只显示一个』,举个例子来说, 你要知道这个月份登陆你主机的用户有谁,而不在乎他的登陆次数,那么就使用上面的范例, (1)先将所有的数据列出;(2)再将人名独立出来;(3)经过排序;(4)只显示一个! 由于这个命令是在将重复的东西减少,所以当然需要『配合排序过的文件』来处理啰!

3.3)wc命令:如果我想要知道 /etc/man.config 这个文件里面有多少字?多少行?多少字符的话, 可以怎么做呢?其实可以利用 wc 这个命令来达成喔!
(100)
【荔枝】
(101)

(102)
【11.6.3】双向重定向:tee
1)想个简单的东西,我们由前一节知道 > 会将数据流整个传送给文件或装置,因此我们除非去读取该文件或装置, 否则就无法继续利用这个数据流。万一我想要将这个数据流的处理过程中将某段信息存下来,应该怎么做? 利用 tee 就可以啰。
(103)
2)tee 会同时将数据流分送到文件去与屏幕 (screen);而输出到屏幕的,其实就是 stdout ,可以让下个命令继续处理!
(104)
【荔枝】
(105)
(106)
(107)
【11.6.4】字符转换命令:tr, col, join, paste, expand
1)tr命令:tr 可以用来删除一段信息当中的文字,或者是进行文字信息的替换;
(108)

(109)
【荔枝】
(110)
(111)

(112)
(113)
补充:处理 Linux & Windows 系统中的人们最麻烦的一件事就是这个事情啦!亦即是 DOS 底下会自动的在每行行尾加入 ^M 这个断行符号!这个时候我们可以使用这个 tr 来将 ^M 去除! ^M 可以使用 \r 来代替之!

2)col命令:
(114)
(115)
【荔枝】
(116)
(117)
补充1)你没看错!由于 man page 内有些特殊按钮会用来作为类似特殊按键与颜色显示,所以这个文件内就会出现如上所示的一堆怪异字符(有 ^ 的)。
补充2) col 经常被利用于将 man page 转存为纯文本文件以方便查阅的功能!

3)join命令:主要是在处理『两个文件当中,有 "相同数据" 的那一行,才将他加在一起的意思。
(118)
【荔枝】
(119)
(120)
需要特别注意的是:在使用 join 之前,你所需要处理的文件应该要事先经过排序 (sort) 处理! 否则有些比对的项目会被略过呢!
4)paste命令:相对于 join 必须要比对两个文件的数据相关性, paste 就直接『将两行贴在一起,且中间以 [tab] 键隔开』而已!
(121)
【荔枝】
(122)

(123)
5)expand命令:将tab键 转换成空格键,如下:
(124)
【荔枝】
(125)
补充:expand命令自动将 [tab] 转成空格键~所以,以上面的例子来说, 使用 cat -A 就会查不到 ^I 的字符啰~此外,因为 [tab] 最大的功能就是格式排列整齐! 我们转成空格键后,这个空格键也会依据我们自己的定义来添加大小~ 所以,并不是一个 ^I 就会换成 8 个空白喔!这个地方要特别注意的哩! 此外,您也可以参考一下 unexpand 这个将空白转成 [tab] 的命令功能啊!

【11.6.5】切割命令: split
1)介绍: 如果你有文件太大,导致一些携带式设备无法复制的问题!找 split 就对了! 他可以帮你将一个大文件,依据文件大小或行数来分割,就可以将大文件分割成为小文件了! 
(126)
【荔枝】
(127)
(128)
(129)
补充:在 Windows 操作系统下,你要将文件分割需要如何作?伤脑筋吧!在 Linux 底下就简单的多了!你要将文件分割的话,那么就使用 -b size 来将一个分割的文件限制其大小,如果是行数的话,那么就使用 -l line 来分割!
【11.6.6】参数代换:xargs
1)xargs作用: 产生某个命令的参数的意思! xargs 可以读入 stdin 的数据,并且以空格符或断行字符作为分辨,将 stdin 的数据分隔成为 arguments 。 
(130)
【荔枝】
(131)
(132)
(133)
(134)
补充: 会使用 xargs 的原因是, 很多命令其实并不支持管线命令,因此我们可以透过 xargs 来提供该命令引用 standard input 之用!

2)举例来说,我们使用如下的范例来说明:

(135)
【11.6.7】关于减号- 的用途
1)在管线命令当中,常常会使用到前一个命令的 stdout 作为这次的 stdin , 某些命令需要用到文件名 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代, 举例来说:

(136)
【补充】上面这个例子是说: 我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - 。后面的这个 - 则是取用前一个命令的 stdout, 因此,我们就不需要使用 file 了!这是很常见的例子喔!注意注意!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值