第1章 初识Linux shell
内存存储单元按组划分成很多块,这些块称作页面(page).
内核创建了第一个进程(称为init进程)来启动系统上所有其他进程.
Linux系统将硬件设备当成特殊的文件,称为设备文件.
第3章 基本的bash shell命令
/etc/passwd文件包含了所有系统用户账户列表以及每个用户的基本配置信息.
man命令用来访问存储在Linux系统上的手册页面.
关键字搜索:man -k 关键字
ls命令: -R参数叫作递归选项.它列出了当前目录下包含的子目录中的文件.
-l参数会产生长列表格式的输出.
touch: 修改每个指定文件的存取(access)和修改(modification)时间戳记.若文件不存在且没有使用-c选项,则会生成空文件.
cp: 复制文件 用法: cp [source] [destination]
-R递归复制整个目录
链接文件
符号链接就是一个实实在在的文件,它指向存放在虚拟目录结构中某个地方的另一个文件.这两个通过符号链接在一起的文件,彼此的内容并不相同.
硬链接会创建独立的虚拟文件,其中包含了原始文件的信息及位置,但是它们从根本上而言是同一个文件.
mv: 重命名,移动.
rm: 删除.
mkdir: 创建目录.
file: 查看文件类型
查看文件:cat,more,less,tail,head.
第4章 更多的的bash shell命令
ps: 查看进程 常用选项:
-ef 查看系统上运行的所有进程
top: 实时显示进程信息.
结束进程:kill,killall.
df: 查看磁盘使用情况.
du: 显示某个特定目录的磁盘使用情况
sort: 排序
grep:
grep [options] pattern [file]
-v参数,反向搜索(不匹配)
-n参数,显示匹配模式的行所在的行号
-c参数,打印有多少行含有匹配的模式
-e参数,指定多个匹配模式
-b参数,在输出的每行前面同时打印出当前行在输入文件中的字节偏移量
-o参数,只输出文件中匹配到的部分.常常和 -b 一起使用,得出匹配内容的偏移量.
-r参数,遇到目录时递归读取目录下每一个文件
第5章 理解shell
在生成子shell进程时,只有部分父进程的环境被复制到子shell环境中.
进程列表: 将一系列命令放入括号()中,命令之间用;分割.进程列表会生成子shell来执行命令.echo $BASH_SUBSHELL若大于0则表明有子shell.
后台模式: 在命令末尾加上&. jobs命令显示后台作业信息.
alias: 创建别名.
第6章 使用Linux环境变量
环境变量分为两类:全局变量和局部变量.全局变量可以用于所有shell,局部环境变量只能在定义它们的进程中可见.自己创建的局部变量或shell脚本,应使用小写字母命名,避免重定义系统环境变量.
要查看全局变量,可以使用env或printenv命令
set命令显示某个特定进程设置的所有环境变量.
unset命令用来删除某个环境变量.
在变量名前加$相当于取环境变量的值(类似于c中的*).
在设定全局环境变量的进程所创建的子进程中,该变量都是可见的,修改(删除)子shell中全局环境变量并不会影响到父shell中该变量.
PATH环境变量定义了用于进行命令和程序查找的目录.添加目录方法PATH=$PATH:/home/christine/Scripts
/etc/profile :该文件是bash shell默认的的主启动文件.只要你登录了Linux系统,bash就会执行/etc/profile启动文件中的命令.
存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件,该文件有两个作用:查看/etc目录下通用的bashrc文件,为用户提供一个定制自己的命令别名的地方.
第7章 理解Linux文件权限
/etc/passwd 文件包含以下信息:
登录用户名
用户密码
用户账户的UID(数字形式)
用户账户的组ID(GID)(数字形式)
用户账户的文本描述(称为备注字段)
用户HOME目录的位置
用户的默认shell
示例:wanfeng:x:1000:1000:wanfeng,,,:/home/wanfeng:/bin/bash
用户密码字段都被设置成了x,Linux系统都将用户密码保存在/etc/shadow中.
/etc/shadow 文件包含以下信息:
与/etc/passwd文件中的登录名字段对应的登录名
加密后的密码
自上次修改密码后过去的天数密码(自1970年1月1日开始计算)
多少天后才能更改密码
多少天后必须更改密码
密码过期前提前多少天提醒用户更改密码
密码过期后多少天禁用用户账户
用户账户被禁用的日期(用自1970年1月1日到当天的天数表示)
预留字段给将来使用
useradd:添加新用户
userdel:删除用户
usermod:修改/etc/passwd文件中的字段
passwd:修改用户密码
chsh:修改默认登录shell
八进制模式安全设置:获取这3个rwx权限的值,然后将其转换成3位二进制值,用一个八进制值来表示.三位八进制值组成了user,group,other的权限.
umask:umask值只是个掩码,它会屏蔽掉不想授予该安全级别的权限,对文件来说一开始的权限是666,减去umask值之后,剩下的文件权限就是默认文件权限,对目录来说一开始的权限是777.
chmod:改变文件和目录权限.
除了三位八进制权限之外,Linux还储存了三个额外信息位:
设置用户ID(SUID):当文件被用户使用时,程序会以文件属主的权限运行.
设置组ID(SGID):对文件来说,程序会以文件属组的权限运行;对目录来说,目录中创建的新文件会以目录的默认属组作为默认属组.
粘着位:文件或目录只能由root用户或者其所有者移动或删除.
这三位组成一位八进制值,加在标准三位八进制权限之前.
第11章 构建基本脚本
shell脚本里变量、等号和值之间不能出现空格.
命令替换: 命令替换允许将shell命令的输出赋给变量,有两种格式:反引号字符(`)和$()格式.例:val=`ls $HOME`或val=$(ls $HOME)
输出重定向: 命令的输出发送到一个文件中,而不是在屏幕打印.使用大于号完成这项功能.
command > outputfile
若不想覆盖文件原有内容,可以用双大于号(>>)来追加数据.
输入重定向: 输入重定向符号是小于号(<).
command < inputfile.
内联输入重定向: 符号是远小于号(<<).除了这个符号,你必须指定一个文本标记来划分输入数据的开始和结尾.任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致.
command << marker
data
marker
管道: 管道被放在命令之间,将一个命令的输出重定向到另一个命令中:
command1 | command2
Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来.在第一个命令产生输出的同时,输出会被立即送给第二个命令.
数学运算:
bash shell提供了一种更简单的方法来执行数学表达式$[ operation ],bash shell数学运算符只支持整数运算.
bash计算器(bc): 支持浮点数运算.浮点运算是由内建变量scale控制的,必须将这个值设置为希望在计算结果中保留的小数位数.
在脚本中有两种使用方法:
variable=$(echo "options; expression" | bc)
或者
1 variable=$(bc << EOF 2 options 3 statements 4 expressions 5 EOF 6 )
退出脚本: 默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出.exit命令允许你在脚本结束时指定一个退出状态码,范围为0~255.
第12章 使用结构化命令
if-then 语句:若if后面命令的状态退出码是0,位于then部分的命令就会被执行.
if command then commands fi
if-then-else 语句:
if command then commands else commands fi
嵌套的if-then语句:
if command1 then commands elif command2 then more commands fi
总结:if后面必须有命令和then.
test命令
if test condition then commands fi
condition是test命令要测试的一系列参数和值.
bash shell提供了另一种条件测试方法,无需在if-then语句中声明test命令:
if [ condition ] then commands fi
方括号定义了测试条件.第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错.
1. 数值比较(整数)
n1 -eq n2 检查n1是否与n2相等 n1 -ge n2 检查n1是否大于或等于n2 n1 -gt n2 检查n1是否大于n2 n1 -le n2 检查n1是否小于或等于n2 n1 -lt n2 检查n1是否小于n2 n1 -ne n2 检查n1是否不等于n2
2. 字符串比较:大于小于符号需转义( \ )
str1 = str2 检查str1是否和str2相同 str1 != str2 检查str1是否和str2不同 str1 < str2 检查str1是否比str2小 str1 > str2 检查str1是否比str2大 -n str1 检查str1的长度是否非0 -z str1 检查str1的长度是否为0
3. 文件比较
-d file 检查file是否存在并是一个目录 -e file 检查file是否存在 -f file 检查file是否存在并是一个文件 -r file 检查file是否存在并可读 -s file 检查file是否存在并非空 -w file 检查file是否存在并可写 -x file 检查file是否存在并可执行 -O file 检查file是否存在并属当前用户所有 -G file 检查file是否存在并且默认组与当前用户相同 file1 -nt file2 检查file1是否比file2新 file1 -ot file2 检查file1是否比file2旧
复合条件测试:
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
第13章
for命令:
for var in list do commands done
for根据IFS来分隔list
如果要指定多个IFS字符,只要将它们在赋值行串起来就行. IFS=$'\n':;
IFS='\n' 将字符\和字符n作为IFS的换行符.
IFS=$'\n' 使用换行符做为字段分隔符.
在文件名或路径名中使用通配符可使for自动遍历目录中的文件.
若文件名中含有空格,应该将$file变量用双引号圈起来.
while命令:
while test command do other commands done
break命令:break可以跳出单层循环,break n可以指定要跳出的循环层级.
continue和break一样,也可以指定要终止的循环层级.
在shell脚本中,你可以对循环的输出使用管道或进行重定向。这可以通过在done命令之后添加重定向命令来实现.
第14章 处理用户输入
bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的所有参数.
位置参数变量是标准的数字: $0是程序名,$1是第一个参数, $2是第二个参数,依次类推.当参数序号大于9时,要使用{}将数字包围起来,如${10}.由于每个参数是通过空格分隔的,若参数值中有空格,需要使用引号.也可以使用变量替换数字,如${!count},注意:花括号中不能使用$符号,用!替代.
basename命令:返回不包含路径的脚本名.
在使用参数之前,需要判断参数中是否存在数据[ -n "$1" ],在判断时,要将被判断的参数加上双引号,否则会判断失败.
特殊变量:
$# :参数个数(不计入$0)
$* :将命令行上提供的所有参数当作一个单词保存(在for中不能被分隔)
$@ :将命令行上提供的所有参数当作同一字符串中的多个独立的单词(在for中可以被分隔)
$$ 本进程PID
shift命令: 删除最左边的变量,将所有参数左移一个位置.注:$0不会受影响.也可以一次移动多个位置:shift n.
getopt命令: getopt optstring parameters
optstring定义了命令行有效的选项字母,每个需要参数值的选项字母后紧跟一个冒号.例:
getopt ab:cd -a -b test1 -cd test2 test3
-a -b test1 -c -d -- test2 test3
set和getopt配合使用就可以达到格式化原参数并将其替换的目的,方法如下:
set -- $(getopt -q ab:cd "$@")
getopt不擅长处理带空格的参数
getopts命令: getopts optstring variable
每次调用它时,它只处理命令行上检测到的一个参数.能很好的处理带空格的参数.
optstring值类似于getopt命令,variable中保存当前正在处理的那个参数
getopts命令会用到两个环境变量.如果选项需要跟一个参数值,OPTARG环境变量就会保存这个值.OPTIND环境变量保存了参数列表中getopts正在处理的参数位置.
例:
#!/bin/bash # simple demonstration of the getopts command # echo while getopts :ab:c opt do case "$opt" in a) echo "Found the -a option" ;; b) echo "Found the -b option, with value $OPTARG";; c) echo "Found the -c option" ;; *) echo "Unknown option: $opt";; esac done
练习例程:
#!/bin/bash count=0; while [ -n "${!count}" ] do echo Parameter $count is ${!count} count=$[$count + 1] done
read命令: 从标准输入或另一个文件描述符中接受输入.read命令会将提示符后输入的所有数据分配给单个变量.若指定多个变量,输入的每个数据值都会按序分配给下一个变量.如果变量数量不够,剩下的数据就全部分配给最后一个变量
-p选项,打印提升信息.
-t选项,指定计时器(单位为秒),过期后read返回非0退出状态码.
-n选项,指定读取多少个字符后退出.
-s选项,避免输入数据显示出来.
从文件中读取方法: cat test | while read line
第15章 呈现数据
只重定向错误: STDERR文件描述符被设成2.可以选择只重定向错误消息,将该文件描述符值放在重定向符号前: ls -al badfile 2> test2
重定向错误和数据: ls -al badtest 2> test2 1> test1
临时重定向: 文件描述符数字之前加一个&. echo "This is an error message" >&2
永久重定向: exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件. exec 2>testerror
tee命令: 相当于管道的一个T型接头.它将从STDIN过来的数据同时发往两处.一处是STDOUT,另一处是tee命令行所指定的文件名: tee filename,若想追加到文件,使用-a选项.
第16章 控制脚本
生成信号:
Ctrl+C组合键会生成SIGINT信号
Ctrl+Z组合键会生成一个SIGTSTP信号
kill可以向指定pid的进程发送信号.
捕获信号:
trap commands signals
commands为捕获到信号时运行的命令.
当signals为EXIT时,会捕获脚本的退出.
可以删除已设置好的捕获,只需要在trap命令与希望恢复默认行为的信号列表之间加上两个破折号就行了.
第17章 创建函数
创建函数有两种方法:
function name {
commands
}
或
name() {
commands
}
函数使用时只需要指定函数名,且不能在定义之前使用.重定义会覆盖原来的定义,且不会有警告.
函数的默认退出状态码是最后运行的命令的退出状态码.使用return命令来退出函数并返回特定的退出状态码(范围为0~255)
函数中的所有echo语句都会成为函数输出,而不是输出到标准输出.接受函数输出的方式与c语言相似.
bash shell会将函数当作小型脚本来对待.这意味着可以像普通脚本那样向函数传递参数.
全局变量: 在脚本中定义的任何变量都是全局变量.
局部变量: 变量声明前有local关键字的变量.
第19章 初识sed和gawk
sed编辑器
s命令: s/pattern/replacement/flags
用斜线间指定的第二个文本字符串来替换第一个文本字符串模式. 标记(flags)为可选部分,默认情况(无标记)下它只替换每行中出现的第一处,g标记表示全部替换,数字n标记时表示替换第n处的匹配.
d命令: 删除模式匹配或指定地址的所有行.
i命令: 会在指定行前增加一个新行.
a命令: 会在指定行后增加一个新行.
c命令: 使用新行替换指定行的文本的内容.注:命令i和a还有c之后的所有字符都将会被认为是新行的内容("\"除外).
y命令: [address]y/inchars/outchars/ 转换命令会对inchars和outchars值进行一对一的映射.inchars中的第一个字符会被转换为outchars中的第一个字符,第二个字符会被转换成outchars中的第二个字符,inchars和outchars长度必须相同.
=命令: 打印行号.
l命令: 打印数据流中的文本和不可打印的ASCII字符.
w命令: [address]w filename 向文件写入行.
r命令: [address]r filename 将一个独立文件中的数据插入到数据流中.
p标记: 打印一行,通常和-n选项一起使用,只打印包含匹配文本模式的行
命令组合: 可以使用花括号将多条命令组合起来.注:寻址可在花括号之前,表示对花括号之中的所有命令适用,也可以在花括号之中,只对其后的一条语句适用.
行寻址:分为数字方式的行寻址和文本模式过滤.行地址区间:a,b 从某行开始的所有行:a,$.
[address]command
address {
command1
command2
command3
}
-e选项: 执行多个命令. sed -e 's/brown/green/; s/dog/cat/'
gawk程序
gawk options program file
选项:
-F fs 指定行中划分数据字段的字段分隔符
-f file 从指定的文件中读取程序
-v var=value 定义gawk程序中的一个变量及其默认值
gawk程序脚本用一对花括号来定义,而且由于gawk命令行假定脚本是单个文本字符串,你还必须将脚本放到单引号中.
gawk会自动给一行中的每个数据元素分配一个变量,$0代表整个文本行,$n代表第n个数据字段,默认使用空格来划分数据,也可以使用-F选项.
注:使用print命令打印字符串时必须用双引号包括,否则会被当做变量,因为gawk不需要使用$来引用变量.
练习: 使用gawk实现打印本目录下的的文件大小和名字: ls -lh | gawk 'BEGIN{print "SIZE\tNAME"} {print $5"\t"$9}'
练习脚本:
#!/bin/bash
ls -l | sed '1d'| gawk 'BEGIN{print "SIZE\tNAME"} {print $5"\t"$9}' > output.txt
flag=1;
cat output.txt | while read line
do
if [ $flag -eq 0 ]
then
echo $line
fi
flag=0
done | sort -n
rm output.txt
第20章 正则表达式
BRE
^ 定义从数据流中文本行的行首开始的模式,^ 放到模式开头之外的其他位置,那么它就跟普通字符一样.
$ 定义了行尾锚点,将这个特殊字符放在文本模式之后来指明数据行必须以该文本模式结尾.
. 匹配除换行符之外的任意单个字符.
[chars] 使用方括号定义一个字符组,方括号中包含所有希望出现在该字符组中的字符.
[^chars] 在字符组的开头加个脱字符就是排除型字符组,匹配不含组内字符的模式.
[0-9] -表示区间
* *放置在字符(组)后面表明该字符(组)必须在匹配模式的文本中出现0次或多次
[[:alpha:]] 匹配任意字母字符,不管是大写还是小写
[[:alnum:]] 匹配任意字母数字字符0~9、 A~Z或a~z
[[:blank:]] 匹配空格或制表符
[[:digit:]] 匹配0~9之间的数字
[[:lower:]] 匹配小写字母字符a~z
[[:print:]] 匹配任意可打印字符
[[:punct:]] 匹配标点符号
[[:space:]] 匹配任意空白字符:空格、制表符、 NL、 FF、 VT和CR
[[:upper:]] 匹配任意大写字母字符A~Z
ERE
? 表明前面的字符可以出现0次或1次.
+ 表明前面的字符可以出现1次或多次,但必须至少出现1次.
{} 花括号允许你为可重复的正则表达式指定一个上限.这通常称为间隔(interval).可以用两种格式来指定区间.必须指定gawk程序的--re-interval命令行选项
m:正则表达式准确出现m次。
m, n:正则表达式至少出现m次,至多n次
| 逻辑OR,组合两个或多个模式.
() 表达式分组该组会被视为一个标准字符