《Linux命令行与Shell脚本编程大全》学习整理笔记
1、初识Linux Shell
Linux内核控制着计算机系统上所有的硬件和软件,在必要时分配硬件,并根据需要执行软件。内核主要负责四种功能:系统内存管理、软件程序管理、硬件设备管理、文件系统管理。
系统内存管理
内核不仅管理服务器上的可用物理内存,还可以创建和管理虚拟内存(即实际不存在的内存);内核通过硬盘上的存储空间来实现虚拟内存,这块区域称为交换空间(swap space)。内核不断在交换空间和实际的物理内存之间反复交换虚拟内存中的内容,这使得系统以为它拥有比物理内存更多的可用内存。
内存存储单元按组划分为很多块,这些块称作页面(page),内核将每个页面放在物理内存或交换空间,然后,内核会维护一个内存页面表,指明哪些页面位于物理内存内,哪些页面被换到了磁盘上。内核会记录哪些内存页面正在使用,并自动把一段时间内未访问的内存页面复制到交换空间区域(称为换出 swapping out)—即使还有可用的物理内存。当程序要访问一个已被换出的内存页面时,内核必须从物理内存换出另一个内存页来让出空间,然后从交换空间换入目标页面。
软件程序管理
Linux操作系统将运行的程序称为进程。内核控制着Linux系统如何管理运行在系统上的所有进程。内核创建的第一个进程(称为init进程)来启动系统上的所有其他进程。
硬件设备管理
Linux系统将硬件设备当成特殊的文件,称为设备文件。设备文件包括三类:
字符型设备文件:字符型设备文件指处理数据时每次只能处理一个字符的设备,大多数类型的调制解调器和终端都是作为字符型设备文件创建的;块设备文件:块设备文件是指处理数据时每次能处理大块数据的设备,比如硬盘。网络设备文件:网络设备文件指采用数据包发送和接收数据的设备,包括各种网卡设备。
文件系统管理
Linux内核支持通过不同类型的文件系统从硬盘中读写数据。Linux内核采用虚拟文件系统(VFS),作为和每个文件系统交互的接口。
大多数Linux发行版默认的Shell都是GNU bash shell。
2、Linux目录
Linux虚拟目录中比较复杂的部分是它如何协调管理各个存储设备。在Linux PC上安装的第一块硬盘称为根驱动器。根驱动器包含了虚拟目录的核心,其他目录都是从那里开始构建的。Linux会在根驱动器上创建一些特别的目录,我们称之为挂载点(mount point)。挂载点是虚拟目录中用于分配额外存储设备的目录。虚拟目录会让文件和目录出现在这些挂载点目录中,然 而实际上它们却存储在另外一个驱动器中。
通常系统文件会存储在根驱动器中,而用户文件则存储在另一驱动器中。
3、监测程序
1)ps命令
默认情况下,ps命令只会显示当前控制台下,属于当前用户的进程。
ps只能显示某个特定时间点的信息,如果想观察哪些频繁换进换出的内存的进程趋势,用ps命令就不是很方便了。
2)top命令
Top命令跟ps命令一样,显示进程的信息,但是top命令是实时显示的。
Load Avg:平均值负载有三个值:最近1分钟、最近5分钟和最近15分钟的平均负载。值越大说明系统的负载越高。如果最近15分钟的负载平均都很高,说明系统有问题了。
什么样的程度才算是高负载?这个值取决于系统的硬件配置以及系统上通常运行的程序。通常,如果系统负载超过2,说明系统比较繁忙了。
3)kill命令
kill命令可通过进程ID给进程发信号,默认情况下,kill命令会向命令行中列出的全部PID发送一个TERM信号。要发送kill命令,必须是进程的属主或者root权限。TERM信号告诉进程可能的话就停止运行,进程可以选择忽略。
4)监测磁盘性能
mount 挂载存储媒体,Linux文件系统将所有磁盘都并入一个虚拟目录下。在使用新的存储媒体之前,需要把它放在虚拟目录下,这项工作称为挂载。默认情况下,mount命令会显示当前系统上挂载的设备列表。卸载设备umount命令。
5)df命令
如果需要知道某个设备上还有多少磁盘空间,使用df命令。df命令的输出值显示的是Linux系统认为的当前值,有时系统运行的进程已经创建和删除了某些文件,但是尚未释放,这个值不会计算在闲置空间的。
6)排序数据
处理大量数据时一个常用命令sort。sort是对数据进行排序,按照会话指定的默认语言的排序规则对文本数据进行排序。Sort命令默认是按照文本的顺序进行排序。如果要排序数字,sort -n 命令;如果要排序日期数据,sort -M 命令.
-k和-t参数在对按字段分隔的数据进行排序时非常有用,例如/etc/passwd文件。可以用-t 参数来指定字段分隔符,然后用-k参数来指定排序的字段。举个例子,要对前面提到的密码文件 /etc/passwd根据用户ID进行数值排序,可以这么做:
$ sort -t ‘:’ -k 3 -n /etc/passwd
现在数据已经按第三个字段——用户ID的数值排序.
-n参数在排序数值时非常有用,比如du命令的输出。
$ du -sh * | sort -nr
注意,-r参数将结果按降序输出,这样就更容易看到目录下的哪些文件占用空间最多。
7)搜索数据grep
Gerp [option] pattern [file]
Grep命令会在输入或者指定的文件中查找匹配指定模式的字符的行。
Grep -v 反向匹配,指输出不匹配条件的行
Grep -n 输出匹配行的行号
Grep -c 获取有多少行匹配了
Grep -e t -e f file 指定多个匹配模式
8)压缩和归档数据 zip 和 tar
gzip命令会压缩你在命令行指定的文件。也可以在命令行指定多个文件名甚至用通配符来一次性批量压缩文件。
$ gzip my*$ ls -l my*-rwxr–r— 1 rich rich 03 Sep 6 13:43 myprog.c.gz-rwxr-xr-x 1 rich rich 5178 Sep 6 13:43 myprog.gz-rwxr–r— 1 rich rich 59 Sep 6 13:46 myscript.gz-rwxr–r— 60 Sep 6 13:44 myscript2.gztar function [options] object1 object2 …tar -cvf test.tar test/ test2/
上面的命令创建了名为test.tar的归档文件,含有test和test2目录内容。接着,用下列命令: tar -tf test.tar列出tar文件test.tar的内容(但并不提取文件)。最后,用命令: tar -xvf test.tar通过这一命令从tar文件test.tar中提取内容。如果tar文件是从一个目录结构创建的,那整个目 录结构都会在当前目录下重新创建。
4、理解shell
5、Linux环境变量
bash shell 用一个叫做环境变量的特性来存储有关shell会话和工作环境的信息。环境变量分为:
全局变量:对于shell会话和所有生成的子shell都可见。
局部变量:只对创建它们的shell可见。
要查看全局变量,可以使用env或printenv命令、echo $HOME 单个变量
1)设置全局环境变量
创建全局环境变量的方式是先创建一个局部环境变量,然后把它导出到全局环境中。
$ my_variable=”I am Global now” $$ export my_variable$ echo $my_variable I am Global now#删除环境变量$ echo $my_variable I am Global now$ unset my_variable$ echo $my_variable
在涉及环境变量名时,什么时候该使用$,什么时候不该使用$,实在让人摸不着头脑。记住一点就行了:如果要用到变量,使用$;如果要操作变量,不使用$。这条规则的一 个例外就是使用printenv显示某个变量的值
2)定位系统环境变量
登录Linux启动一个shell时候,默认情况下shell会在几个文件中查找命令,这些文件称为启动文件或者环境文件。登录shell会从5个不同的启动文件里读取命令:
/etc/profile$HOME/.bash_profile$HOME/.bashrc$HOME/.bash_login$HOME/.profile
/etc/profile文件是系统默认的bash shell主启动文件,系统上每个用户登录时候都会执行这个配置文件。
6、文件权限
Linux系统使用一个专门的文件来将用户的登录名匹配到对应的UID值。这个文件就是 /etc/passwd文件,它包含了一些与用户有关的信息。
1)添加新用户
向Linux系统中添加新用户的命令是useradd
2)删除用户
userdel
3)默认文件权限
umask命令用来设置所创建文件和目录的默认权限。
1)vim/vi
?? PageDown(或Ctrl F):下翻一屏。
?? PageUp(或Ctrl B):上翻一屏。
?? G:移到缓冲区的最后一行。
?? num G:移动到缓冲区中的第num行。
?? gg:移到缓冲区的第一行。
2)查找和替换
:s/old/new/
?? :s/old/new/g:一行命令替换所有old。
?? :n,ms/old/new/g:替换行号n和m之间所有old。
?? :%s/old/new/g:替换整个文件中的所有old。
?? :%s/old/new/gc:替换整个文件中的所有old,但在每次出现时提示。
8、构建基本脚本
shell脚本的关键在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给 另一个命令。shell可以让你将多个命令串起来,一次执行完成。如果要两个命令一起运行,可以 把它们放在同一行中,彼此间用分号隔开。
在创建脚本文件的时候,必须要在第一行指定要使用的shell。#!/bin/bash
1)注释
在脚本文件中,通常#用作注释。在shell脚本中你可以在独立的行中编写命令,shell会根据命令在文件中出现的顺序处理。
2)echo输出
echo输出文本内容,通常情况下,不需要加引号的echo This is test.
但是当输出的文本中存在单引号时,就会产生不一致的预期输出
echo命令可用单引号或双引号来划定文本字符串。如果在字符串中用到了它们,你需要在 文本中使用其中一种引号,而用另外一种来将字符串划定起来。
$echo”Thisisatesttoseeifyou’repayingattention”Thisisatesttoseeifyou’repayingattention$echo’Richsays”scriptingiseasy”.’Rich says “scripting is easy”.
echo -n 将后面输出的一句,输出在同一行上。
3)使用变量
变量允许你临时性的将信息存储在shell脚本中,以便和脚本中的其他命令一起使用。
环境变量:echo中的环境变量在脚本运行时替换成当前值。也可以将$HOME 变量放到”字符串中”解析,如果确实需要$符号表示时,需要\反斜杠进行转义。
用户变量:用户变量可以是任意字母、数字或者下划线组成的文本字符串,长度不超过20;用户变量大小写区分。
使用=等号进行赋值,在变量、等号、值之间不允许有空格。
shell脚本会自动决定变量值的数据类型。在脚本整个生命周期中,shell脚本中定义的变量会一直保持它们的值,但是在shell结束时会被删除掉。
命令替换:
shell脚本中最有用的特性之一就是可以从命令输出中提取信息,并将其赋给变量。有两种方式可以将命令输出赋给变量:
反引号字符(`)$() 格式要么用一对反引号把整个命令行命令围起来: testing=`date`要么使用$()格式:testing=$(date)
shell会运行命令替换符号中的命令,并将其输出赋给变量testing。注意,赋值等号和命令替换字符之间没有空格
4)管道
将一个命令的输出作为另一个命令的输入。|
9、结构化命令
1)if-then语句
IfcommandThen commandFi
#bash shell的if语句会运行if后面的命令,如果该命令的的退出状态码是0(命令运行成功),位于then部分的命令就会被执行。如果改命令的退出状态是其他值,then部分的命令就不会被执行。#在then部分,你可能使用不止一个命令,可以列出多条命令,bash shell会将这些当成一个语句块。
2)if-then-else结构
ifcommandthencommandelsecommandsfi
3)test命令
if-then语句能否测试命令退出状态码之外的条件,答案是不能。Test命令提供了在if-then中测试不同条件的途径。这样if-then语句就与其他编程语言中的if-then语句 以类似的方式工作了。如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得 if-then语句不会再被执行。
iftestconditionthencommandsfi#如果不写test命令的condition部分,它会以非零的状态码推出,这样就执行if的else语句部分。$ cat test6.sh#!/bin/bash#Testingthetestcommand#iftestthenecho”NoexpressionreturnsaTrue”elseecho”NoexpressionreturnsaFalse”fi$./test6.shNoexpressionreturnsaFalse# bashshell提供了另一种条件测试方法,无需在if-then中添加test语句If[condition]ThencommandsFi
方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,
否则就会报错。
test命令可以判断三类条件:
?? 数值比较
?? 字符串比较
?? 文件比较
数值比较
字符串比较
#字符串相等比较
$cattest7.sh#!/bin/bash#testingstringequalitytestuser=richif[$USER=$testuser]then####比较字符串相等=echo”Welcome$testuser”fi$ ./test7.sh Welcome rich
#字符串顺序比较,需要转义
$cattest9.sh#!/bin/bash#mis-usingstringcomparisons#13val1=baseballval2=hockey#if[$val1\>$val2]thenecho”$val1isgreaterthan$val2″elseecho”$val1islessthan$val2″fi$./test9.shbaseballislessthanhockey
#比较的字符串中含有大写字母
$cattest9b.sh#!/bin/bash#testingstringsortorderval1=Testingval2=testingif[$val1\>$val2]thenecho”$val1isgreaterthan$val2″elseecho”$val1islessthan$val2″fi$$./test9b.shTestingislessthantesting$$sorttestfiletestingTesting
在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。当你将同样的 字符串放进文件中并用sort命令排序时,小写字母会先出现。这是由各个命令使用的排序技术 不同造成的。比较测试中使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。sort 命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺 序中小写字母出现在大写字母前。
#字符串大小:-n和-z可以检查一个变量是否含有数据。
$cattest10.sh#!/bin/bash#testingstringlengthval1=testingval2=”if[-n$val1]thenecho”Thestring’$val1’isnotempty”elseecho”Thestring’$val1’isempty”fiif[-z$val2]thenecho”Thestring’$val2’isempty”elseecho”Thestring’$val2’isnotempty”fi#if[-z$val3]thenecho”Thestring’$val3’isempty”elseecho”Thestring’$val3’isnotempty”fi$$./test10.shThestring’testing’isnotemptyThestring”isemptyThe string ” is empty
空的和未初始化的变量会对shell脚本测试造成灾难性的影响。如果不是很确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过-n或-z来测试一下变量是否含有值。
文件比较
4)if-then高级特性
用于数学表达式的双括号
用于高级字符串处理功能的双方括号、
双括号允许在比较过程中使用高级数学表达式,test命令只能在比较使用简单的算术操作(( expression ))
$cattest23.sh#!/bin/bash#usingdoubleparenthesis#val1=10if(($val1**2>90))then((val2=$val1**2))echo”Thesquareof$val1is$val2″fi$./test23.shThe square of 10 is 100 $
注意,不需要将双括号中表达式里的大于号转义。这是双括号命令提供的另一个高级特性。
双方括号提供了针对字符串比较的高级特性,[[ expression ]],并且提供了模式匹配。
在模式匹配中,可以定义一个正则表达式来匹配字符串值。
$ cat test24.sh#!/bin/bash#usingpatternmatching#4if[[$USER==r*]]thenecho”Hello$USER”else5echo”Sorry,Idonotknowyou”fi$ ./test24.sh 6 Hello rich
在上面的脚本中,我们使用了双等号(==)。双等号将右边的字符串(r*)视为一个模式, 并应用模式匹配规则。双方括号命令$USER环境变量进行匹配,看它是否以字母r开头。如果是 的话,比较通过,shell会执行then部分的命令。
5)case命令
有了case命令,就不需要再写出所有的elif语句来不停地检查同一个变量的值了。case命令会采用列表格式来检查单个变量的多个值。
casevariableinpattern1|pattern2)commands1;;pattern3)commands2;;*)defaultcommands;;esac
case命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的,那么shell会执行 为该模式指定的命令。可以通过竖线操作符在一行中分隔出多个模式模式。星号会捕获所有与已 知模式不匹配的值。这里有个将if-then-else程序转换成用case命令的例子。
$cattest26.sh#!/bin/bash#usingthecasecommand#case$USERinrich|barbara)echo”Welcome,$USER”echo”Pleaseenjoyyourvisit”testing)echo”Specialtestingaccount”jessica)echo”Donotforgettologoffwhenyou’redone”echo”Sorry,youarenotallowedhere”esac$$./test26.shWelcome,richPlease enjoy your visit $
case命令提供了一个更清晰的方法来为变量每个可能的值指定不同的选项
10、更多结构化命令
1)for
forvarinlist#在list参数中,需要提供迭代中用到的一系列值。docommandsdone
记住,for循环假定每个值都是用空格分割的
2)分隔符
默认情况下,bash shell会将下列字符当做分隔符。
空格
制表符
换行符
可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段 分隔符的字符。例如,如果你想修改IFS的值,使其只能识别换行符,那就必须这么做:IFS=$’\n’
3)while命令
whiletestcommanddoothercommandsdone
until命令和while命令工作的方式完全相反。until命令要求你指定一个通常返回非零退 出状态码的测试命令。只有测试命令的退出状态码不为0,bash shell才会执行循环中列出的命令。一旦测试命令返回了退出状态码0,循环就结束了。
untiltestcommandsdoothercommandsdone
在处理多个循环时,break命令会自动终止你所在的最内层的循环。
有时你在内部循环,但需要停止外部循环。break命令接受单个命令行参数值:break n 其中n指定了要跳出的循环层级。默认情况下,n为1,表明跳出的是当前的循环。如果你将n设为2,break命令就会停止下一级的外部循环