自己写的一个shell脚本,基本上涵盖了shell脚本常用的一些操作:数组,函数,文件循环读取,参数传递,awk等,在此记录。
#!/bin/bash
#变量定义
dirName=./testshelldir
tempFile=./temp.txt
#字符串和变量拼接来定义新的变量
fileName=$dirName/test0.txt
#数组定义
loginInfo=(root-123456 hahaha-123456 test-123456)
#获取执行当前脚本的用户
currentUser=`/usr/bin/id -u -n`
#使用if判断来当前用户是否有脚本执行权限,exit退出整个脚本执行
if [ "root" != "${currentUser}" ];then
echo 'only root user can excute this script!'
exit 1
fi
#################模拟登录#######################
#使用read来接收标准输入内容,并将其存储在对应的变量中,-t来限定输入等待时长,-s对键盘输入做隐藏处理
read -p "请输入登录名: " -t 10 loginName
read -p "请输入密码: " -s loginPwd
#遍历数组,awk命令以“-”为分隔符,分别取出用户名和密码
flag=0
for i in ${loginInfo[@]}
do
name=`echo "${i}"|awk -F "-" '{print $1}'`
password=`echo "${i}"|awk -F "-" '{print $2}'`
if [[ $loginName == $name && $loginPwd == $password ]];then
#匹配到数组中的元素,则改变标识并退出循环
flag=1
break
fi
done
if [ $flag == '1' ];then
echo "欢迎登录${loginName}"
else
echo "抱歉,用户名或密码错误,登录失败!"
exit 1
fi
#################获取脚本执行参数################
parmNum=1
echo "调用shell使用传入的参数个数为"$#
for i in $*
do
echo "第${parmNum}个参数为${i}"
parmNum=$[$parmNum+1]
done
##############读取单个文件中的内容################
readFile(){
echo "开始读取文件${1}"
while read line
do
echo "当前行的数据:${line}"
done<$1
}
##使用管道符读取一个文件夹下面的文件列表(文件可使用cat $fileName|while read line读取)
total=0
readDir(){
ls $1 >$tempFile
while read file
do
echo "当前正在读取的文件名称为${file}"
#将文件行数信息保存起来
output=`wc -l $1/$file`
#使用awk指令分割显示文件的行数
rowCount=$(echo "${output}"|awk -F " " '{print $1}')
#计算该目录下面所有文件的总行数
total=$(($total+$rowCount))
echo "totalrow=${total}"
done<$tempFile
#将结果返回
echo "totalrow=${total}"
return ${total}
}
##调用函数执行
readFile $fileName
readDir $dirName
echo $?
同时,分享一下自己编写shell脚本中的一些其他经验:
1.shell脚本执行时间过长,可以让其后台运行:
比如shell脚本test.sh执行时间过长,可以使用 nohup sh test.sh & 来让test.sh后台运行,如果要停止后台运行的脚本test.sh,只需要ps -ef| grep test.sh 找到test.sh的执行进程号,然后kill -9 pid就可以。
2.windows 平台下编写的shell脚本,放到linux上执行的时候报错提示^M符号找不到:
需要将dos转换为unix下的格式,可以在linux上下载dos2unix进行转换,yum -y install dos2unix,下载完成后,使用命令dos2unix test.sh转换test.sh脚本即可,再次运行就没有这种问题了。
其次,在window平台编写shell脚本的时候,可以预先调整其编码为unix下的编码,如果已经写好了,可以使用Notpad++工具进行转换,在右下角点击"转换为unix格式"即可。
3.关于if比较:
(1) 含有逻辑运算符的比较使用[[]],例如:if [[ $name == ‘root’ && $passwd == ‘123456’ ]]
(2) 数字的比较如果使用的是>,<,>=,<=等符号最好使用(()),因为使用[]会报错,但是使用-gt -lt 等符号的时候,可以使用[]
4.关于管道符"|"的使用,管道符会创建子进程,shell中子进程中的值无法传入到父进程,所以在使用ls ${dir}| while read line或者sed -i ‘1d’ ${file}|while read line这些命令的时候,需要注意,在ls,sed外部定义的父变量,在子进程while中只是对父变量进行了拷贝,而无法对其值进行修改,如果想修改,就不要创建子进程。