1、创建脚本
1)如何创建新的shell脚本
vim *.sh ##一般以.sh为后缀
#!bin/bash ##脚本使用的解释器,通常用幻数“#!”指定
#AUTHOR ##脚本作者
#DATE ##脚本创作时间
#MAIL ##脚本作者联系方式
#VERSION ##脚本的版本
2)三种调用shell方式
<1>sh test.sh ##sh调用, 用sh作为解释环境
<2>source test.sh ##用当前的shell作为解释环境
<3>chmod +x /mnt/test.sh ##给操作权限,脚本需要有操作的权限
/mnt/test.sh ##用shell中指定的幻数作为解释环境
ctrl+z打入后台,用”ps f“查看三种调用方式的解释环境
3)vim如何支持
写shell时,自动添加基本信息
vim /etc/vimrc
在最后写:
autocmd BufNewFile *.sh,*.script exec ":call WESTOS()" ##新建以.sh和.sceipt结尾的文件,自动执行WESTOS()中的命令,两者之间用逗号“,”隔开,如果是对多个文件要执行,用“,”隔开
"map <F5> ms:call WESTOS()<cr>'s ##调用命令影射到F5,手动,注释用 ”
function WESTOS() ##WESTOS即给命令命的名
call append(0,"################################") ##一个tab键=8个空格
call append(1,"# Author: #")
call append(2,"# Create_Date: ".strftime("%Y-%m_%d")." #")
call append(3,"# Version: #")
call append(4,"################################")
endfunction
4)脚本的调试
sh -x *.sh ##适用于所有shell脚本
执行ip_show.sh ,显示当前主机ip地址
#!/bin/bash
ifconfig eth0 | grep "inet "|cut -d " " -f 10
2.shell中的常用命令
1)diff 命令时用俩比较两个文件或者目录的不同
diff file file1
diff dir dir1
diff中常用的参数
-b 或 --ignore-space-change ##不检查空格字符的不同
-B 或--ignore-blank-lines ##不检测空白行
-c ##显示全部内容,并标出不同之处
-i 或--ignore-case ##不检查大小写的不同
-p ##若比较的文件为c语言的程序码文件时,显示差异所在的函数名称
-q 或--brief ##仅显示有无差异,不显示详细的信息
-r 或--recursive ##比较子目录中的文件
-u ##以合并的方式来显示文件内容中的不同
diff在比较文件过程中结果读取方式
[num1,num2][a|c|d][num3,num4]
num1,num2表示在第一个文件中的行数
a表示添加-----add
c表示更改-----change
d表示删除-----delete
例:
root@shell mnt]# diff text text1
3c3
< 123 ##<表示第一个文件中的内容
--- ##分割线
> 1233 ##>表示第二个文件中的内容
表示第一个文件的第三行和第二个文件的第三行不同,
补丁:
diff -u file file1 > file.path ##file.path 就是补丁
yum install patch -y
patch file file.path ##添加补丁,不保留源文件
或patch -b file file.path ##-b 保留原文件,原文件为file.orig,即*.orig
2)cut
cut 命令多用于字符截取
cut -d ##指定分隔符
cut -f 1,7|1-7 ##指定截取的列,1,7表示第1列和第7列,1-7表示截取1到7列
cut -c 1,4|1-4 ##指定截取的字符位置
3)sort &uniq
多用于字符排序
sort -n ##纯数字排序
sort -r ##倒序
sort -u ##去掉重复数字
sort -o ##输出到指定文件中
sort -t ##指定分隔符
sort -k ##指定要排序的列
uniq
对重复字符做相应的处理
uniq -u ##显示唯一的行
uniq -d ##显示重复的行
uniq -c ##每行显示一次并统计重复次数
一般sort和uniq组合时用,如
sort -rn westos | uniq -u
4)&&和||
||表示条件不成立
&&表示不成立
ping -c1 -w1 172.25.254.333 && echo yes ||echo no ##成立输出yes,不成功输出no,-c1 -w1 表示刷新一次,等待时间为一秒
5)test
test命令和[]等同
test "$A" ="$B" 等同于 [ "$A" = "$B" ]
[ "$A" = "$B" ] ##等于
[ "$A" != "$B" ] ##不等于
[ "$A" -eq "$B" ] ##等于
[ "$A" -ne "$B" ] ##不等于
[ "$A" -le "$B" ] ##小于等于
[ "$A" -lt "$B" ] ##小于
[ "$A" -ge "$B" ] ##大于等于
[ "$A" -gt "$B" ] ##大于
-a ##且
-o ##或
-z ##表示为空
-nt 表示比较两个文件哪个时间新
-ef 表示这两个文件是不是同一个
-ot 表示哪个文件时间老
[ -z "$1" ] ##是否是空
[ -e "$1" ] ##是否存在
[ -f "$1" ] ##纯文本
[ -L "$1" ] ##链接
[ -b "$1" ] ##块设备
[ -c "$1" ] ##字符设备
[ -d "$1" ] ##目录
[ -S "$1" ] ##套接字
tr 'a-z' 'A-Z' < westos ##替换大小写
编写shell 执行sh check_file.sh 时,检测是否有输入,以及输入的文件或者目录的类型
vim check_file.sh
#!/bin/bash
[ -z "$1" ]&& {
echo "Please show me a file after script !!!"
exit
}
[ -e $1 ] || {
echo "$1 is not exist"
exit
}
[ -L "$1" ]&& {
echo "$1 is a link file"
exit
}
[ -f "$1" ]&& {
echo "This is a file"
exit
}
[ -c "$1" ]&& {
echo "$1 zifushebei"
exit
}
[ -d "$1" ]&& {
echo "$1 is a diretcort"
exit
}
[ -b "$1" ]&& {
echo "$1 is a block"
exit
}
3.Shell中的文本处理正则表达式
1)grep文本过滤命令
全面搜索研究正则表达式并显示出来
grep命令时一种强大的文本搜索工具,根据用户指定模式,对目标文本进行匹配检查,打印匹配得到的行,由正则表达式或者字符及基本文本字符所编写的过滤条件
grep的格式
grep root passwd ##过滤含有root的
grep -i root passwd ##忽略大小写
grep -i "root\>" passwd ##root后无字符
grep -i "\<root\>" passwd ##root前后都无字符
grep -i "^root\>" passwd ##以root开头且root后无字符
grep -i "\<root$" passwd ##以root结尾且root前无字符
grep -iE "^root\>|\<root$" passwd ##以root开头且root后无字符的或以root结尾且root前无字符。E表示扩展正则表达式
grep -iE "^root\>|\<root$" passwd -v ##反向过滤
grep -iE "^root\>|\<root$" passwd -v |grep root ##反向过滤并过滤含有root的
grep -iE "^root\>|\<root$" passwd -v |grep "\<root\>" ##反向过滤并过滤含有root且root前后都无字符的
grep r... /etc/passwd ##过滤含有“r...”,含有r且r后有三个字符
grep r..t /etc/passwd
grep x text ##含有x
grep -E "x*" text ##x出现任意次
grep -E "x?" text ##x出现0-1次
grep -E "x+" text ##x出现1-n次
grep -E "x{3}" text ##x出现3次
grep -E "x{3}y" text ##x出现3次y出现1次
grep -E "x{1,3}y" text ##x出现1-3次,且含有y
grep -E "x{1,}y" text ##x出现1-任意次,有y
grep -E "x{,3}y" text ##x出现0-3次,有y
测试 cp /etc/passwd .
对passwd文件修改
vim text
对文件修改,便于看到命令效果
2)sed 行编辑器stream editor
用来操作纯ASCII码的文本,处理时,把当前处理的行存储在临时缓冲区中,成为“模式空间(pattern space)”,可以指定仅仅处理哪些行
sed符合模式的处理,不符合条件的不予处理,处理完后把缓冲区的内容送到屏幕,接着处理下一行,这样不断重复,直到文件末尾。
sed对字符的处理
p ##显示
d ##删除
a ##添加
c ##替换
w ##写入
i ##插入
p模式操作
cat -b fstab ##忽略空行
cat -n fstab
sed -n /^#/p fstab ##显示以 # 开头的行,不加-n会重复显示,加-n就会只显示操作过的内容
sed -n '/^#/!'p fstab ##显示不以 # 开头的行
cat -n fstab | sed -n '2,6p' ##显示2-6行
cat -n fstab | sed -n '6p' ##显示第6行
cat -n fstab | sed -n -e '6p;2p' ##显示第二行和第六行
cat -n fstab | sed -n -e '2p' -e '6p' ##显示第二行和第六行
cat -n fstab | sed -n '2,6!p' ##显示除了2-6行外的其他行
测试: [root@shell mnt]# cp /etc/fstab .
[root@shell mnt]# cat -b fstab
输命令看效果
d模式的操作
sed '/^#/d' fstab ##删除以#开头的行
sed -e '/^#/d' -e '/^$/d' fstab ##删除以#开头的行,删除空行
cat -n fstab | sed '4,6d' ##删除4-6行
cat -n fstab | sed '4d' ##删除第4行
cat -n fstab | sed -e '4d;6d' ##删除第4行和第6行
sed '/UUID/!d' fstab ##删除除了以UUID开头的行
测试: 同p模式
a模式
sed '/^UUID/ahello' fstab ##在以UUID开头的行后一行添加hello
sed '/^UUID/ahello\nwestos' fstab ##在以UUID开头的行后一行添加hello行和westos行
i模式
sed '/^UUID/ihello' fstab ##在UUID行前一行添加
c模式
sed '/^#/chello' fstab ##用hello替换以#开头的行
w模式
sed '/^#/w /mnt/textfile' fstab ##把fstab中以#开头的行全部定向到/mnt/textfile中
测试:cat /mnt/textfile
sed '6r /mnt/hello' /mnt/fstab ##把/mnt/hello中的内容添加到/mnt/fstab的第6行以后
测试:在/mnt/hello中写入内容,运行命令查看效果
sed 'r /mnt/hello' /mnt/fstab ##加到第一行
其他用法
sed -n '/^UUID/=' fstab ##显示以UUID开头的行的行号
sed -ne '/^UUID/=;/^UUID/p' fstab ##显示以UUID开头的行的行号,并显示以UUID开头的行
sed -ne '/^UUID/=;/^UUID/p' fstab |sed 'N;s/\n/ /g' ##N表示提前提取下一行的内容 ,显示以UUID开头的行的行号,并显示以UUID开头的行,并且行号在显示行内容之前
vim rule
/^UUID/=
sed -nf rule fstab ##使用rule中写的规则
给每一行加行号:
sed '=' -i passwd
sed 'N;s/\n/ /g' passwd -i
替换
sed 's/nologin/bash/g' passwd ##替换全文的nologin为bash
sed '1,5s/nologin/bash/g' passwd ##替换1-5行的nologin为bash
sed '5s/nologin/bash/g' passwd ##替换第5行的nologin为bash
sed -e '5s/nologin/bash/g;2s/nologin/bash/g' passwd ##替换第2和第5行的nologin为bash
sed '/daemon/,/mail/s/nologin/bash/g' passwd ##替换daemon和mail之间的nologin为bash
sed -e 's/:/###/g;s/nologin/westos/g' passwd ##替换全文的:为###,并且替换全文的nologin为bash
sed 's@/@ @g' passwd ##替换全文的 / 为空格,@和/是相同意思
sed 'G' passwd ##每一行后加一空行
sed '$!G' passwd ##每一行后加一空行,最后一行不加
3)awk的基本用法
awk -F : 'BEGIN{print "hello"}' passwd ##开始打印hello,-F指定分隔符,默认分隔符是空格
awk -F : 'BEGIN{print "hello"}{print $1}END{print "end"}' passwd ##开始打印hello,结尾打印end,$1第一个字符
awk -F : '{print FILENAME}' passwd ##逐行打印文件名
awk -F : '{print NR}' passwd ##第NR数
awk -F : '{print NF}' passwd ##有几列
awk -F : 'BEGIN{print "NAME"}' ##开始打印NAME
awk -F : '{print $1}' passwd ##打印分隔符第一列字符
awk -F : '/bash$/{print $1}' passwd ##打印以bash结尾的行的第一列字符 ---##此命令筛选出能够登陆系统的用户
awk 'BEGIN{N=0}/bash$/{N++}END{print N}' passwd ##BEGIN表示以什么开始,END表示以什么结束----##查询能够登陆系统的用户的数
awk 'BEGIN{N=100;print N+50}' ##加法
awk '/[a-d]/{print}' passwd ##包含a-d字符的行
awk '/^[a-d]/{print}' passwd ##以a-d开头行
awk '!/^[a-d]/{print}' passwd ##不以a-d开头行
awk '/^[^a-d]/{print}' passwd ##不以a-d开头行
awk '/^a|bash$/{print}' passwd ##以a开头或者以bash结尾行
awk '/!^a|bash$/{print}' passwd ##不以a开头,以bash结尾的行
awk '!/^a|bash$/{print}' passwd ##不以a开头,不以bash结尾的行
awk -F : '$6~/bin$/' passwd ##第6列以bin结尾的行
awk -F : '$6!~/bin$/' passwd ##第6列不以bin结尾的行
awk -F : '$6!~/^\/home/&&/bash$/{print $1}' /etc/passwd ##显示根目录不在/home下的用户
ifconfig eth0 | awk '/inet\>/{print $2}' ##显示本机ip
4.shell中的变量
``是通用的$()不通用
1)shell当中的变量的种类
环境级变量----只在当前shell生效----shell关闭即失效
用户级变量----只对当前用户生效----写在用户骨文件中
系统级变量----对所有用户生效----被写在etc/profile或者etc/profile.d下—写在系统配置文件中
2)shell脚本中变量的定义方法
1·环境级变量
export a=1
2·用户级变量
vim ~/.bash_profile
export a=1
source ~/.bash_profile
3·系统级变量
vim /etc/profile
export a=1
source /etc/profile
或
cd /etc/profile.d/
vim westos.sh
#!/bin/bash
export a=1
source /etc/profile.d/westos.sh
测试:echo $a
3)字符的转译及变量的声明
\ ##转译单个字符
"" ##若引用,批量转译""中出现的字符
'' ##强引用,批量转译''中出现的字符
'' 与 "" ##双引号""不能转译 "\", "`", "!", "$"
${} ##变量声明
如:a=1
echo $ab
echo ${a}b
4)变量值传递
$1 ##脚本后第1串字符
$2 ##脚本后第2串字符
$3 ##脚本后第3串字符
$# ##脚本后所跟字符串的个数
$* ##脚本后跟的所有字符串,模式为“123”
$@ ##脚本后跟的所有字符串,模式为"1" "2" "3"
5)read 命令
read命令 -p(提示语句) -n(字符个数) -t(等待时间) -s(不回显)
read -p "Please input a world :" -s WORLD
echo ""
echo $WORLD
6)退出值
echo $? ##显示退出值
0表示成功
非0表示失败
2表示用法不当
127表示命令找不到
126表示不可执行
linux中系统中命令别名的设定
alias xie='vim' ##当前shell可用
vim ~/.bashrc ##当前用户可用
alias xie='vim'
source ~/.bashrc
vim /etc/profile.d/ ##所有用户都可以用
vim /etc/profile.d/westos.sh
source /etc/profile.d/westos.sh
5.shell中的常用语句
1)for语句
for Num in 1 5 7
do
echo $Num
sleep 1 ##休眠时间为1s,即间隔一秒再次执行
done
for Num in {1..10}
for Num in {10..1}
for Num in `seq 1 2 10` ##步长为2
例1:编写脚本 text.sh ,从userfile中取出要建立用户名建立用户
#!/bin/bash
[ -z "$1" ] && { ##检测是否为空
echo "please input userfile!!"
exit 1
}
[ ! -e "$1" ] && { ##检测是否存在
echo "ERROR : $1 is not exist"
exit 2
}
for NAME in `cat $1`
do
id $NAME &> /dev/null
[ "$?" -eq "0" ] && {
echo "$NAME is exist!!"
}||{
useradd $NAME &>/dev/null
echo "$NAME is created!"
}
done
例2:10秒倒计时
#!/bin/bash
TTY=`ps $$| grep $$ |awk '{print $2}'`
for Num in {10..1}
do
clear
echo -ne $Num > /dev/$TTY
echo -ne '\r \r' ##不换行
sleep 1 ##间隔1s
done
2)while语句 ----只判定一次
当条件为真
while true
do
done
update ##监测系统负载
echo$$ ##显示当前id
例子:显示时间
#!/bin/bash
TTY=`ps $$| grep $$ |awk '{print $2}'`
while true
do
clear ##清屏
echo -ne `uptime` > /dev/$TTY
echo -ne '\r \r' ##不换行
sleep 1
done
3)if语句 可以在一直判定,从上到下依次判定
if
then
elif
then
elif
then
else ##可以不写
fi
例:运行 userfile.sh,检测文件类型
#!/bin/bash
if [ -z "$1" ]
then
echo "Error!!Please input a filename follow script!"
elif [ ! -e "$1" ]
then
echo "Error!! filename is not exist!"
elif [ -L "$1" ]
then
echo "$1 is a link file"
elif [ -f "$1" ]
then
echo "$1 is a file"
elif [ -d "$1" ]
then
echo "$1 is a directory"
elif [ -b "$1" ]
then
echo "$1 is a block"
elif [ -c "$1" ]
then
echo "$1 is a char"
fi
4)case语句 --选择性操作时用,相比if更快
例1: 写echo.sh,当输入A时,输出B,当输入B,输出A,其他输入,输出error
case $1 in
A)
echo B
;;
B)
echoA
;;
*)
echo error
esac
例2,建立 virt_ctrl.sh ,使sh virt_ctrl.sh delete|start|stop|create desktop
#!/bin/bash
case $1 in
start)
virsh start $2
virt-viewer
;;
stop)
virsh destory $2
;;
delete)
virsh undefine $2
rm -fr /var/lib/libvirt/images/$2.qcow2
;;
create)
virt-install \
--cdrom /home/kiosk/Desktop/rhel-server-7.3-x86_64-dvd.iso \
--memory 1000 \
--vcpus 1 \
--disk /var/lib/libvirt/images/$1.qcow2,size=8,bus=virtio \
--network bridge=br0,model=virtio \
--name $1 >/dev/null &
;;
*)
echo error
esac
5)export
expect ----是自动应答命令,用于交互式命令的自动执行
spawn ----是expect中的监控程序,其运行后会监控命令提出的交互问题
send ----发送问题答案给交互命令
“\r” ----表示回车
exp_continue ----表示当问题不存在时继续回答下面的问题
expect eof ----表示问题回答完毕退出expect环境
interact ----表示问题回答完毕留在交互界面
set NAME[ lindex $argv n ] ##定义变量
yum install expect -y ##安装expect服务
例1: sh auto_ssh 172.25.254.103 redhat ,可以登录到103主机
#!/bin/bash
/usr/bin/expect <<EOF
spawn ssh $1 ##执行的命令
set timeout 3 ##等待时间为3s
expect {
"connecting" { send "yes\r" ; exp_continue }
"password" { send "$2\r" ; exp_continue }
interact ##表示登录后停留在当前环境 ,eof表示登录后退出
}
EOF
例2:检测1-10主机是否开启,并显示主机名
#!/bin/bash
Auto_ssh()
{
/usr/bin/expect << EOF
set timeout 10
spawn ssh root@172.25.254.$1 $2 ##此处$1 $2 $3 分别指 $NUM hostname redhat expect {
"yes/no" { send "yes\r";exp_continue}
"password" { send "$3\r"}
}
expect eof
EOF
}
for NUM in {1..10}
do
ping -c1 -w1 172.25.254.$NUM &> /dev/null
if
[ "$?" -eq "0" ]
then
Auto_ssh $NUM hostname redhat |grep password: -A1 | grep password -v ##-A1表示关键字和关键字后一个,
fi
done
6)脚本中的语句控制器
exit ##脚本退出,退出值为n
break ##退出当前循环
continue ##提前结束循环内部的命令,但不终止循环
测试
#!/bin/bash
for i in {1..10}
do
if
[ "$i" = "5" ]
then
echo lucky num
continue|break|exit
fi
echo $i
done
echo westos