鸟哥私房菜基础系列第3篇
私房菜 第3篇 学习shell
Vi文字处理器
在进行shell编程之前,一定要有一款趁手的编写工具,那就是unix-like平台中最为风靡的文字处理软件Vi,基本上是linux平台默认的文字处理软件。
书中流出了大量常用的指令。
这一块准备独立成篇
学习BASH
什么是shell
顾名思义,shell就是一个壳,我们通过这个壳,给内核kernel发出指令,操作硬件完成相应的任务。
BASH shell
shell的种类其实有很多,常见的有Bourne Shell(sh), Sun中默认的C SHell,商业上常用的K Shell等,每种shel都有自己的特点。。Linux使用的是Bourne Again SHell(简称 bash),这个Shell是Bourne Shell的增强版本,是基于GNU的架构下发展而来。。第一个流行的shell是由Steven Bourne开发出来的,为了纪念他所以称为Bourne shell,简称sh。后来另一个广为流传的shell是由柏克莱大学的Bill Joy设计的依附于BSD版的Unix系统中的shell,这个shell的语法有点类似C语言,所以得名为C shell,简称为csh。由于在学术界Sun主机势力相当庞大,而Sun主要是BSD的分支之一,所以C shell也是另一个很重要且流传很广的shell之一(因为太多的程序设计师使用的就是C语言)
bash shell的优点
- 命令编辑能力 而且还有命令记忆功能,历史命令记录在~/.bash_history中,可以修改默认的记录个数
- 补全功能 可以没事在linux的shell中没事多敲几次 tab这是一个良好的习惯,可以补全目录,也可以补全文件名
- 命令别名(alias)设定功能 在命令行中输入alias就可以知道当前都有哪些别名。定义别名也很简单,比如,
alians lm=\'ls -al\'.敲入
lm`就可以实现原来命令的功能,简介方便。 - 作业控制、前景背景控制 可以把一些程序放到后台(背景)中执行,以免被ctl + c误杀
- 强大的shell scripts功能 相当于windows中的批处理文件的概念。linux中的shell scripts可以写成文件,可以交互,其实从登陆文字界面的linux开始就在使用shell的功能。
BASH的命令格式
[root@test /root]# command [-options] parameter1 parameter2 ...
指令 选项 参数(1) 参数(2)
- command为指令的名称,例如变换路径的指令为cd
- 中括号[]并不存在于实际的指令中,在加入参数时,通常为“-”符号,
有时候完整名称会输入“--”符号。例如ls --help - parameter1 parameter2为依附在option之后的参数,或者是
command的参数 - command, -options, parameter1这几项之间以空格分隔,
不论空几格shell都视为一格 - 指令太长的时候,可以使用 \ 符号来跳转Enter,使指令连续到下一行
变量
从编程的角度来说,变量的内涵应当很清楚了,一个变量就可以代表一串值,用起来很方便。
有一些不成文的规定,定义系统变量时,一般都是用大写,比如PATH
其实讲到变量这一块,就涉及到了PATH环境变量等概念,这一块内容对从感性上了解linux系统的整个架构还是非常有用的,尤其会在下面讲到一些配置文件
echo
现实变量的值
语法:
[root @test root]# echo $variable
参数说明:
范例:
[root @test root]# echo $PATH
env 可以查看系统中到底有多少变量
env 是 environment的缩写。一般,全大写的变量都是系统预设的。
有很多变量的意义可以查阅原书。
set set的使用方法就是直接输入set。它除了会显示当前的环境变量,也会显示您的自定义变量。
BASH=/bin/bash <BASH的主程序放置路径
BASH_VERSINFO=([0]="2" [1]="05b" [2]="0" [3]="1" [4]="release"
[5]="i586-mandrake-linux-gnu") <BASH版本信息
BASH_VERSION=\('2.05b.0(1)-release' <==BASH的版本
COLORS=/etc/DIR_COLORS <==使用颜色
COLUMNS=100 <==当前终端使用的字段有几个字符的宽度
HISTFILE=/home/vbird/.bash_history <==当前用来保存历史指令的文件,为一个隐藏文件
HISTFILESIZE=1000 <==历史指令文件中指令的最大数(只记录1000个指令)
IFS=\)' \t\n' <默认的分隔符
LINES=40 <当前光标所在的位置为第几行
MAILCHECK=60 <每隔多久检查一次有无新邮件(以秒为单位)
PPID=24572 <当前bash程序的ID号
UID=500 <登入者的用户ID(UID)
**$ <当前shell的PID echo $$ 查看**
? <==最后一个命令的回传值。若之前的命令被正确执行,则传回0,否则传回1 echo $? 查看
当你登录BASH之后就会获得一个属于自己用户的程序执行吗PID,你所定义的变量只能自己使用,或者是在同一个PID下面的子程序使用,别人用不了,如果想影响别人就只能修改系统中公共的配置文件。要想自己的变量在下次仍然能够使用,就要写入配置文件,并添加随系统一起启动。
设定变量的规则
-
变量与变量内容以等号“=”连结;
-
等号两边不能直接接空格符;
-
变量名称只能是英文字母与数字,其中数字不能是开头字符;
-
若有空格符,可以使用双引号或单引号将变量内容结合起来,但要特别留意,双引号内的特殊字符可以保留变量特性,单引号内的特殊字符则仅为一般字符;
- 比如
name="Mike jordan"
,双印中中的空格都是值,可以把前后连起来 - 如果name 是一个变量,那么 newname="\(name",newname的值将和name的值一样,而newname='\)name'中new那么的值就是$name
- 比如
-
必要时以跳转字符“\”将特殊符号(如Enter,$,\,空格符,'等)变成一般符号;
-
在一串指令中,还需要借助其他指令提供的信息,这时可以使用quote“
command
”;
[test @test test]# cd /lib/modules/uname –r
/kernel -
若该变量为扩增变量内容时,则需以双引号及\(变量名称(如"\)PATH":/home)继续累加内容;
[test @test test]# name=Oliver
[test @test test]# name="$name"isme <正确。 echo \(name --> Oliverisme [test @test test]# name="\)name:isme" <正确。 前面引用变量$name一定要和后面的分开 -
若该变量需要在其他子程序执行,则以export使变量可以动作,如export PATH;
在当前的bash线面 键入 bash就可以开启两一个bash,exit就可以退出 -
通常大写字符为系统预设变量,自定义变量可以使用小写字符,方便判断(纯粹依照用户兴趣与嗜好);
-
取消变量的方法为:unset 变量名称。
export
当您取得一个bash之后,即得到了一个程序,但是若您再次执行bash,那么将进入子程序,程序的概念我们放在第16章详谈,这里您有个概念即可。由于您已经进入了该子程序,所以父程序中的变量设定将不继续存在。如果想让该变量内容继续在子程序中使用,请执行
export 变量
unset
直接取消变量内容
用户别名alias与历史history
alias
键入这条指令就能查看当前有哪些别名
定义别名就可以这样:
alias rm='rm -i' 注意 = 前后没有空格
取消别名就是用unalias
history
将入history
就可以查看曾经键入的历史命令,如果嫌麻烦,可以定义别名
alias h='history'
[test @test test]# history
[test @test test]# [!number] [!command] [!!]
参数说明:
number :第几个指令
command :指令的开头几个字母
! :上一个指令
范例:
[test @test test]# history <==底下列出的就是(1)历史指令的编号;(2)指令的内容
66 man rm
67 alias
68 man history
69 history
[test @test test]# !66 <==执行第 66 个历史指令
[test @test test]# !! <==执行上一个指令(在本例中,就是 !66指令)
[test @test test]# !al <==执行最近一次以 al 为开头的指令内容,就是第 67 个指令
所有的历史命令存储在,~/.bash_history文件中
bash shell的配置文件
上面介绍的变量,别名等等设置,一档推出去系统之后就失效了,要想保证一直能用,就应当写入配置文件。
配置分为系统设定值 和 个人自定义设定值,修改前者对应文件中的变量,将会影响到所有用户,修改后者对应文件中的变量则是个性化自己的习惯。当然这些配置文件的名称位置,不同版本的distro会略有区别,下面介绍的内容,看看有个印象即可。
系统之设定
· /etc/profile:这个文件设定了几个重要变量,例如PATH、USER、MAIL、HOSTNAME、HISTSIZE、umask等,也同时规划出,/etc/inputrc 这个针对键盘热键设定的文件数据内容。您可以在这里设定总体的PATH等信息。同时,这个文件还规划出/etc/profile.d及/etc/inputrc这两个文件,其中,inputrc作用于history(历史指令)。总之,您可以了解到刚刚我们学会的变量设定方式,在这个文件中也可以设定。但是设定上需要特别小心,因为所有的用户都会用到这个文件的信息。注:通常我都喜欢将/usr/local/bin 这个路径加在最前面,因为通常自己安装的套件自己最喜欢,所以当然最先搜寻。此外,请注意,可以改变HISTSIZE的大小,改成50就可以,比较安全!
· /etc/bashrc:这个文件用于规划umask,同时规划提示符的内容(就是里面那个PS1)。特别留意的是,这个文件在不同的 Linux 版本里摆放的位置可能不太一样,所以需要查询。
· /etc/man.config:这个文件或许跟bash shell没有太大相关性,但是对于系统管理员来说,却是很重要的一个文件!这个文件的内容规范了使用man时man page的路径到哪里寻找,说得简单一点,这个文件指定了输入man时查看数据的路径设定。那么什么时候修改这个文件?如果您是以 Tarball方式安装数据,那么您的 man page(指令说明文件)可能会放在/usr/local/softpackage/man中,其中的softpackage 是套件名称,这时您得以手动方式将该路径加到 /etc/man.config中,否则使用man时会找不到相关的说明文档。
个人设定
下面的“~”代表的是根目录。
· ~/.bash_profile:里面定义了个人路径(PATH)与环境变量的文件名称。您可以在这里修改您的个人路径,**当然,也可以在 /.bashrc这个个人设定的变量中修改**。有的时候可以用/.profile或~/.bash_login等文件来取代这个文件!
· ~/.bashrc:这个文件对于个人喜好的bash设定是最重要的,因为我都是在这里设定我的个人变量,例如命令别名的设定,路径的重新定义等。
· ~/.bash_history:这个文件用于将您曾经用过的命令记录下来,而当您再次以上下键搜寻或者直接以history搜寻时,就可以找到曾经用过的指令。需要注意的是:
1. 在这一次执行过程中用到的指令,将在您退出shell之后才会被记录到这个文件中,否则将先被写到高速缓存中;
2. 可以通过history指令将其中的记录搜寻出来;
3. 这个文件的指令记录笔数与HISTSIZE有关,您可以自行在~/.bashrc中设定,或者直接由root在/etc/profile中统一设定。
· ~/.bash_logout:这个文件则是在您注销shell的时候BASH为您所做的事情。通常默认是只有清除屏幕这件事,不过,您也可以将一些备份或其他您认为重要的工作写在这个文件中(例如清空暂存空间),那么当您退出Linux时,就可以解决一些烦人的事情。
source
如果需要将当前的配置文件内容读入一次,需要重新注销再登录,那么有没有办法不注销而直接读入变量配置文件呢?当然可以,使用source即可
source 变量配置文件
通配符与符号
* 通配符,代表任意字符(0到多个)
? 通配符,代表一个字符
# 注释,这个最常用在脚本中,视为说明
\ 跳转符号,将特殊字符或通配符还原成一般字符
| 分隔两个管线命令的界定
; 连续性命令的界定(注意,与管线命令不同)
~ 用户的根目录
$ 即变量前需要加的变量值
& 将指令变成在背景下工作
! 逻辑运算中的“非”(not)
/ 路径分隔符号
>, >> 输出导向,分别为“取代”与“累加”
' 单引号,不具有变量置换功能
" 具有变量置换功能
` ` 两个“`”中间为可以先执行的指令
( ) 中间为子shell的起始与结束
[ ] 中间为字符组合
{ } 中间为命令区块组合
组合键 执行结果
Ctrl + C 终止当前命令
Ctrl + D 输入结束(EOF),例如邮件结束的时候
Ctrl + M 就是Enter
Ctrl + S 暂停屏幕的输出
Ctrl + Q 恢复屏幕的输出
Ctrl + U 在提示符下,将整行命令删除
Ctrl + Z 暂停当前命令
有用的示例
[test @test test]# ls test* <==*代表后面不论接几个字符都予以接受(没有字符也接受)
[test @test test]# ls test? <==?代表后面一定要一个字符
[test @test test]# ls test??? <==???代表一定要接3个字符
[test @test test]# cp test[1-5] /tmp <==test1, test2, test3, test4, test5若存在,就将其复到/tmp 下
[test @test test]# cd /lib/modules/`uname -r`/kernel/drivers <==被 ` ` 括起来的内容会先执行
连续指令的书写
command1; command2 葫芦command1的执行结果如何,command2都会执行
command1 && command2 command1执行后无误即?=1, 才执行command2
command1 || command2 当command1执行有错误即?= 0,才执行command2
命令输出重定向
标准输入:代码为0,或称为stdin,使用方式 <
标准输出:代码为1,或称为stdout,使用方式1>
错误输出:代码为2,或称为stderr,使用方式2>
基本的指令书写格式:
指令 > 设备或者文件
2>
>>
<
[test @test test]# ls -al > list.txt
将显示结果输出到 list.txt 文件中,若该文件已存在则予以取代
[test @test test]# ls -al >> list.txt
将显示结果累加到list.txt 文件中,该文件为累加的,旧数据保留!
[test @test test]# ls -al 1> list.txt 2> list.err
将显示数据正确输出到 list.txt,错误的数据输出到list.err
[test @test test]# ls -al 1> list.txt 2>&1
将显示数据不论正确或错误均输出到list.txt中。注意,错误与正确信息输出到同一个文件中,则
必须以上面的方法来写,不能写成其他格式
[test @test test]# ls -al 1> list.txt 2> /dev/null
将显示的数据,正确的输出到list.txt,错误的数据予以丢弃!
· < :由 < 的右边读入参数文件;
· > :将原本由屏幕输出的正确数据输出到 > 右边的file(文件名称)或device(设
备,如printer);
· >> :将原本由屏幕输出的正确数据输出到 >> 右边,与 > 不同的是,该文件将
不会被覆盖,而新的数据将以累加方式添加到文件的最后面;
· 2> :将原本应该由屏幕输出的错误数据输出到2>的右边;
· /dev/null :可以视为垃圾设备。
管线命令 |
- 执行last,将这个月的所有人的所有登入数据取出来;
- 使用grep将上面的输出数据(stdout)中的root撷取出来,其他的不要;
- 使用wc这个可以计算行数的指令对上一步取到的数据计算行数。
管线命令 “|”仅能处理经由前一个指令传来的正确信息,也就是标准输出(Stdout)
信息,对于标准错误信息并没有直接处理能力,请记得这一点
cut
语法:
[root @test /root ]# cut -d "分隔字符" [-cf] fields
参数说明:
-d :后面接的是分隔字符,默认是空格符
-c :后面接的是第几个字符
-f :后面接的是第几个区块
范例:
[root @test /root]# cat /etc/passwd | cut -d ":" -f 1
将 passwd文件中每一行里的“:”用作分隔符,列出第一个区块,也就是姓名所在
[root @test /root]# last | cut -d " " -f1
以空格符作为分隔,并列出第一个区块
[root @test /root]# last | cut -c1-20
将 last 之后的数据,每一行的1~20个字符取出来
注意了passwd这个文件不是啊所拍好的,每一行都是使用了相同的分隔符而已,如下:
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
statd:x:102:65534::/var/lib/nfs:/bin/false
sync:x:4:65534:sync:/bin:/bin/sync
sys:x:3:3:sys:/dev:/bin/sh
sort
sort把每一行作为一个单位来比较,按照ASCII从第一个字符往后
sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式:
sort [-bcfMnrtk][源文件][-o 输出文件]
补充说明:sort可针对文本文件的内容,以行为单位来排序。
参 数:
-b 忽略每行前面开始出的空格字符。
-c 检查文件是否已经按照顺序排序。
-f 排序时,忽略大小写字母。
-M 将前面3个字母依照月份的缩写进行排序。
-n 依照数值的大小排序。
-o<输出文件> 将排序后的结果存入指定的文件。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
-k 选择以哪个区间进行排序。
wc
语法:
[root @test /root ]# wc [-lmw]
参数说明:
-l :多少行
-m :多少字符
-w :多少字
范例
[root @test /root]# cat /etc/passwd | wc -l
这个文件里有多少行
[root @test /root]# cat /etc/passwd | wc -w
这个文件里有多少字
wc是相当有用的计算文件内容的一个工具组。举个例子来说,当您要知道目前您的账号文件中有多少个账号,就使用上面的wc –l,因为/etc/passwd里一行代表一个用户,所以知道行数就知道有多少账号了。如果要计算一个文件里有多少个字符时,需要使用wc -w。
uniq
语法:
[root @test /root ]# uniq
[root @test /root]# last | cut -d" " -f1 | sort | uniq
tee
语法:
[root @test /root ]# last | tee last.list | cut -d " " -f1
有没有发现在命令重定向的时候,如果我们将数据重定向到文件,屏幕上就不会出现任何数据。如果我们需要将数据同时显示在屏幕上和文件中呢?这个时候就需要tee指令了。使用 last 可以查看到这个月的登入数据,而使用tee之后,会将数据同时传给下一个命令执行,也会将数据写入last.list文件中。所以,这个指令也是个好帮手。
tr 删除或者提到
语法:
[root @test /root ]# tr [-ds] SET1
参数说明:
-d :删除 SET1 这个字符串
-s :取代重复的字符
范例:
[root @test /root]# last | tr '[a-z]' '[A-Z]'
将小写改成大写
[root @test /root]# cat /etc/passwd | tr -d :
“:”这个符号在 /etc/passwd 中不见了!
[root @test /root]# cat /home/test/dostxt | tr -d '\r' > dostxt-noM
将 DOS 文件的行尾符号 ^M去除
split
语法:
[root @test /root ]# split [-bl] 输入文件输出文件前导字符
参数说明:
-b :以文件 size 来分
-l :以行数来分
范例:
split -l 5 /etc/passswd test #以5行大小的单位切割文件,切割出来的每一个文件的开头都是testXXX
压缩指令与正规表示法
压缩指令
这一块鸟哥的书有的讲的比较老,就没有比如 copress压缩指令貌似都没有用的了
bzip, bunzip2, bzcat
语法:
[root @test root]# bzip2 [-dz] filename <==压缩解压缩指令 #压缩之后,文件名自动为.bz2
[root @test root]# bzcat filename.bz2 <==读取压缩文件内容
参数说明:
-d :解压缩
-z :压缩
加压之后,源文件自动消失,会出现一个在源文件名后加上.bz的压缩文件,把.bz文件解压的时候,解压文件会消失,会自动出现一个去掉.bz拓展名的加压后的文件
范例:
同样的,我们以刚刚复制过来的 /root/man.config文件为例
[root @test root]# bzip2 –z man.config
[root @test root]# bzcat man.config.bz2
[root @test root]# bzip2 –d man.config.bz2
[root @test root]# bunzip2 man.config.bz2
gzip,gunzip, zcat
语法:
[root @test /root ]# gzip [-d#] filename <==压缩与解压缩
[root @test /root ]# zcat filename.gz <==读取压缩文件内容
参数说明:
-d :解压缩的参数
-# :压缩等级,1最不好,9最好,6为默认值
范例:
[root @test /root]# gzip man.config
会生成 man.config.gz文件
[root @test /root]# zcat man.config.gz
会读取出 man.config的内容
[root @test /root]# gzip -d man.config.gz
[root @test /root]# gunzip man.config.gz
解压缩,产生 man.config文件
[root @test /root]# gzip -9 man.config
以最大压缩比压缩 testing文件
这一块补充一下
gzip可以压缩文件夹,加上参数-r 比如
gzip -r testdir
testdir目录中的文件会一一都被压缩成.gz的文件,原文件消失,解压的时候则正好相反
bzip2 加参数也没办法压缩目录
这样比较好记忆:bzip根本不能压缩目录,gzip不能直接压缩目录(必须借助-r参数),于是出现了下面的tar指令
tar
语法:
[root @test /root ]# tar [-zxcvfpP] filename
[root @test /root ]# tar -N 'yyyy/mm/dd' /path -zcvf target.tar.gz source
参数说明:
-z :是否同时具有 gzip
-x :解开一个压缩文件
-t :查看 tarfile 里面的文件
-c :建立一个压缩文件
-v :压缩过程中显示文件
-f :使用文件名
-p :使用原文件的原有属性(属性不会依据用户而变)
-P :可以使用绝对路径
-N :比后面接的日期(yyyy/mm/dd)还要新的文件才会被打包进新建的文件中
--exclude FILE:在压缩过程中,不要将FILE打包
上面参数对比关联记忆
反义词 c 打包 --- x 解包
近义词 z 使用gzip压缩, j 使用bzip2压缩
v 现实作用的过程,主要作用了那些文件
f 说明后面会有自己命名
t 不解压,这是查看一下压缩文件的内容
范例
[root @test /root]# tar -cvf directory.tar directory
只将目录整合打包成一个文件
[root @test /root]# tar -zcvf directory.tar.gz directory
除了将目录打包外,同时以 gzip 压缩
[root @test /root]# tar -zcvf filename.tar.gz /home/test/*
将 /home/test/目录下的文件全部打包并压缩为一个 filename.tar.gz文件
[root @test /root]# tar -xvf directory.tar
解压tar包,请注意,由于没有gzip(.tar而非.tar.gz)的作用,所以只要使用 –xvf 即可,不需要加上z,否则会有问题
[root @test /root]# tar -zxvf directory.tar.gz
这个就是加上gzip的压缩结果!所以需要加上–z
[root @test /root]# tar –ztvf directory.tar.gz
这个 t 可以用来查看 tar 里面的文件信息,而不需要将它解开!
[root @test /root]# tar -zcvfP home.tar.gz /home
建立起来的压缩文件内文件为绝对路径
[root @test /root]# tar -N '2002/06/25' -zcvf home.tar.gz /home
在/home目录中,比2002/06/25还要新的文件才会被打包进入 home.tar.gz 文件中
[root @test /root]# tar -zcvf host.tar.gz / --exclude /mnt --exclude /proc
将根目录的所有数据都打包进 host.tar.gz文件中,但是/mnt及/proc则不打包
[root @test /root]# tar -cvf - /home | tar -xvf -
将/home打包后,直接解压缩在/root下。不需要再建立一次中间文件,不过,使用上面的语法最好使用绝对路径,这样不易产生问题,这个方式适合不想建立中间文件的情况。
cpio 备份与还原
语法:
[root @test /root ]# cpio -covB > [file|device] <备份
[root @test /root ]# cpio -icduv < [file|device] <还原
参数说明:
-o :将数据复制输出到文件或设备上
-i :将数据自文件或设备复制出到系统中
-t :查看 cpio 建立的文件或设备的内容
-c :以一种较新的便携格式(portable format)储存
-v :让储存过程中文件名称可以在屏幕上显示
-B :让默认的Blocks可以增至5120bytes,默认是512bytes
这样的好处是可以让大文件的储存速度加快,请参考i-nodes
-d :自动建立目录,由于cpio的内容可能不在同一目录内,
如此在反备份过程会有问题。这个时候加上-d,就可以自动将需要的目录建立起来
-u :自动用较新的文件覆盖较旧的文件
[root @test /root]# find / -print | cpio -covB > /dev/st0
将搜寻到的文件存到磁带机
[root @test /root]# cpio -icduv < /dev/st0
将磁带机的数据还原回来
[root @test /root]# cpio -icdvt < /dev/st0 > /tmp/content
将磁带机的内容(文件名)转存到/tmp/content
[root @test /root]# find / -type -f | cpio -o > /tmp/root.cpio
[root @test /root]# cpio -i < /tmp/root.cpio
- 备份:在备份用法中,它可以直接输出到文件或设备中,但是如前面说过的,必须
配合find这个指令。-o表示将文件或目录输出到右边,还记得命令重定向吗?对,
就是那个东西。在上面的例子中,我们将备份的数据复制到磁带机里,磁带机的设
备代号就是/dev/st0。 - 还原:如何还原数据?可以直接输入cpio –i,i就是input,例如上头的例子。这个指
令可以多看看
正规表示法
通配符
^ 句首字符相符
$ 句尾相同的字符
? 任何一个单一字符
- 随意几个任意字符
\ 跳转符号,将特殊字符变成普通字符
[list] 列表中的字符
[range] 列表中范围内的字符
[^list] 反向选择,与 [list] 相反
[^range] 反向选择,与 [range]相反
{n} 与前一个相同字连续n个
{n,m} 与前一个相同字连续n-m个
grep
范例:
grep ^boot /etc/* #找出etc目录下面所有文件中带有以boot在行首的**所有行**
grep [XYZ] /etc/* #找出etc目录中所有含有XYZ任意字符的行
学习shell scripts
脚本本身就是一个程序。bash中的脚本本身就是一个功能相当强大的程序工具,一些简单的计算任务,完全不需要使用C等高级语言,使用bash的shell脚本就能应对。
对于一个新手来说,脚本中的程序内容更少,更多的是一长串命令的组合。其实,bash的交互形式,就相当于及时的脚本执行过程。
bash执行脚本时
- 如果读取到一个Enter符号(CR),就尝试开始执行该行命令;
- 如同前面bash command提到的,指令间的多个空白会被忽略;
- 空白行也将被忽略,并且Tab也不会被理会;
- 如果一行内容太多,则可以使用\延伸至下一行;
- 此外,使用最多的#可做为注释。任何加在#后的字,将全部被视为注释文字而被忽
略。
在撰写脚本时,最好养成如下良好的习惯:
- 先宣告使用的shell为何(特别留意这一点,在某些情况下,例如/etc/crontab,如果没有宣告使用的shell,常会出现错误信息而导致脚本无法被执行)。
- 注明该脚本的内容功能、版本信息、作者、文件创建日期等。
- 每一个大步骤的主要功能(也顺便供自己未来做修改之用)。
如何执行一个脚本
· 一个是将该文件改成可以执行的属性,如chmod 755 scripts.file,然后执行该文件;
· 另一种则是直接以sh这个执行文件来执行脚本内容,如sh scripts.file。
范例:
第一个简单的脚本
#!/bin/bash #宣告这是一个shell脚本
# funtion : print string "hello! how are ?" on screen
# date : 2017/08/06
# written by yuchen
hello=hello\!\ how\ are\ you\? #注意\之后的都是转移的字符,包括空格,另一种写法就是放到 双引号中
echo $hello
sh test01-hello.sh
执行脚本
脚本中生命不同的变量
declare
语法:
[test @test test]# declare [-afirx]
参数说明:
-a :定义为数组 array
-f :定义为函数 function
-i :定义为整数 integer
-r :定义为只读 #类似于C语言中的const Java中的final
-x :定义为通过环境输出变量
这里出现了一个问题,就是用的Debian的linux默认情况使用的shell是debian自己的一个叫dash的,dash默认是不认识declare
关键字的,这个时候就会报错,比如在脚本中写的有declare关键字的时候,执行脚本的时候,可以使用指定的bash,bash test03-declare.sh
,或者修改系统默认的shell为bash。
交互性执行脚本
使用read
[root @test test]# vi test04-read.sh
#!/bin/bash
# This program is used to "read" variables
# VBird 2002/06/27
echo "Please keyin your name, and press Enter to start."
read name
echo "This is your keyin data ==> $name"
给脚本传入参数
[root @test test]# myscript opt1 opt2 opt3 opt4
脚本的逻辑判断是与表达式
逻辑判断式听起来和逻辑运算很像,其实性质是差不多的,相当于一种拓展,把原先的简单的符号变成了一个选项表示的表达式。
这一块特别的多,具体看以参看原书。
1 关于文件与目录的逻辑卷标
-f 常用!检测文件是否存在
-d 常用!检测目录是否存在
-b 检测是否为一个block文件
-c 检测是否为一个character文件
-S 检测是否为一个socket标签文件
-L 检测是否为一个符号链接文件
-e 检测某个东西是否存在!可以是任何东西
2. 关于程序的逻辑卷标
-G 检测是否由GID所执行的程序拥有
-O 检测是否由UID所执行的程序拥有
-p 检测是否为程序间传送信息的name pipe或FIFO
3. 关于文件的属性检测
-r 检测是否为可读属性
-w 检测是否为可写入属性
-x 检测是否为可执行属性
-s 检测是否为非空白文件
-u 检测是否具有SUID属性
-g 检测是否具有SGID属性
-k 检测是否具有sticky bit属性
4. 两个文件之间的判断与比较。例如
-nt 第一个文件比第二个文件新
-ot 第一个文件比第二个文件旧
-ef 第一个文件与第二个文件为同一个文件(诸如链接文件)
5. 逻辑与(and)和或(or)
&& 逻辑与
|| 逻辑或
下面讨论bash shell scripts的运算符的加减乘除
等于
!= 不等于
< 小于
大于
-eq 等于
-ne 不等于
-lt 小于
-gt 大于
-le 小于或等于
-ge 大于或等于
-a 双方都成立(and)
-o 单方成立(or)
-z 空字符串
-n 非空字符串