Shell基础实践

        Shell 脚本(shell script),是一种为 shell 编写的脚本程序,对于开发或运维人员来说,是一项必备的技能,尤其是运维人员,需要编写大量的shell脚本来维护数据库或系统安全等,下面是shell脚本编写的一些基础。

Linux 的 Shell 种类众多,具体可到路径/usr/bin下查看:


常见的有:

Bourne Shell(/usr/bin/sh或/bin/sh)

Bourne Again Shell(/bin/bash)

C Shell(/usr/bin/csh)

K Shell(/usr/bin/ksh)

Shell for Root(/sbin/sh)

一、创建shell
#!/bin/bash #!跟shell命令的完全路径。作用:显示后期命令以哪种shell来执行这些命令。如果不指定shell,以当前shell作为执行的shell
创建shell程序的步骤:
1.创建一个包含命令和控制结构的shell文件
2.修改这个文件的权限使它可以执行
使用chmod u+x
3.执行
方法1:./example.sh
方法2:绝对路径 /root/shell/example.sh
方法3:bash example.sh 文件是644

二、shell变量:
临时变量==对其他程序不可见
永久变量==环境变量
用户自定义变量:由字母或下划线打头,使用时前面加$
将一个命令的执行结果赋值给变量:
A='date' echo $A
B=$(ls -l) echo $B

列出所有变量
set | grep DAY
单引号和双引号的区别
单引号之间的内容原封不动指定给变量, 单引号字符串中的变量是无效的;
双引号取消了空格的作用,特殊符号的含义保留, 双引号里可以有变量,双引号里可以出现转义字符

删除变量
echo Day

获取字符串长度
str=“abcd”
echo ${#str}

位置变量和特殊变量
位置变量:命令行第一个为命令 其他为位置参数
./example.sh file1 file2 file3
$0 文件名 example.sh
$n 第n个参数值 ,n=1,...N

特殊变量
$* 这个程序的所有参数
$# 这个程序的参数个数
$$ 这个程序的PID
$! 执行上一个后台程序的PID
$? 执行上一个指令的返回值
例如:z.sh
#!/bin/bash
echo "$* 表示这个程序的所有参数"
echo "$# 表示这个程序的参数个数"

touch /tmp/a.txt
echo "$$ 表示程序的进程ID"

touch /tmp/b.txt &
echo "$! 执行上一个后台指令的PID"
echo "$$ 表示程序的进程ID"

#!/bin/bash
var1="abcd efg"
echo $var1
var2=1234
echo "The value of var2 is" $var2
echo $HOME
echo $PATH
echo $PWD
三、常用命令
Read命令:
从键盘读取数据,赋给变量
read a b c
1 2 3
echo $a $b $c
1 2 3
#!/bin/bash
echo "input first second third:"
read first second third
echo "$first"
echo "$second"
echo "$third"

expr命令
作用:变量的算术运算
语法:expr 表达式
expr 8 / 2
4
expr 8 \* 2
16

test命令
语法 test 测试条件
test str1 测试字符串是否不为空
test -n str1 或 test -z str1 测试字符串是否为空
test init -eq int2


test int1 -eq int2
test int1 -ge int2 >=
test int1 -gt int2 >
test int1 -le int2 <=
test int1 -lt int2 <
也可以省略test 写成 :[int1 -lt int2]
文件测试
test -d file 是否为目录
test -f file 是否为文件
test -x file 是否可执行
-r 是否可读
-w 是否可写
-e 是否存在
test -s file 是否为空
可以简写[-x file]
if [ "$var1" == "$var2" ] ; then

四、流程控制
;分号 ls /opt; ls 前面执行失败 不影响后面
&& 前面执行失败 后面不会执行

#!/bin/bash
echo "if test"
if [ -x /bin/ls ] ; then
/bin/ls
fi
echo "============"
if [ -x /bin/ls ]
then
/bin/ls
fi
多条件联合
-a &&
-o ||

例子:测试文件类型
#!/bin/bash
echo "input a filename:"
read file_name

if [ -d $file_name ] ; then
echo "$file_name is a dir"
elif [ -f $file_name ] ; then
echo "$file_name is a file"
elif [ -c $file_name -o -b $file_name ] ; then
echo "$file_name is a device file"
else
echo "$file_name is an unknow file"
fi
case分支语句
语法:
case 变量 in
字符串1)命令列表1
;;
...
字符串n)命令列表n
;;
*)命令列表n
;;
esac

