shell真正体现价值的地方在于编写脚本使用工具来获取系统的相关的信息的。这个才是shell脚本使用的重大的意义的。所以,使用shell必须要将shell脚本转化为系统管理的工具来大幅度的提供系统管理的效率的。这个是价值所在的。
1.监测磁盘空间脚本
[root@mrzhang monitor]# cat diskmonitor
#!/bin/bash
# test disk monitor
# 定义标准输出流对应的输出目录信息
DATE=` date '+%m%d%y'`
exec >disk_space_$DATE.rpt # 指定标准输入流对应的输出目录的。
#定义遍历的目录信息
CHECK_DIRECTIONS="/var/log /home"
for dir in $CHECK_DIRECTIONS
do
echo "Usage dir : $dir"
# 不需要错误输出流的内容
du -S /var/log 2>/dev/null | sort -rn | sed '{11,$D;=}' | sed 'N;s/\n/ /' | gawk '{ printf $1 ":" "\t" $2 "\t" $3 "\n"}'
done
2.备份数据文件
[root@mrzhang monitor]# cat Daily_archive
#!/bin/bash
# 实现文件和目录按天归档操作
DATE=`date +%y%m%d`
#设置归档文件名称
FILE=archive$DATE.tar.gz
# 设置配置文件名称,以及最终的文件输出目录
CONFIG_FILE=/root/monitor/Files_To_Backup
DESTINATION=/root/monitor/$FILE
# 读取和检查配置文件
if [ -f $CONFIG_FILE ]
then
echo
else
echo "$CONFIG_FILE is not exists"
exit
fi
# 读取配置文件中的设置的目录,获取需要归档的文件
# 定义文件读取的起点,开始读取文件
FILE_NO=1
# 将标准的输入流指向了配置文件,开始读取配置文件
exec < $CONFIG_FILE
# 读取文件之后保存到变量 FILE_NAME中保存起来
read FILE_NAME
# 读取文件成功的话,执行下面的文件操作
while [ $? -eq 0 ]
do
if [ -f $FILE_NAME -o -d $FILE_NAME ];then
FILE_LIST="$FILE_LIST $FILE_NAME"
else
echo "$FILE_NAME is not exists"
fi
FILE_NO=$[ $FILE_NO + 1 ]
read FILE_NAME
done
# 执行文件归档操作实现
tar -czf $DESTINATION $FILE_LIST 2>/dev/null
[root@mrzhang monitor]# cat Files_To_Backup
/home/user/Downloads
/home/user/Documents/CLandSS_V2
/home/Samantha/Documents
/home/Does_not_exists
/home/Timothy/Junk
/home/consultant/Work
/var/log
/home
#上面的脚本对应的是执行的是根据每一天来进行文件的归档备份操作的。
# 下面的脚本可以实现根据小时来实现文件的归档操作实现:和根据天进行归档的操作,唯一的区别在于需要根据时间创建时间对应的范围信息的,其他的没有什么区别。
[root@mrzhang monitor]# cat Hourly_Archive
#!/bin/bash
# 定义基础目录信息
BASEDEST=/root/monitor/archive/hourly
DAY=`date +%d`
MONTH=`date +%m`
TIME=`date +%k%M`
# 创建目录信息
mkdir -p $BASEDEST/$MONTH/$DAY
#设置归档文件名称
FILE=archive$TIME.tar.gz
# 设置配置文件名称,以及最终的文件输出目录
CONFIG_FILE=/root/monitor/Files_To_Backup
DESTINATION=$BASEDEST/$MONTH/$DAY/$FILE
# 读取和检查配置文件
if [ -f $CONFIG_FILE ]
then
echo
else
echo "$CONFIG_FILE is not exists"
exit
fi
# 读取配置文件中的设置的目录,获取需要归档的文件
# 定义文件读取的起点,开始读取文件
FILE_NO=1
# 将标准的输入流指向了配置文件,开始读取配置文件
exec < $CONFIG_FILE
# 读取文件之后保存到变量 FILE_NAME中保存起来
read FILE_NAME
# 读取文件成功的话,执行下面的文件操作
while [ $? -eq 0 ]
do
if [ -f $FILE_NAME -o -d $FILE_NAME ];then
FILE_LIST="$FILE_LIST $FILE_NAME"
else
echo "$FILE_NAME is not exists"
fi
FILE_NO=$[ $FILE_NO + 1 ]
read FILE_NAME
done
# 执行文件归档操作实现
tar -czf $DESTINATION $FILE_LIST 2>/dev/null
3.管理用户账户
[root@mrzhang monitor]# cat Delete_User
#!/bin/bash
# delete user account
# 删除用户需要如下的4个步骤的:
# 1.获取到需要删除的用户账户的正确的账户名称
# 2.强制终止正在系统上面运行的属于该账户的进程
# 3.确认系统属于该账户的所有文件
# 4.删除用户账户
#获取用户输入的答案,是一个通用的方法
function get_answer {
unset ANSWER
unset ASK_COUNT
ASK_COUNT=0
# 输入的内容为空的话,需要持续输入的
while [ -z "$ANSWER" ]
do
ASK_COUNT=$[ $ASK_COUNT + 1 ]
case $ASK_COUNT in
1)echo "please answer the question";;
2)echo "please answer the question";;
3)echo "One last try...please answer the question";;
4)echo "refuse to answer the question"; exit;;
esac
#针对每一次的回答需要设置提示语信息
if [ -n "$LINE2" ]
then
echo $LINE1
echo -e $LINE2 " \c"
else
echo -e $LINE1 " \c"
fi
# 开始下一次的输入操作,主要注意的是当输出流进入到管道的模式下面的话,对应的read是无法从标准输入中读取数据的
read -t 60 ANSWER
done
#重置提示语信息
unset LINE1
unset LINE2
}
# 处理请求答案的方法
function process_answer {
case "$ANSWER" in
y|Y|YES|Yes|yEs|yeS|YEs|yES);;
*)echo $EXIT_LINE1;echo $EXIT_LINE2;exit
esac
unset $EXIT_LINE1
unset $EXIT_LINE2
}
###################Main Script###############
# 定义标准输入流的操作的,后续重新定向到标准的输入流中的
exec 3>&0
#定义标准的输入流操作
echo "Step #1 - Determine User Account name to Delete"
LINE1="Please enter the username of the user"
LINE2="account you wish to delete from system"
get_answer
# 获取用户输入的账号信息
USER_ACCOUNT=$ANSWER
# 设置提示语信息
LINE1="Is $USER_ACCOUNT the user account"
LINE2="you wish to delete from the system?[y/n]"
# 再次确认是否删除指定用户
get_answer
EXIT_LINE1="Because the account $USER_ACCOUNT is not"
EXIT_LINE2="the one you wish to delete we are leaving the script"
process_answer
# 下面确认账户是否是系统的默认的账户
USER_ACCOUT_RECORD=`cat /etc/passwd | grep -w $USER_ACCOUNT`
# 找不到对应的用户的话,执行如下操作
if [ $? -eq 1 ]
then
echo "accont $USER_ACCOUNT is not exists"
exit
fi
# 找到了对应的系统账户
echo "I found the account $USER_ACCOUNT"
# 再次确认是否删除指定的用户$USER_ACCOUNT
LINE1="Is this the correct User Account?[y/n]"
get_answer
EXIT_LINE1="Because the account $USER_ACCOUNT is not"
EXIT_LINE2="the one you wish to delete we are leaving the script"
process_answer
####################################### DEAL WITH PROCESSES#####################
# 处理账户对应的正在运行的进程信息
ps -u $USER_ACCOUNT
case $? in
1)echo "no process running";;
0)echo "process running process"
LINE1="Would you like me to kill the process?[y/n]"
get_answer
case "$ANSWER" in
y|Y|YES|Yes|yEs|yeS|YEs|yES)
#定义捕捉信息 rm 操作
trap "rm $USER_ACCOUNT_Running_Process.rpt" SIGTERM SIGINT SIGQUIT
ps -u $USER_ACCOUNT > ${USER_ACCOUNT}_Running_Process.rpt
# 开始服务文件中的进程进行操作处理
exec < ${USER_ACCOUNT}_Running_Process.rpt
# 开始读取数据
read USER_PROCESS_REC #第一次读取数据的时候是空的。
read USER_PROCESS_REC
# 读取数据
while [ $? -eq 0 ]
do
#获取进程id
USER_PID=`echo $USER_PROCESS_REC| tail -n 1 | cut -d " " -f1`
kill -9 $USER_PID
echo "Killed $USER_PID"
read USER_PROCESS_REC
done
rm ${USER_ACCOUNT}_Running_Process.rpt ;;
*)echo "";;
esac
esac
####################################### CREATE A Report#####################
# 创建删除账户的报告
echo "Creating a report of all files owned by $USER_ACCOUNT"
echo "It is recommended that you backup/archive these files"
echo "and then do one of these things"
echo "1)Delete the files"
echo "2)Change the files ownership to a current user account"
# 创建变量
REPORT_DATA=`date +%y%m%d`
REPORT_FILE="${USER_ACCOUNT}"_Files_"${REPORT_DATE}".rpt
find / -user $USER_ACCOUNT > $REPORT_FILE 2>/dev/null
# 重新将标准的输入流切换到控制太上面的。
echo "Report is complete"
echo "Name of report: $REPORT_FILE"
echo "Location of report : `pwd`"
####################################### REMOVE USER Account##################
echo "========================================================================="
echo " remove user account"
LINE1="Do you wish to remove ${USER_ACCOUNT} account from system [y/n] "
# 继续调用的时候,对应的read -p 出现了问题的,read不需要执行任何输入就继续进行操作了。
exec 0>&3
get_answer
EXIT_LINE1="Since you do not wish to remove the user account"
EXIT_LINE2="$USER_ACCOUNT at this time exiting the script"
process_answer
# 开始删除用户
userdel $USER_ACCOUNT
echo "User Account ,$USER_ACCOUNT has been removed "
[root@mrzhang monitor]# vim Delete_User
[root@mrzhang monitor]# cat Delete_User
#!/bin/bash
# delete user account
# 删除用户需要如下的4个步骤的:
# 1.获取到需要删除的用户账户的正确的账户名称
# 2.强制终止正在系统上面运行的属于该账户的进程
# 3.确认系统属于该账户的所有文件
# 4.删除用户账户
#获取用户输入的答案,是一个通用的方法
function get_answer {
unset ANSWER
unset ASK_COUNT
ASK_COUNT=0
# 输入的内容为空的话,需要持续输入的
while [ -z "$ANSWER" ]
do
ASK_COUNT=$[ $ASK_COUNT + 1 ]
case $ASK_COUNT in
1)echo "please answer the question";;
2)echo "please answer the question";;
3)echo "One last try...please answer the question";;
4)echo "refuse to answer the question"; exit;;
esac
#针对每一次的回答需要设置提示语信息
if [ -n "$LINE2" ]
then
echo $LINE1
echo -e $LINE2 " \c"
else
echo -e $LINE1 " \c"
fi
# 开始下一次的输入操作,主要注意的是当输出流进入到管道的模式下面的话,对应的read是无法从标准输入中读取数据的
read -t 60 ANSWER
done
#重置提示语信息
unset LINE1
unset LINE2
}
# 处理请求答案的方法
function process_answer {
case "$ANSWER" in
y|Y|YES|Yes|yEs|yeS|YEs|yES);;
*)echo $EXIT_LINE1;echo $EXIT_LINE2;exit
esac
unset $EXIT_LINE1
unset $EXIT_LINE2
}
###################Main Script###############
# 定义标准输入流的操作的,后续重新定向到标准的输入流中的
exec 3>&0
#定义标准的输入流操作
echo "Step #1 - Determine User Account name to Delete"
LINE1="Please enter the username of the user"
LINE2="account you wish to delete from system"
get_answer
# 获取用户输入的账号信息
USER_ACCOUNT=$ANSWER
# 设置提示语信息
LINE1="Is $USER_ACCOUNT the user account"
LINE2="you wish to delete from the system?[y/n]"
# 再次确认是否删除指定用户
get_answer
EXIT_LINE1="Because the account $USER_ACCOUNT is not"
EXIT_LINE2="the one you wish to delete we are leaving the script"
process_answer
# 下面确认账户是否是系统的默认的账户
USER_ACCOUT_RECORD=`cat /etc/passwd | grep -w $USER_ACCOUNT`
# 找不到对应的用户的话,执行如下操作
if [ $? -eq 1 ]
then
echo "accont $USER_ACCOUNT is not exists"
exit
fi
# 找到了对应的系统账户
echo "I found the account $USER_ACCOUNT"
# 再次确认是否删除指定的用户$USER_ACCOUNT
LINE1="Is this the correct User Account?[y/n]"
get_answer
EXIT_LINE1="Because the account $USER_ACCOUNT is not"
EXIT_LINE2="the one you wish to delete we are leaving the script"
process_answer
####################################### DEAL WITH PROCESSES#####################
# 处理账户对应的正在运行的进程信息
ps -u $USER_ACCOUNT
case $? in
1)echo "no process running";;
0)echo "process running process"
LINE1="Would you like me to kill the process?[y/n]"
get_answer
case "$ANSWER" in
y|Y|YES|Yes|yEs|yeS|YEs|yES)
#定义捕捉信息 rm 操作
trap "rm $USER_ACCOUNT_Running_Process.rpt" SIGTERM SIGINT SIGQUIT
ps -u $USER_ACCOUNT > ${USER_ACCOUNT}_Running_Process.rpt
# 开始服务文件中的进程进行操作处理
exec < ${USER_ACCOUNT}_Running_Process.rpt
# 开始读取数据
read USER_PROCESS_REC #第一次读取数据的时候是空的。
read USER_PROCESS_REC
# 读取数据
while [ $? -eq 0 ]
do
#获取进程id
USER_PID=`echo $USER_PROCESS_REC| tail -n 1 | cut -d " " -f1`
kill -9 $USER_PID
echo "Killed $USER_PID"
read USER_PROCESS_REC
done
rm ${USER_ACCOUNT}_Running_Process.rpt ;;
*)echo "";;
esac
esac
####################################### CREATE A Report#####################
# 创建删除账户的报告
echo "Creating a report of all files owned by $USER_ACCOUNT"
echo "It is recommended that you backup/archive these files"
echo "and then do one of these things"
echo "1)Delete the files"
echo "2)Change the files ownership to a current user account"
# 创建变量
REPORT_DATA=`date +%y%m%d`
REPORT_FILE="${USER_ACCOUNT}"_Files_"${REPORT_DATE}".rpt
find / -user $USER_ACCOUNT > $REPORT_FILE 2>/dev/null
# 重新将标准的输入流切换到控制太上面的。
echo "Report is complete"
echo "Name of report: $REPORT_FILE"
echo "Location of report : `pwd`"
####################################### REMOVE USER Account##################
echo " remove user account"
LINE1="Do you wish to remove ${USER_ACCOUNT} account from system [y/n] "
# 继续调用的时候,对应的read -p 出现了问题的,read不需要执行任何输入就继续进行操作了。
exec 0>&3
get_answer
EXIT_LINE1="Since you do not wish to remove the user account"
EXIT_LINE2="$USER_ACCOUNT at this time exiting the script"
process_answer
# 开始删除用户
userdel $USER_ACCOUNT
echo "User Account ,$USER_ACCOUNT has been removed "
4.系统快照报告
[root@mrzhang monitor]# cat Snapshot_Stats
#!/bin/bash
#定义脚本变量
DATE=`date +%m%d%Y`
DISKS_TO_MONITOR="/dev/vda1"
MAIL=`which mutt`
MAIL_TO="root"
REPORT=/root/monitor/${DATE}.rpt
# 保存文件描述符信息
exec 3>&1
# 将标准输出输入到文件$REPORT文件之中
exec 1>$REPORT
################# MAIN SCRIPT##############################
echo -e "\t\tDaily System Report"
echo -e "Today is `date +%m/%d/%Y`"
##################GEATHER System Uptime Statistics########
echo -e "System has been \c"
uptime |sed 's/\,//g' | gawk '{
if($4=="days" || $4=="day")
{ print $2,$3,$4,$5}
else { print $2,$3} }'
##################GEATHER System Disk Usage Statistics########
for disk in "$DISKS_TO_MONITOR"
do
df -h /dev/vda1 | sed -n 's/%//p'| sed 'N;D'| gawk '{ print $5}'
done
##################GEATHER Memory Usage Statistics########
echo -e "Memory Usage: \c"
free | sed -n '2p' | gawk '{x=int(($3/$2)*100);print x}'| sed 's/$/%/'
##################GEATHER Number of Zombie Processes########
echo -e "Zombie Processes"
ZOMBIE_CHECK=`ps -al | gawk '{ print $2,$4}' | grep Z`
if [ -z $ZOMBIE_CHECK ]
then
echo "no zombie processes found"
else
echo "Current System Zombie Processes"
ps -al |gawk '{ print $2,$4}'|grep Z
fi
# 完成操作之后,输出流会员
exec 1>&3
#########################################send mail############
#只有mutt是可以发送邮件的,单纯的mail是无法发送邮件的
$MAIL -s "System Statistics Report for $DATE" -- $MAIL_TO -a $REPORT
5系统统计数据报告
5-1 获取系统统计数据
[root@mrzhang monitor]# cat System_calc
#!/bin/bash
# create system calc report 创建系统的统计数据报告
# 定义脚本变量
REPORT_FILE=/root/monitor/capstats.csv
DATE=`date +%m/%d/%Y`
TIME=`date +%k:%M:%S`
##################################GATHER PERFORMANCE STATISTICS######
#获取系统上面用户的商量信息
USERS=`uptime | sed 's/users.*$//g' | gawk '{ print $NF}'`
# 获取系统负载因子
LOAD=`uptime | gawk '{ print $NF}'`
#获取空闲的内存总量
FREE=`vmstat 1 2 | sed -n '3p' | gawk '{ print $4}'`
#获取空闲状态对应的cpu的占比数据
IDLE=`vmstat 1 2 | sed -n '3p' | gawk '{ print $15}'`
# 结果输出到文件
echo "$DATE,$TIME,$USERS,$LOAD,$FREE,$IDLE" >>$REPORT_FILE
#####################################
5-2统计数据的报表数据
[root@mrzhang monitor]# cat Report_Stats
#!/bin/bash
# System calc report output
############################################设置脚本变量################
REPORT_FILE=/root/monitor/capstats.csv
TEMP_FILE=/root/monitor/capstats.html
DATE=`date +%m/%d/%Y`
MAIL=`which mutt`
MAIL_TO="root"
##########################################创建报表头信息################
echo "
Report for $DATE
" > $TEMP_FILEecho "
echo "
DateTimeUsers" >> $TEMP_FILEecho "
LoadFree Memory%Cpu Idle" >> $TEMP_FILE############################################给报告中增加数据############
cat $REPORT_FILE |gawk -F "," '{
printf "
%s%s%s",$1,$2,$3;printf "
%s%s%s\n\n",$4,$5,$6}' >> $TEMP_FILEecho "
" >> $TEMP_FILE########################################执行文件的首尾工作###############
$MAIL -a $TEMP_FILE -s "Peformance Report $DATE" -- $MAIL_TO
rm -rf $TEMP_FILE
6.问题追踪数据库:将脚本执行过程中的各种问题同步到对应的数据库中,这样的话,可以将执行过程中的所有的操作的问题写入到数据库中的。便于后续的操作和管理实现。
6-1 向数据库中插入数据,获取相关的数据查询结果。
[root@mrzhang monitor]# cat Record_Problem
#!/bin/bash
# 给数据库增加数据记录操作
# 定义数据库常量信息
MYSQL=`which mysql`" Problem_Trek -u cbres"
ID_NUMBER=`date +%y%m%d%H%M`
REPORT_DATE=`date +%Y%m%d`
# 获取用户输入的简要的描述信息
echo -e "Briefly describe the problem & its symptons: \c"
read ANSWER
PROB_SYMPTONS=$ANSWER
#######################################设置参数值信息#########
FIXED_DATE=0
PROB_SOLUTIONS=""
echo "Problem recorded as follows:"
$MYSQL <
insert into problem_logger values($ID_NUMBER,$REPORT_DATE,$FIXED_DATE,"$PROB_SYMPTONS","$PROB_SOLUTIONS");
commit;
select * from problem_logger where id_number=$ID_NUMBER\G
EOF
6-2 执行数据库的更新脚本操作实现
[root@mrzhang monitor]# cat Update_Problem
#!/bin/bash
# 执行问题的更新操作和实现
# 定义环境变量
MYSQL=`which mysql`" Problem_Trek -u cbres"
# 获取需要更新的数据库的记录id信息
if [ $# -eq 0 ]
then
echo "从数据库获取需要更新的数据记录id"
RECORD_EXISTS=`$MYSQL -Bse 'select id_number from problem_logger where fixed_date="0000-00-00" or prob_solutions=""'`
#更新记录存在,那么需要更新数据记录
if [ -n "$RECORD_EXISTS" ]
then
echo "The following records needs updating"
# 输出需要处理的记录的信息,这样的话便于后续的获取到对应的id信息
$MYSQL <
select id_number,report_date,prob_symptons from problem_logger where fixed_date="0000-00-00" or prob_solutions=""\G
EOF
fi
echo "What is the ID number for the"
echo -e "problem you want to update?:\c"
read ANSWER
ID_NUMBER=$ANSWER
else
ID_NUMBER=$1
fi
##########################################获取问题的执行时间信息################
echo -e "Was problem solved today?(y/n) \c"
read ANSWER
case "$ANSWER" in
y|Y|YES|Yes|yEs|yeS|YEs|yES) FIXED_DATE=`date +%Y%m%d`;;
*) echo "What was the date of resolution?[YYYYMMDD] \c"
read ANSWER
FIXED_DATE=$ANSWER
;;
esac
###########################################获取问题的解决方案信息################
echo -e "Briefly describe the problem solution: \c"
read ANSWER
PROB_SOLUTIONS=$ANSWER
###########################################开始执行数据库的更新记录操作##########
echo "Problem record updated as follows:"
$MYSQL <
update problem_logger set prob_solutions='$PROB_SOLUTIONS',fixed_date=$FIXED_DATE where id_number=$ID_NUMBER;
commit;
select * from problem_logger where id_number=$ID_NUMBER\G
EOF