《shell编程从入门到精通》张昊编著 学习笔记
目录
Linux程序的3种运行方法
使程序具有可执行权限
调用命令解释器执行
使用source执行
I/O重定向
标准输入
标准输出
标准错误
管道
管道的数据共享在linux内核中是通过内存拷贝实现的,相交于CPU运算,数据的移动更耗时。因此在设计管道时,要尽量把能够减少数据量的操作置于管道的前端。这样可以保证数据的快速拷贝,减少程序运算量。
重定向
重定向标准输出 cat xx.log 1> xx.bak 1默认,可以省略
重定向标准错误 cat xx.log 2> /dev/null
重定向标准输入 0<
Linux Shell
shell语言是 动态类型语言,弱类型语言
shell的3种变量
用户变量
局部变量:声明时需要以 local 修饰,如 local num=1234
全局变量:声明时不需任何修饰,如 num=1234
位置变量
另称系统变量、位置参数
直接引用的位置参数只能从0-9,超过必须用括号括起,如${10}
常用符号:
$# 变量个个数
$0 输出文件名
$? 输出上一条命令的返回值
$ 输出所有参数
环境变量
如 PATH、HOME、LOGNAME...
替换运算符
模式匹配运算符
${varname#pattern} 从头开始匹配,删除匹配的最短部分,并返回剩下部分
> path="/home/prince/desktop/long.file.name"
> echo "${path#/*/}"
> prince/desktop/long.file.name
${varname##pattern} 从头开始匹配,删除匹配的最长部分,并返回剩下部分
> path="/home/prince/desktop/long.file.name"
> echo "${path##/*/}"
> long.file.name
${varname%pattern} 从后开始匹配,删除匹配的最短部分,并返回剩下的部分
> path="/home/prince/desktop/long.file.name"
> echo "${path%.*}"
> /home/prince/desktop/long.file
${varname%%pattern} 从后开始匹配,删除匹配的最长部分,并返回剩下的部分
> path="/home/prince/desktop/long.file.name"
> echo "${path%%.*}"
> /home/prince/desktop/long
${varname/pattern/string} 将varname中第一个匹配pattern的部分替换为string
${varname//pattern/string} 将varname中所有匹配pattern的部分替换为string
命令替换
反引号: echo `PWD` # /home/oliver
单引号和双引号的区别
强引用: 单引号不会转义 如:echo '$PWD' 结果为 $PWD
弱引用: 双引号会转义 如 echo "$PWD" 结果为 /home/oliver
函数
shell执行命令的顺序
1. 别名
2. 关键字,如if,for
3. 函数
4. 内置命令
5. 外部命令
函数定义
[function] functionName ()
{
shell command
}
向函数传递位置参数,位置参数是函数私有的,对位置参数的任何操作不会影响函数外部使用的任何参数
local定义的变量是函数内部变量,在函数退出时消失,不会影响函数外部同名变量
条件控制和流程控制
if/else语句
if condition
then
statement
[elif condition
then
statement]
[else
statemnt]
fi
逻辑操作
NOT
AND
if condition1 && condition2
then
statements
fi
OR
case语句
case expression1 in
pattern1)
statements;
pattern2)
statements;
pattern3 | pattern4)
statements;
...
esac
任何pattern之间都可以由 管道字符 | 分割的几个模式组成。
在这种情况下。如果expression匹配其中任意一个模式,起相应的语句即被执行
循环
for循环
for fileName in 'find . -iname "*.mp3"'
do
echo "$fileName"
done
while循环
while condition
do
statementss;
done
until循环
until condition
do
statementss;
done
跳出循环
break 、continue
文件
文件类型
> 普通文件 -
> 目录 d
> 字符设备 c
> 块设备文件 b
> 套接口文件 s
> 符号链接文件 l
文件权限
所有者、用户组、其他用户
chown [OPTION]... [OWNER][:[GROUP]] FILE...
chown oliver file 改变file的属主为 oliver
chgrp oligroup file 改变file的属组为 oligroup
chmod 755 file
特殊的目录
/ 根目录 : 一般比较小,一般不含任何文件,可能存放系统引导映像,通常叫/vmlinuz,所有其他文件在根文件系统的子目录中
/etc 存放网络等配置文件
/dev 存放所有设备的设备文件
/usr 一般很大,一般程序文件都安装在这
/var 包括系统一般运行时要改变的数据
/proc 虚拟目录,可以查看到当前运行环境的各种信息(如CPU状态、内存......)
进程
创建进程
查看进程
ps
top
pstree
前后台进程切换
CTRL + Z 将当前进程挂起,当出现提示符后,键入 bg ,将刚挂起的进程转到后台运行
bg %N N是作业号,表示将指定进程带往后台,bg可以一次将多个进程带往后台
jobs 查看当前后台运行的进程
fg [job_spec] 将指定进程转到前台运行
常用命令
read
从命令行中读取一个值然后赋值给指定的变量。
> read website
> hello world
> echo "website的值是 $website"
> website的值是 hello world
grep
ln
创建符号链接文件
ln -s idea.sh idea_l.sh
文本处理
sort 文本排序
sort -t: -k3 -n /etc/group
-t: 定义分隔符
-k3 3表示比较第3个字段
-n 表示按照整数值排序
uniq 文本去重
uniq [-c|-d|-u] [InFile|OutFile]
1. 常与sort组合使用
2. 例子:
sort pra.txt|uniq 去重后展示
sort pra.txt|uniq -d 只显示重复的记录
sort pra.txt|uniq -u 只显示不重复的记录
wc
wc -l 统计文本行数
wc -c 统计字符数
wc -w 统计单词数
cut
cut -d ':' -f 1,7 /etc/passwd|grep bash
-d ':' 指定分隔符
-f 1,7 表示cut截取每行的第一列字段和第七列字段
join
join命令可以连接不同的文件,使得相同key值的记录信息连到一起。
join aa.txt bb.txt
文本替换
tr 替换字符
tr 'a-z' 'A-Z' < aa.txt > bb.txt
从aa.txt中读入数据,将所有的小写字母替换为大写字母后,标准输出重定向到 bb.txt
tr -d '\0' <aa.txt >bb.txt
从aa.txt读入的数据删除所有空白字符后输出到bb.txt
sed
echo $PATH | sed 's/:/\n/g' 将PATH变量的值按:换行
touch
更新文件的访问和修改时间
find
find /etc -iname "*.xml" -exec cp {} /tmp/work/ \;
递归检索/etc下的xml文件,然后将这些文件赋值到/tmp/work下。
-exec command {} \ : 对匹配的文件执行该参数所给的shell命令
-exec 选项处理匹配到的文件
find命令是一次性将所有匹配的文件传递给exec执行,故可能出现 参数列较长 或 参数列溢出 的问题。
(这时可以通过 find 和 xargs 组合使用,xargs是分批取得参数的)
find /work -mtime 2 查找/work目录下最近2天修改过的文件
find /work -mmin x 最近x分钟修改过的文件
类似的有 -amin/atime 最近访问 -cmin/-ctime 最近创建
diff
比较文件间的不同
挂载和卸载
mount /dev/sda6 /mnt/sda6 将/dev/sda6挂载到/mnt/sda6上
unmount /mnt/sda6 卸载/mnt/sda6
流编辑 sed
sed -e '1,5d' /tmp/passwd.bak 行地址,删除第一行
sed -n -e '1,5p' /tmp/passwd.bak 行范围地址,打印1到5行
sed -n -e '/^#/p' /tmp/passwd.bak regexp地址,打印所有以#开头的注释行
sed -e 's/world/java/g' /tmp/passwd.bak 将/tmp/passwd.bak中的world替换为java
组合命令
使用分号分割命令 sed -n -e '=;p' /tmp/passwd.bak
解析:=告诉sed打印行号,p告诉sed打印该行
使用文本文件执行sed命令
> cat handle.sed
1d
s:sbin/nologin:bin/zsh:g
p
> sed -n -f handle.sed /tmp/passwd.bak
例子中将sed命令写入到handle.sed文件中。执行时通过-f参数引用命令
将多条命令应用到一个地址范围
sed -n -e '1,5{s:sbin/nologin:bin/zsh:g;s/:/|/g;p}' /tmp/passwd.bak
解析:
将/sbin/nologin替换成/bin/zsh
将 : 分隔符替换成|分隔符
打印该行
文本处理 awk
awk具有计算机语言特有的性质,如变量、判断、循环、数组
awk -F":" '{print "USER " $1 "\tSHELL " $3}' /tmp/passwd.bak
-F 设置awk的初始化变量FS,字段分隔符,默认是空白字符
模式匹配
awk '/^$/'{print "this is an empty line."} /tmp/passwd.bak
正则表达式/^$/匹配文件中的空行,当匹配上时,执行awk的print语句。
计算机语言性质
变量:
用户自定义变量、
内建变量
awk变量可由字母数字下划线组成,以字母下划线开头
数组
赋值
arr[baidu] = "baidu.com"
arr[yahoo] = "yahoo.com"
删除
delete arr[baidu] 删除arr数组指定元素
delete arr 删除arr数组
判断
if语句 、if/else语句、 if/else if/else 语句
awk '{if($1 < $2) {count++; print $2 " too high"} else {count--; print "ok"}}' num.txt
如果第一个域小于第二个域,count加1,并打印 $2 too high,否则count减1,并打印 ok
循环
while
i = 4
while ( i>=1 ){
print $i
i--
}
do/while
count=1
do{
print $count
} while ( count != 1 )
for
for( x = 1; x <= 4; x++ ){
print "iteration ",x
}
算数运算 awk 'BEGIN{print "3+2 = " 3+2}'
多行记录处理
多文件联合处理
任务调度
最新的版本 cron.allow和cron.deny在 /etc目录下
cron守护进程
cron守护进程可管理crontab、at命令的自动调度。
- 检查新的crontab文件
- 阅读文件中列出的执行时间
- 在适当时间提交执行命令
- 侦听来自crontab命令的有关更新的crontab文件的通知
调度重复性系统任务 crontab
显示crontab文件
crontab -l [username]
crontab文件项的语法
例子:
每月第1和15天的下午4点,在用户控制台窗口中显示提醒
0 16 1,15 * * echo hello > /dev/console
为username添加crontab文件
crontab -e [username]
删除crontab文件
crontab -r [username]
控制对crontab命令的访问
cron.allow、cron.deny 编辑和创建需要超级用户权限
cron.allow的优先级大于cron.deny
允许oliver用户访问crontab 例子:echo oliver >> /etc/cron.allow
拒绝oliver用户访问crontab 例子:echo oliver >> /etc/cron.deny
控制对at命令的访问
/etc/at.deny
调用单次系统任务 at
创建at作业
at [-m] time [date]
-m 在作业完成后发送邮件
date 指定月份的前3个或更多字母、一周中的某日或关键字today或tomorrow
例子:
在下午7:30分删除备份文件,并在作业完成后发送邮件
>> at -m 1930
at> rm /home/oliver/log/*.bak
at> rm /home/oliver/log2/*.bak
按Ctrl + D 退出at程序并保存at作业
查看队列中的at作业
atq
显示at作业
at -l [job-id]
删除at作业
at -r [job-id]
线程
进程上下文切换开销大
上下文切换的主要任务是保存老进程的CPU操作状态,并加载新进程的保存状态,用新进程的内存影响替换进程的内存映像。线程允许进程在几个正在运行的任务之间进行切换而不必执行前面提到的完成上下文。
系统监控
系统内存信息
cat /proc/meminfo
硬盘监控,查看/dev/sdb盘使用的百分比
df|grep "/dev/sdb"|awk '{print $5}'|sed 's/%//g'
查看CPU硬件状况
cat /proc/cpuinfo
查看CPU运行状态
cat /proc/stat
获取最忙碌的进程信息
ps -aux|sort -nk 3r|head -4
sort的n表示按数值排序
k 表示按列排序
3 表示第3列
r 表示倒序