例如 菜单项
#!/bin/bash
echo "************************"
echo "Please select your operation"
echo " 1 Copy"
echo " 2 Delete"
echo " 3 Backup"
echo "*************************"
read op
case $op in
C)
echo "your selection is Copy"
;;
D)
echo "your selection is Delete"
;;
B)
echo "your selection is Backup"
;;
*) # 参数* ,匹配所有参数
echo "invalide selection"
;;
esac
循环for...done语句
格式:
for 变量 in 名字表
do
命令列表
done
例如 循环打印星期
#!/bin/bash
for DAY in Sunday Monday Tuesday Wednesday Thursday Friday Saturday
do
echo " The day is:$DAY "
done
while 循环语句
格式
while 条件
do
命令
done
例如 求10以内自然数的平方值
#!/bin/bash
num=1
while [ $num -le 10 ]
do
square=`expr $num \* $num`
echo $square
num=`expr $num + 1`
done
双括号的用法:(())
例如:依次输出小于100的2的幂值,输出的结果应该为2,4,8,16,64

[rfhadoop@master shell]$ vim '(())'.sh

#!/bin/bash
echo "The while loop example"
echo
VAR1=1
while (( VAR1<100 ))
do
echo "Value of the variable is: $VAR1"
((VAR1=VAR1*2))
done
echo
echo "The loop execution is finished"


*echo默认自动换行,下面方法让其输出不换行
方法一:
echo -n "不换行输出"
方法二:
echo -e "字符串\c"
echo -e 处理特殊字符;
可接的特殊字符有
\c 最后不加上换行符号;
\f 换行但光标仍旧停留在原来的位置;
\n 换行且光标移至行首;
\r 光标移至行首,但不换行;
\t 插入tab;
\v 与\f相同;
\\ 插入\字符;
...

利用双层循环输出直角三角形
#!/bin/bash
read -p "Please Enter the line number:" Line
read -p "Please Enter the char number:" char
a=1
while [ $a -le $Line ]
do
b=1
while [ $b -le $a ]
do
# echo -n "$char"
echo -e "$char\c"
b=`expr $b + 1`
done
echo
a=`expr $a + 1`
done
结果
打印一个正三角
*
***
*****

#/bin/bash
read -p "Please Enter a number:" Line
for ((i=1;i<=Line;i++))
do
for ((j=$Line-$i;j>0;j--))
do
echo -n ' '
done
for ((h=1;h<=$((2*$i-1));h++))
do
echo -n '*'
done
echo
done

打印一个功能菜单,实现输错后,可以重新输入,只有输入Q才可以退出菜单
while true
do
echo "********************"
echo "Please Enter your operation"
echo "1 Copy"
echo "2 Delete"
echo "3 Backup"
echo "4 Quit"
echo "********************"
read op
case $op in
C)
echo "your selection is Copy"
;;
D)
echo "your selection is Delete"
;;
B)
echo "your selection is Backup"
;;
Q)
echo "Exit..."
break
;;
*)
echo "invalid selection,please try again"
continue
;;
esac
done
五、shell函数
定义函数
函数中没有局部变量 都是全局变量
function 函数名(){
}
函数调用:函数名 参数1 参数2
不带()

自动备份mysql数据库
date -s “2018-2-19“ 修改文件时间
$? 查看上一条命令执行的结果
0 成功
1 失败
#auto backup mysql
#grantG 2018-3-26
#Define PATH
BAKDIR=/data/backup/mysql/`date +%Y-%m-%d`
MYSQLDB=test
MYSQLUSR=root
MYSQLPW=123
#must use root user run scripts,$UID is system variable
if
[ $UID -ne 0 ];then
echo This script must use root user!!!
sleep 2
exit 0
fi
#judge the DIR exists or not ,if not ,then create it
if
[ ! -d $BAKDIR ];then
mkdir -p $BAKDIR
else
echo This is $BAKDIR exists...
fi
#Use mysqldump backup mysql
/usr/bin/mysqldump -u$MYSQLUSR -p$MYSQLPW -d $MYSQLDB >$BAKDIR/webapp_db.sql
cd $BAKDIR ; tar -czf webapp_mysql_db.tar.gz *.sql
#find the sql file end with *.sql in the $BAKDIR/ and delete it

#find . -type f name *.sql |xargs rm -rf
#or
find . -type f -name *.sql -exec rm -rf {} \;
#if database backup success,print success,and delete the dir of the backup dir 30 days ago
[ $? -eq 0 ] && echo "This `date +%Y-%m-%d` MySQL BACKUP is SUCCESS"
cd /data/backup/mysql/ ; find . -type d -mtime +30 | xargs rm -rf
echo The mysql backup successfully


例如:自动解压zip数据包脚本

