文章目录
0. Shell在OS中所处的位置
0.1 shell的概念
Shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。是在Linux内核与用户之间的解释器程序,现在Linux通常指/bin/bash解释器来负责向内核翻译以及传达用户/程序指令,shell相当于操作系统的“外壳”,如下图所示。
0.2 shell接口指令的快速删除和光标的移动
0.3 bash的进站与欢迎讯息:/etc/issue, /etc/motd
man issue
& man agetty
可得到/etc/issue
中变量的含义
想要让使用者登入后取得一些讯息,例如您想要让大家都知道的讯息, 那么可以将讯息加入/etc/motd
里面去 (root权限) E.g.
1. 学习Shell
1.1 Bash shell概述
1.1.1 CentOS 7.x 系统合法的shell与/etc/shells
Shell的历史:
作者 | 版本 |
---|---|
Steven Bourne | Bourne shell,简称sh |
Bill Joy | 依附于BSD版Unix的shell,简称csh |
GNU框架 | Bourne Again SHell ,简称bash,同时也是Linux distributions的标准shell |
以CentOS 7.x 为例,可用的shells有:
- /bin/sh (已经被/bin/bash 所取代)
- /bin/bash (就是Linux 预设的shell)
- /bin/tcsh(整合C Shell ,提供更多的功能)
- /bin/csh (已经被/bin/tcsh 所取代)
- /sbin/nologin,非登陆壳程序
系统中合法的shell写入了/etc/shells文件,使得系统提供某项服务时,可对所用的shell类型进行检查。
重点关注的是bash shell,它有诸多的优点(加粗为讲解点):
- 命令编修功能(history)
- 命令与文件补全功能(tab)
- 命令别名设置(alias)
- 工作控制、前景背景控制(job control, foreground, background)
- 程序化脚本(shell scripts)
- 通配符(wildcard)
1.1.2 指令类型的查询:type指令
指令的类型:
类型 | 含义 |
---|---|
file | 外部指令 |
alias | 命令别名所设定的名称 |
builtin | bash内建的指令 |
type指令的用法:
★注:其中 type -a 指令
的显示结果即为该指令的搜索顺序,如下图所示:
1.2 Shell的变量功能
1.2.1 shell的取用、修改和取消
shell的变量功能类似于cpp中的多态特性,也即高级语言中的变量定义。
变量也有作用域,分为环境变量和自定义变量,可以理解为环境变量=全局变量
,自定义变量=局部变量
。
- 变量的取用:使用
echo
指令,对PATH这一环境变量而言,取用方式有echo $PATH
或echo ${PATH}
; - 变量的取消:使用
unset
指令,对取消myname变量,取消命令为unset myname
; - 变量的设定或修改:使用
=
连结变量和内容,如myname=Gavin
,PATH="${PATH}:\root"
,PATH=${PATH}:\root
;
对于变量的设定或修改,有如下规则:
- 等号两边不能直接接空格符;
- 变量名称只能是英文字母与数字,但是开头字符不能是数字;
- 变量内容若有空格符可使用双引号『"』或单引号『’』将变量内容结合起来,但:
① 双引号内的特殊字符如 $ 等,可以保有原本的特性;
② 单引号内的特殊字符则仅为一般字符 (纯文本); - 可用跳脱字符『 \ 』将特殊符号(如 [Enter], $, , 空格符, '等)变成一般字符;
- 在一串指令的执行中,还需要藉由其他额外的指令所提供的信息时,可以使用反单引号`指令`或 $(指令);
- 若该变量为扩增变量内容时,则可用 “$变量名称” 或 ${变量} 累加内容;
- 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量;
- 通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断。
1.2.2 环境变量的功能
1.2.2.1 变量的查看
env/export
可以列出当前shell环境下的所有环境变量及其内容
p.s.export
可将自定义变量转换为环境变量
- HOME(用户家目录)
- SEHLL(当前的SHELL环境是哪个)
- HISTSIZE(历史命令记录条数)
- PATH(执行文件搜索的路径)
- LANG(当前语系)
set
观察所有变量(含环境变量与自定义变量),还可以设定整个指令输出/输入环境,见1.4.3
- PS1(提示字符的设定):
- $(关于本shell的PID)
- ?(关于上一个指令的回传值)
- OSTYPE, HOSTTYPE, MACHTYPE(主机硬件与核心的等级)
1.2.2.2 语系的设定
locale -a
可以查看系统支持的语系,保存在/usr/lib/locale/
目录当中;
系统默认的语系定义保存在/etc/locale.conf
文件当中;
设定LANG
或者是LC_ALL
时,则其他的语系变量就会被这两个变量所取代。
1.2.3 变量的键盘读取和宣告
1.2.3.1 read指令
读取来自键盘输入的变量。
1.2.3.2 declare/typeset
declare 或typeset 是一样的功能,就是在『宣告变量的类型』。如果使用declare 后面并没有接任何参数,那么bash 就会主动的将所有的变量名称与内容通通叫出来,和使用set类似。
注:如果将变量设定为『只读』,通常得要注销再登入才能复原该变量的类型。
1.2.4 与文件系统及程序的限制关系:ulimit
bash 利用ulimit指令可以限制用户的某些系统资源的,包括可开启的文件数量, 可使用的CPU 时间,可使用的内存总量等。
1.2.5 变量内容的删除取代和替换
- 变量内容的删除与取代
- 变量的测试与内容替换
1.3 命令别名与历史命令
1.3.1 命令别名alias
使用alias
可以获取当前已有的命令别名:
可以使用 alias
命令设置命令别名,如alias lm='ll -al | more'
可以使用unalias
命令取消命令别名,如unalias lm
1.3.2 历史命令history
1.3.2.1 history指令和!*指令
正常情况下,历史命令的读取与记录过程如下:
- 以bash 登入Linux 主机之后,系统会主动的由家目录的~/.bash_history 读取以前曾经下过的指令,那么 ~/.bash_history 会记录不超过HISTFILESIZE 这个变量设定值的记录,多的将会依次覆盖掉最早的指令;
- 历史命令在注销时,会将最近的HISTFILESIZE 笔记录到本shell的纪录文件当中;
- 此外,可以用history -w 将~/.bash_history 中的记录强制立刻写入history中。
除了history历史命令外,还有如下命令可以回溯并执行历史命令:
1.3.2.2 history的相关问题
- 同一账号同时多次登入的history 写入问题:在多重登陆的情况下,只有最后注销的bash shell的~./bash_history才是写入的数据。解决该问题的方法为,单一bash登入,再用工作控制(job control)来切换不同的工作,即统一一个bash作为工作shell;
- 无法记录时间:历史命令是依序记录的,并没有记录时间,所以在查询方面会有一些不方便。可以透过~/.bash_logout 来进行history 的记录,加上date 来增加时间参数,是一个可行的解决办法。
1.4 login/non-login shell及bash环境的配置文件
1.4.1 login shell
login shell:取得bash 时需要完整的登入流程的,称为login shell。比如,由tty1 ~ tty6 登入,输入用户的账号与密码并验证通过后,所取得的bash 就称为login shell。
login shell会读取两个配置文件:
1. /etc/profile
:这是系统整体的设定,即每个使用者登入取得bash 时一定会读取的配置文件,最好不要修改该文件;其中设定的变量主要有:
- PATH:会依据UID 决定PATH 变量要不要含有sbin 的系统指令目录;
- MAIL:依据账号设定好使用者的mailbox 到/var/spool/mail/账号名;
- USER:根据用户的账号设定此一变量内容;
- HOSTNAME:依据主机的hostname 指令决定此一变量内容;
- HISTSIZE:历史命令记录笔数。CentOS 7.x 设定为1000 ;
- umask:包括root 默认为022 而一般用户为002 等!
此外,该文件还会呼叫外部的设定数据,有/etc/profile.d/*.sh
,/etc/locale.conf
(由/etc/profile.d/lang.sh呼叫),/usr/share/bash-completion/completions/*
(命令自动补全)。
2. ~/.bash_profile
或~/.bash_login
或~/.profile
:属于使用者个人设定,在这里写入保存。设定为上面的三个文件只读取一个,读取的顺序与上面的顺序相同。
3.login shell的配置文件读取流程:
1.4.2 non-login shell
取得bash 接口的方法不需要重复登入的举动。比如:
- 你以X window 登入Linux 后,再以 X 的图形化接口启动终端机,此时那个终端接口并没有需要再次的输入账号与密码,那个bash 的环境就称为non-login shell 了;
- 你在原本的bash 环境下再次下达bash 这个指令,同样的也没有输入账号密码, 那第二个bash (子程序) 也是non-login shell 。
non-login shell只会读取~/.bashrc
,此外还会呼叫/etc/bashrc
文件(Red Hat系统特有),因为其中定义了:
- 依据不同的UID 规范出umask 的值;
- 依据不同的UID 规范出提示字符(就是PS1 变量);
- 呼叫/etc/profile.d/*.sh 的设定。
1.4.3 source指令、其它相关配置及配置文件
source 配置文件档名
:读入环境配置文件的指令,在/etc/profile/*.sh,/etc/bashrc中均有体现(.的形式)
由于 /etc/profile 与~/.bash_profile 都是在取得login shell 的时候才会读取的配置文件,所以, 如果你将自己的偏好设定写入上述的文件后,通常都是得注销再登入后,该设定才会生效。利用source 或小数点(.) 都可以将配置文件的内容读进来目前的shell 环境中,避免重新登陆;- 查看终端机环境配置:
stty [-a]
, 删除配置使用erase,比如stty erase ^h
,默认组合键如下:
-
set
指令除了可显示变量,还可以设定整个指令输出/输入环境。比如记录历史命令、显示错误内容等:
-
/etc/man_db.conf
:规定了下达man 的时候,该去哪里查看数据的路径设定; -
~/.bash_history
:预设情况下, 历史命令记录在这里,登入bash 后,bash 会先读取这个文件,将所有的历史指令读入内存; -
~/.bash_logout
:记录了注销bash 后,系统在退出前需做的指令,可以将备份或销毁工作写入该文件,作为自定义设置。
1.5 shell中的通配符和特殊符号
通配符:
特殊符号:
1.6 数据流重导向及管线命令
1.6.1 数据流重导向
- 标准输入(stdin):代码为 0 ,使用 < 或 << ;
< : 将原本需要由键盘输入的数据,改由文件内容来取代, E.g:cat > catfile < ~/.bashrc
;
<< : 结束的输入字符:用cat 直接将输入的讯息输出到catfile 中, 且当由键盘输入 eof 时,该次输入就结束,E.g.cat > catfile << "eof"
; - 标准输出(stdout):代码为 1 ,使用 > 或 >>,标准输出指的是『指令执行所回传的正确的讯息』:
1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上; - 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>>,可理解为『指令执行失败后,所回传的错误讯息』:
2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;
若是想将标准错误输出忽略,可将错误输出重导向至黑洞装置/dev/null
;
若是将正确与错误数据写入同一文件,可使用2&>1
或&>
来进行,而不能用> list 2> list
,因为会导致数据的交叉写入; - 命令输出重导向的应用场景:
1.屏幕输出的信息很重要,而且我们需要将他存下来的时候;
2.背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
3.一些系统的例行命令(例如写在/etc/crontab 中的文件) 的执行结果,希望他可以存下来时;
4.一些执行命令的可能已知错误讯息时,想以『2> /dev/null 』将他丢掉时;
5.错误讯息与正确讯息需要分别输出时; - 命令执行的判断依据: ;,&&, ||
符号 | 作用 |
---|---|
; | 不考虑指令相关性的连续指令下达 |
cmd1 && cmd2 | 1. 若 cmd1 执行完毕且正确执行($?=0),则开始执行 cmd2; 2. 若cmd1执行完毕且为错误 ($?≠0),则 cmd2 不执行; |
cmd1 || cmd2 | 1. 若 cmd1 执行完毕且正确执行($?=0),则 cmd2 不执行; 2. 若 cmd1 执行完毕且为错误 ($?≠0),则开始执行 cmd2; |
1.6.2 管线命令(cut; grep; wc; xargs, etc.)
命令名称 | 命令作用 |
---|---|
| | 处理经由前一个指令传来的standard output,传给下一个指令,作为下一个指令的standard input 1. 管线命令仅会处理standard output,对于standard error output 会予以忽略; 2.管线命令必须要能够接受来自前一个指令的数据成为standard input 继续处理才行; 3.若要standard error由管线命令所接受,在指令中加入 2>&1 即可; |
- | 在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的stdin , 某些指令需要用到文件名 (例如tar) 来进行处理时,该stdin 与stdout 可以利用减号"-"来替代 |
cut | 主要用途在于将同一行里面的数据依据分隔符进行分解,但处理在处理多空格相连的数据效果不好 选项与参数: -d :后面接分隔字符。与 -f 一起使用; -f :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思; -c :以字符 (characters) 的单位取出固定字符区间; |
grep | 分析一行文本, 若当中有所需要的信息,就将该行拿出来grep [-A] [-B] [--color=auto] '搜寻字符串' filename :在正则表达式中可用于截取目标字符串的上下文选项与参数: -A :后面可加数字,为 after 的意思,除了列出该行外,后续的 n 行也列出来; -B :后面可加数字,为 befer 的意思,除了列出该行外,前面的 n 行也列出来; -a :将 binary 文件以 text 文件的方式搜寻数据; -c :计算找到 ‘搜寻字符串’ 的次数; -i :忽略大小写的不同,所以大小写视为相同; -n :顺便输出行号; -v :反向选择,亦即显示出没有 ‘搜寻字符串’ 内容的那一行; –color=auto :可以将找到的关键词部分加上颜色的显示,默认已有别名; |
sort | 可以依据不同的数据型态来排序 选项与参数: -f :忽略大小写的差异,例如 A 与 a 视为编码相同; -b :忽略最前面的空格符部分; -M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法; -n :使用『纯数字』进行排序(默认是以文字型态来排序的); -r 反向排序; -u :就是 uniq ,相同的数据中,仅出现一行代表; -t :分隔符,预设是用 [tab] 键来分隔; -k :以那个区间 (field) 来进行排序的意思 |
uniq | 使得重复的资料只显示一次 选项与参数: -i :忽略大小写字符的不同; -c :进行计数 |
wc | word count,对文件中的字数,行数或字符数进行计数 选项与参数: -l :仅列出行; -w :仅列出多少字(英文单字); -m :多少字符; |
tee | 中文意思为:字母T,T形物;双向重导向,可将数据流分送到文件和屏幕,如:last | tee last.list | cut -d " " -f1 选项与参数: -a :以累加 (append) 的方式,将数据加入 file 当中; |
tr | 用来删除一段讯息当中的文字,或者是进行文字讯息的替换 选项与参数: -d :删除讯息当中的 SET1 这个字符串; -s :取代掉重复的字符! |
col | 简单的处理将[tab] 按键取代成为空格键 选项与参数: -x :将 tab 键转换成对等的空格键 |
join | 两个文件当中,有"相同数据" 的那一行,才将他加在一起:join [-ti12] file1 file2 选项与参数: -t :join 默认以空格符分隔数据,并且比对『第一个字段』的数据, 如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个; -i :忽略大小写的差异; -1 :这个是数字的 1 ,代表『第一个文件要用那个字段来分析』的意思; -2 :代表『第二个文件要用那个字段来分析』的意思。 |
paste | 将两行贴在一起,且中间以[tab] 键隔开:paste [-d] file1 file2 选项与参数: -d :后面可以接分隔字符。预设是以 [tab] 来分隔的! - :如果 file 部分写成 - ,表示来自 standard input 的资料的意思; |
expand | 将 [tab] 按键转成空格键:expand [-t] file 选项与参数: -t :后面可以接数字,表示一个 [tab] 按键代表多少个字符。一般来说,一个 tab 按键可以用 8 个空格键取代; |
xargs | 读入stdin 的数据,以空格符或断行字符作为分辨,将stdin 的资料分隔成为arguments:xargs [-0epn] command 选项与参数: -0 :如果输入的 stdin 含有特殊字符,例如 `, , 空格键等等字符时,这个 -0 参数可以将他还原成一般字符。这个参数可以用于特殊状态; -e :这个是 EOF (end of file) 的意思。后面可以接一个字符串(紧相接,无空格),当 xargs 分析到这个字符串时,会停止继续工作; -p :在执行每个指令的 argument 时,都会询问使用者的意思; -n :后面接次数,每次 command 指令执行时,要使用几个参数的意思; 当 xargs 后面没有接任何的指令时,默认是以 echo 来进行输出喔 |
2. Shell Scripts
shell script 是利用shell 的功能所写的一个程序(program),这个程序是使用纯文本文件,将一些shell的语法与指令(含外部指令)写在里面, 搭配正规表示法、管线命令与数据流重导向等功能,以达到所想要的处理目的。
★ Shell script中的注释是以#打头的注释行
,和python相同。
★ 第一行#!/bin/bash
在宣告这个script 使用的shell 名称。
★在数值的运算上,可使用declare -i total=${firstnu}*${secnu}
,也可使用$((运算内容))
(推荐第二种)
2.1 shell scripts的执行
要执行的文件*.sh必须具备可读与可执行(rx)的权限。
- 直接指令下达:
1.绝对路径:使用/home/dmtsai/shell.sh
来下达指令;
2.相对路径:假设工作目录在/home/dmtsai/ ,则使用./shell.sh
来执行;
3.变量PATH功能:将shell.sh 放在PATH 指定的目录内,例如: ~/bin/。 - 以bash程序来执行:通过
bash shell.sh
或sh shell.sh
来执行
以上几种脚本的执行方式,都是开启了一个新的shell来执行该脚本,也就意味这使用在脚本中定义的变量将不会保留到父shell当中,也即脚本结束后脚本中的变量会变无效;
- 以source来执行:
source 脚本名
在脚本中执行的动作,在脚本执行完毕后,在其父shell中仍然有效。
2.2 shell scripts中的判断
2.2.1 test的测试功能
2.2.2 判断符号[ ]
判断符号本身相当于test,只是test后要跟参数,而判断符号将参数放入中括号当中。比如test -z ${HOME}
= [ -z "\${HOME}" ]
两个命令是等价的,都是判断HOME变量是否为空。
★用于 if 语句中的条件判断
注意事项:
- 在中括号 [] 内的每个组件都需要有空格键来分隔;
- 在中括号内的变数,最好都以双引号括号起来;
- 在中括号内的常数,最好都以单或双引号括号起来。
2.2.3 shell script的默认变数($0,$1,…)
执行的脚本的名称为$0
,第一个参数为$1
,参数234依此类推。此外还有特殊的变量,分别为:
$#
:代表后接的参数『个数』,以上表为例这里显示为『 4 』;$@
:代表『 “$1” “$2” “$3” “$4” 』之意,每个变量是独立的(用双引号括起来);$*
:代表『 “$1c$2c$3c$4” 』,其中 c 为分隔字符,默认为空格键, 所以本例中代表『 “$1 $2 $3 $4” 』之意。
此外,可以利用shift 数字
拿掉参数列表(从$1开始)中的前几个参数。
2.3 判断语句与循环语句
2.3.1 if 判断语句
2.3.2 loop 循环(for; while; until)