第7天——shell基础
一、常用shell命令
二、shell脚本
1、执行shell脚本
2、test命令
3、判断符号[]
4、shell script参数
5、条件判断if..else...fi;case
6、函数
7、Script检查
8、循环结构
三、课件分发任务
四、定时任务
一、常用shell命令
1、管道命令:|
命令1 | 命令2 命令1的输入作为命令2的输入
2、grep命令
3、find命令
选项参数:-type, -name, -size, -perm....
4、sed命令
sed (stream editor)是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
命令格式:sed [option] "[action]" [filename]
动作说明:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!
预备工作:创建demo.txt
当然也可用vim demo.txt的方式来创建。
我们修改一下demo.txt的内容:
(1)替换操作(substitute)
任务:将所有行的第一个hello替换成HELLO。
注意:输出内容是替换了的,但是原文件并没有改变。
任务:将第2行到第3行的第2个hello替换成HELLO。
任务:将第2行的hello全部替换成HELLO。
任务:将全部的hello替换成HELLO,之后生成新文件demo1.txt。
任务:将全部的hello替换成hi,要求修改原文件。
(2)插入操作
任务:在第2行之前插入一行新内容“I love Linux”
任务:在第2行之后插入一行新内容“Linux is interesting, and I love it.”
i: insert 在当前行之前插入
a: append 在当前行之后插入
(3)删除操作(d: delete)
任务:删除第2行
任务:删除第2行到第3行
任务:删除包含scala字符串的匹配行
5、tail命令
(1)显示末尾若干行
tail -n filename
任务:显示install.log最后四行内容
(2)显示文件修改行
tail -F filename 显示文件修改的内容。
预备工作:修改 install.log,在末尾增加两行内容。
存在退出,查看一下最后两行:
在实际应用中,日志文件在不断修改,如何显示修改的内容呢?只需要参数-F。
思考题:如何给出install.log文件的行数?
方法一、用vim编辑install.log文件,在命令模式下按G键定位到最后一行
方法二、用vim编辑install.log文件,在末行模式下设置行号:set nu
方法三、利用cat -n命令
方法四、利用wc -l (lines)统计文件行数(-c 统计字符数、-w 统计单词数)
我们不妨看看-c和-w的结果。
6、sort命令
预备工作:创建ips.txt文件
(1)按行排序(字典排序法)
(2)按第4节排序
7、cut命令
(1)命令格式:cut [-option] filename
(2)选项option
-b (byte)字节
-c (character)字符
-d (delimiter)按指定分隔符分割列
-f (fetch)提取第几列
任务:提取ips.txt文件每行第7个字符
任务:提取ips.txt文件第4节的内容
8、history命令
(1)查看历史命令:history
(2)清除历史命令:history -c # c: clear
此命令发布之后,按上方向键就不能调出历史命令了。
二、shell脚本
注意:脚本文件第一行必须是“
#/bin/bash
”,指定命令解释器bash
1、执行shell脚本
假设程序文件名是:/home/shell.sh
执行脚本有以下三种方式:
(1)直接执行
(shell.sh文件必须具备可读与可执行(rx) 的权限)
修改shell.sh的权限:
绝对路径:运行/home/shell.sh 来执行指令
相对路径:cd到/home/ ,使用./shell.sh执行
(2)source 执行
:source shell.sh
说明,此时可以删掉shell.sh脚本第一行的注释#/bin/bash。
(3)bash执行或sh执行
:bash shell.sh 或 sh shell.sh
任务1、显示当前用户的主目录
1)编写脚本 vim shell01.sh
2)设置权限:chmod u+x shell01.sh
3)执行脚本:./shell01.sh
要使得切换到另一个用户,比如howard,也能执行该脚本,那么应该修改权限:chmod o+x shell01.sh(要求其他人也有执行权限)
切换到howard用户,执行脚本:
任务2、编程实现两个数相乘
1)编写脚本:vim multiplication.sh
#!/bin/bash
read -p "a=" a
read -p "b=" b
product=
$((a*b))
echo "$a * $b = $product"
2)设置权限:chmod u+x multiplication.sh
3)执行脚本:./multiplication.sh
输入两个实数,结果会报错:
问题:怎么才能计算两个实数的乘积呢?
1)编写脚本:vim multiplication02.sh
2)设置权限:chmod u+x multiplication02.sh
3)执行脚本:./multiplication02.sh
课堂练习
:编写脚本operation.sh,可以实现加减乘除运算功能。输入两个整数a,b和一个运算符op(+、-、*、/)。
1)编写脚本:vim operation.sh
说明:$((a $op b))也可以写成$((a${op}b)),用花括号将op括起来,那么与a和b之间就可以不用空格了。
2)修改权限:chmod u+x operation.sh
3)执行脚本:./operation.sh
2、test命令
(1)判断文件类型
-e (exist)该文件是否存在? !!!
-f (file)该文件是否存在且为文件(file)?!!!
-d (directory)该文件名是否存在且为目录(directory)?!!!
-b (block device)该文件是否存在且为一个块设备?
-c (character device)该文件是否存在且为一个字符设备?
-S (Socket)该文件是否存在且为一个Socket文件?
-p (pipe)该文件是否存在且为一个FIFO(pipe)文件?
-L (link)该文件是否存在且为一个链接文件?
(2)判断文件权限
-r (readable)检查该文件是否存在且具有可读的权限?
-w (writable)检查该文件是否存在且具有可写的权限?
-x(executable)检查该文件是否存在且具有可执行的权限?
-s 检查该文件是否存在且为非空文件?
-u 检查该文件名是否存在且具有SUID的属性?
-g 检查该文件名是否存在且具有SGID的属性?
(3)判断字符串
test -z string 空
test -n string 非空
test str1=str2
test str1!=str2
任务:编写shell脚本,实现如下功能
•先给予提示:please input a filename:
•是否输入了文件名,如果为空提示:you must input a filename,并结束脚本。
•判断文件是否存在?不存在则结束脚本。
•判断文件类型以及统计文件都有哪些权限。
•输出文件类型和文件所有的权限。
1)编写脚本:vim shell02.sh
#!/bin/bash
# program: enter a filename and return its type and permissions
echo "Enter a filename and check whether the file exists. If the file exists, return its type and permissions."
read -p "Enter a filename: " filename
test -z $filename && echo "filename cannot be null" && exit 1
test ! -e $filename && echo "$filename does not exist" && exit 2
test -f $filename && filetype="file"
test -d $filename && filetype="directory"
test -r $filename && perms="readable"
test -w $filename && perms="$perms writable"
test -x $filename && perms="$perms executable"
echo "$filename is a $filetype"
echo "permissions: $perms"
2)修改权限:chmod u+x shell02.sh
3)执行脚本:./shell02.sh
(4)两个文件之间的比较
-nt 判断file1 是否比file2 新 (nt: newer than)
-ot 判断file1 是否比file2 旧 (ot: older than)
-ef 判断两个文件是否为同一个文件(ef: equal file)
任务:判断文件test1.txt与test2.txt的新旧与异同。
1)编辑脚本:vim test.sh
1 #!/bin/bash
2
3 test test1.txt -nt test2.txt && echo test1.txt is newer than test2.txt
4 test test1.txt -ot test2.txt && echo test1.txt is older than test2.txt
5
6 test test1.txt -ef test2.txt && echo test1.txt and test2.txt are the same file
7 test ! test1.txt -ef test2.txt && echo test1.txt and test2.txt are different files
2)设置权限:chmod u+x test.sh
3)运行脚本:./test.sh
3、判断符号[] (跟test基本相同)
(1)[ XXXX ] (
注意[ ]和脚本XXXX之间保留空格
)
(2)==和!=用于比较字符串;(==, != 两边必须有空格)
(3)整数比较只能使用-eq,-gt, ge, lt, le这种形式(-eq: equal, -gt: greater than, -ge: greater than or equal to, -lt: less than, le: less than or equal to)
(4)[ ]中的逻辑与和逻辑或使用-a 和-o 表示(-a: and, -o: or)
(5)&&、||、<和> 操作符如果出现在[ ]结构中的话,会报错。
任务:根据用户输入执行不同操作。
1)编辑脚本 vim shell03.sh
2)设置权限 chmod u+x shell03.sh
3)执行脚本 ./shell03.sh
4、shell script参数
(1)shell script默认参数
ls -l,其中-l就是shell脚本参数。
(2)如何使用用户自定义脚本的参数
/path/scriptname arg1 arg2 arg3 arg4 # 参数之间用空格隔开
$0 $1 $2 $3 $4
$n:n=0、1、2、3、……
$#:表示参数个数,就上面案例而言,其值为4
$@:表示"$1" "$2" "$3" "$4" 每个变量是独立的,用双引号括起来
$*:表示"$1 $2 $3 $4"
任务:要求脚本输入4个参数,如果参数不够,提示用户;如果输入了4个参数,显示4个参数的值。
1)编辑脚本:vim shell04.sh
2)设置权限:chmod u+x shell04.sh
3)运行脚本:./shell04.sh
(3)参数偏移
shift
shift可以造成参数变量号码偏移。
下面,通过案例来演示shift的用法。
1)编辑脚本:vim shell05.sh
2)设置权限:chmod u+x shell05.sh
3)执行脚本:./shell05.sh mike howard alice green smith
思考题:
1)脚本参数有5个,执行shift 100,会不会报错?
不会报错,结果没有造成偏移效果。
2)shift的参数可不可以是负整数,表明向前偏移?
运行脚本会报错:
5、条件判断
(1)单分支结构
if [ 条件 ]; then
语句组
fi
(2)双分支结构
if [ 条件 ]; then
语句组1
else
语句组2
fi
例1、比较两个整数大小。
1)编辑脚本:vim if01.sh
#!/bin/bash
a=12
b=13
if [ $a -gt $b ]; then
echo "$a > $b"
else
echo "$a <= $b"
fi
2)设置权限:chmod u+x if01.sh
3)执行脚本:./if01.sh
例2、比较传入的两个参数的大小
1)编辑脚本:vim if02.sh
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Two numbers are required."
exit 1
fi
if [ $1 -gt $2 ]; then
echo "$1 > $2"
else
echo "$1 <= $2"
fi
2)设置权限:chmod u+x if02.sh
3)执行脚本
例3、嵌套实现多分支结构
1)编辑脚本:vim if03.sh
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Two numbers are required."
exit 1
fi
if [ $1 -gt $2 ]; then
echo "$1 > $2"
else
if [ $1 -eq $2 ]; then
echo "$1 == $2"
else
echo "$1 < $2"
fi
fi
2)设置权限:chmod u+x if03.sh
3)执行脚本:./if03.sh 100 200
思考题:变成实现如下功能。
如果/tmp/part1/bash下面存在if3.sh就打印if3.sh存在;如果不存在,就“创建”(注意目录是否存在以及不存在时的创建问题)。
1)编辑脚本:vim if04.sh
#!/bin/bash
path="/tmp/part1/bash"
if [ ! -e $path ]; then
mkdir -p $path
echo "$path is created."
else
echo "$path exists."
fi
filename="${path}/if3.sh"
if [ -e $filename ]; then
echo "$filename exists."
else
touch $filename
echo "$filename is touched."
fi
2)设置权限:chmod u+x if04.sh
3)执行脚本:./if05.sh
(3)case多分支结构
判断用户输入的是哪个数,1-7显示输入的数字,大于7或小于0显示please input 1-7,输出英文的星期几。
方法一:
# vim case01.sh
#!/bin/bash
read -p "input an integer [1-7]: " n
if [ $n -lt 1 -o $n -gt 7 ]; then
echo "please input 1-7"
else
case $n in 1)
echo "Monday"
;;
2)
echo "Tuesday"
;;
3)
echo "Wednesday"
;;
4)
echo "Thursday"
;;
5)
echo "Friday"
;;
6)
echo "Saturday"
;;
7)
echo "Sunday"
;;
esac
fi
方法二:
#vim case02.sh
#!/bin/bash
read -p "input an integer [1-7]: " n
case $n in 1)
echo "Monday"
;;
2)
echo "Tuesday"
;;
3)
echo "Wednesday"
;;
4)
echo "Thursday"
;;
5)
echo "Friday"
;;
[6-7])
echo "Weekend"
;;
*)
echo "input an integer between 1 and 7."
esac
6、函数
语法格式:
function func-name() {
语句组
}
任务:输入one,输出Today is Monday,输入two,输出Today is Tuesday……
1)编辑脚本:vim func01.sh
#!/bin/bash
function print() {
echo "Today is $1"
}
case $1 in "one")
print "Monday"
;;
"two")
print "Tuesday"
;;
"three")
print "Wednesday"
;;
"four")
print "Thursday"
;;
"five")
print "Friday"
;;
"six")
print "Saturday"
;;
"seven")
print "Sunday"
;;
*)
echo "you should input one/two/three/four/five/six/seven"
esac
2)设置权限:chmod u+x func01.sh
3)执行脚本
课堂练习
:编写计算圆面积的函数并调用。
圆周率3.14是实数,要考虑脚本里如何处理实数的计算。
1)编辑脚本:vim func02.sh
#!/bin/bash
function circle_area() {
s=`echo "scale=2; 3.14*$1*$1" |bc`
}
read -p "r=" r
circle_area $r
echo "s=$s"
2)设置权限:chomod u+x func02.sh
3)执行脚本
补充:如何获取函数的返回值?
函数体利用return语句返回函数值,但是只能是
整数
。
调用函数后,利用
$?
可以获取函数的返回值。
课堂练习
:编写符号函数sign(),输入正整数,返回1,输入零,返回0,输入负整数,返回-1。
1)编辑脚本:vim func03.sh
2)设置权限:chmod 765 func03.sh
3)执行脚本:./func03.sh
说明:符号字节型的-1映射到无符号字节型的255,符号字节型的-2映射到无符号字节型的254,以此类推。
7、Script检查
(1)命令格式
sh [-nvx] scripts.sh
(2)选项与参数
-n:(non-execution)不执行script,仅查询语法的问题;
-v:(verbose)在执行scripts.sh前,先将scripts.sh的内容输出到屏幕上;
-x:(executed)将使用到的scripts.sh内容显示到屏幕上,这是很有用的参数; !!!
任务1:测试func02.sh是否有语法问题。
没有任何输出,表明脚本语法没有问题。
修改func02.sh,故意犯个语法错误:
可以看出,脚本运行出错,但是sh -n却无法检查出这个错误。
再次修改func02.sh:
确实能够捕获这种类型的语法错误。
vim中永久显示行号,开启语法高亮。
步骤1
:先复制一份vim配置模板到个人目录下
cp /usr/share/vim/vimrc ~/.vimrc
注:redhat(centos) 改成 cp /
etc
/vimrc ~/.vimrc
步骤2
:
vim ~/.vimrc
进入insert模式,在最后加二行
syntax on
set nu!
保存收工。
任务2:执行func03.sh之前输出脚本内容。
任务3:执行func03.sh,显示执行语句的流程。
8、循环结构
(1)条件循环
第一种条件循环:当型循环
while [ 条件 ]; do
命令组
done
执行情况:条件为真,执行循环,直到条件为假,结束循环。
任务1、每个两秒显示系统负载监测结果。
1)编辑脚本:vim while01.sh
永真循环是个死循环。
2)设置权限:chmod u+x while01.sh
3)执行脚本:./while01.sh
怎么结束这个死循环呢?很简单,按Ctrl+C即可。
任务2、计算1+2+3+……+100
1)编辑脚本:vim sum.sh
i=1
sum=0
while [ $i -le 100 ]
do
sum=$(($sum+$i))
i=$(($i+1))
done
echo "1+2+...+100=$sum"
2)设置权限:chmod u+x sum.sh
3)执行脚本:./sum.sh
第二种条件循环:直到型循环
until [ 条件 ]; do
命令组
done
执行情况:条件为假,执行循环,直到条件为真,结束循环。
任务:计算1+2+3+……+100
1)编写脚本:vim sum02.sh
2)设置权限:chmod u+x sum02.sh
3)执行脚本:./sum02.sh
(2)计数循环
for ...
do
[语句组]
done
任务:计算1+2+……+100
1)编写脚本:vim sum03.sh
#!/bin/bash
sum=0
for i in `seq -s " " 1 1 100`
do
sum=$(($sum+$i))
done
echo "1+2+...+100=$sum"
2)设置权限:chmod u+x sum03.sh
3)执行脚本:./sum03.sh
三、课件分发任务
任务:把/usr/soft目录里的epel-release-6-8.noarch.rpm分发到其它虚拟机。
实现步骤:
假设,主虚拟机地址192.168.159.128,从虚拟机地址192.168.159.129
要完成课件从主虚拟机到从虚拟机的分发,就需要完成免密登录。
SSH远程免密登录
从服务器192.168.159.128——>服务器192.168.159.129
1、在服务器192.168.159.128上生成公钥/私钥对
ssh-keygen
2、将公钥拷贝到服务器192.168.159.129
3、免密登录
此时,退出服务器192.168.159.129
来尝试远程无密拷贝:
(1)拷贝单个文件
[root@localhost ~]#
scp /usr/soft/epel-release-6-8.noarch.rpm [email protected]:/root
切换到192.168.159.129服务器,查看是否拷贝成功。
将拷贝过来的文件删除掉。
下面我们在/tmp/part1/bash目录里创建完成课件分发的脚本。
切换到源服务器192.168.159.128。
(1)创建目标服务器的ip地址文件ips.txt
可以添加多个目标服务的IP地址。
(2)创建分发课件的脚本send.sh
(3)修改send.sh脚本的权限
(4)执行send.sh脚本
(5)验证课件是否分发成功
OK!!!
三、定时任务
•分小时日月星期命令
•100-231-311-120-6 command (取值范围,0表示周日一般一行对应一个任务)
•记住几个特殊符号的含义:
•“*”代表取值范围内的数字,“/”代表”每”,“-”代表从某个数字到某个数字,“,”分开几个离散的数字
操作步骤:
1、新增调度任务
vim /etc/crontab
2、启动crontab服务
service crond start
3、查看服务是否已经运行用
ps ax | grep crond 或service crond status
4、crontab命令
crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond命令每分钟会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。
说明:先切换到服务器192.168.159.129,删除root目录的epel-release-6-8.noarch.rpm。
过了2分钟,查看:
OK!!!