awk -F.'{print $2} #对取出的内容的第二列进行操作 ./passwd 则为后面的/passwd
-F. 以.作为分隔符
print输入
awk对列操作 $2第二列

例如:功能更全的菜单
#!/bin/bash
srcPath=""
dstPath=""

ErrMsg="Your enter the directory or file does not exist."
DstDirMsg="Please input destination directory"
SrcFilesMsg="Please input source directory or file"
DstFilesMsg="Delete the file or directory"
DirFileMsg=""

function inputSourcePath(){
while true
do
echo $DirFileMsg
read srcPath
if [ -d $srcPath -o -f $srcPath ]; then
if [ -e $srcPath ]; then
break
fi
fi
echo "$ErrMsg"
done
}

function inputDstPath(){
while true
do
echo $DstDirMsg
read dstPath
if [ -d $dstPath -a -e $dstPath ]; then
break
fi
echo "$ErrMsg"
done
}
function copy(){
while true
do
inputSourcePath
inputDstPath

if [ $srcPath != $dstPath -a -d $srcPath ]; then
break
elif [ -f $srcPath -a `dirname $srcPath` !=$dstPath ]; then
break
fi
echo "The source and destination cannot be the same! Please input again"
done

cp -a $srcPath $dstPath
echo "The files have been successfully copied."
}

function delele(){
inputSourcePath
echo "Proceed with removal? y"
read yn
if [ $yn == "y" ]; then
rm -rf $srcPath
echo "successfully delete!"
fi
}
function backup(){
inputSourcePath
inputDstPath
backName=`date -d today +%Y%m%d%H%M%S`
cd $dstPath
tar -czvf "$backName.tar.gz" $srcPath
echo "A successful backup to $dstPath/$backName.tar.gz"
}
function pressAnyKey(){
read -p "Press any key to continue..."
}
while true
do
echo "******************************"
echo " 1 Copy"
echo " 2 Delete"
echo " 3 Backup"
echo " 4 Quit"
echo "******************************"

read op
case $op in
1)
echo "Your selection Copy"
DirFileMsg=$SrcFilesMsg
copy
pressAnyKey
clear
;;
2)
echo "Your selection Delete"
DirFileMsg=$DstFilesMsg
delete
pressAnyKey
clear
;;
3)
echo "Your selection Backup"
DirFileMsg=$SrcFilesMsg
backup
pressAnyKey
clear
;;
4)
echo "Exit"
break
;;
*)
echo "Error!invalid selection ,try again!"
;;
esac
done

六、正则表达式
-v 不匹配
-n 显示行号
搜索包括单引号的行,并把行号也打印出来
grep -n --color \' /tmp/passwd
搜索出包含go或ga的行
grep -n --color g[ao] /tmp/passwd
搜索不以#开头的行
grep -n ^[^#] /tmp/passwd
搜索空白行及行号
grep -n ^$ regex.txt
任意长度的字符
grep .* regex.txt
寻找有r开头t结尾长度为4的行
grep ^r..t regex.txt
寻找oo,ooo,oooo等至少有两个o以上的行
grep ooo* regex.txt
查找g开头和g结尾中间可有可无
grep g.*g regex.txt

sed和awk
sed在线文件编辑器
显示第三行
sed -n '3p' regex.txt
显示前三行
sed -n '1,3p' regex.txt
除前三行以外的内容
sed -n '1,3!p' regex.txt
第三行和之后三行的内容
sed -n '1,+3p' regex.txt
在文件尾追加''@@@''
sed '$a@@@' regex.txt >a.txt
把文件第三行替换成“$$$"
sed '3c$$$'
复制粘贴
把文件的第二行到第四行复制粘贴到文件的末尾
sed ‘2,4H;$G'
删除空行 d
sed `/^$/d` regex.txt >c.txt
将regex.txt中包含qwe的行写到文件新的文件中
sed `/qwe/w newregex.txt` regex.txt

set 查看系统环境变量的
set | grep PATH

awk,优良的文本处理工具,功能最强大的数据处理引擎之一
默认分割符是空格,可以用-F,改变成逗号为分隔符 -F,

从哪安装

自定义年月日显示方式
date | awk '{print "Year:"$6 "\tmonth:"$2 "\tday:"$3}'

显示第一列和第三列
awk | '{print $1,$3}' result.txt
打印一个文件头和文件尾
awk 'BEGIN {print "name old\n"} {print $1,$3} END {print "end of class1 result"}' result.txt

第三列大于22的记录都输出
awk '$3>=22 {print $0}' result.txt

第一列为jack或者第4列为4的记录都输出
awk '{if ($1=="jack" || $4==3) print $0}' result.txt


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值