如何编写Shell文件

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	17|1-7			##指定截取的列,17表示第1列和第7,1-7表示截取17列
cut -c	14|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	
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值