Shell及Shell Scripts

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 $PATHecho ${PATH};
  • 变量的取消:使用unset指令,对取消myname变量,取消命令为unset myname;
  • 变量的设定或修改:使用=连结变量和内容,如myname=GavinPATH="${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.shsh 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)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.4 shell script的追踪和debug

在这里插入图片描述

3. 重点回顾

在这里插入图片描述在这里插入图片描述在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/yueguangmuyu/article/details/108665007