运用场景:
每当我们为很多安装同样的机器升级或者更新服务时,要备份配置文件中的某一行或者多行,或者一个数据块或者多个数据块,和服务升级、更新完后,再把对应的备份数据重新写回新的配置文件中;在大批量的服务器中操作,会浪费很多的时间和精力,以下脚本就是用来完成类似的事情。
主要功能有:
1.备份指定的一行或者多行,一个块或者多个块
2.备份指定的单个文件
3.还原所有部分备份和所有备份
4.配置文件精确定位插入【正则匹配】
5.配置文件精确定位删除
6.配置文件类似行后批量插入
服务的配置文件样例:
点击(此处)折叠或打开
-
server.config:
-
####配置文件样例:
-
ser_max_connection=6000 #行
-
ser_min_connection=10
-
-
ser_time_out=60
-
ser_time_spent=120
-
-
server tcp_nodes{ ##块
-
-
ser_client_ip=ipv4
-
ser_client_len=20*N
-
ser_client_syn=yes
-
ser_client_ack=yes
-
}
以下是shell脚本的代码实现,脚本主要是利用sed工具来完成配置编辑功能。此脚本是根据真实应用环境中改成通用版本,并没有经过严格的测试,如果你想要用此脚本,还请根据自己的环境下,做严重的测试。如果你有更好的想法,请加入QQ群:
63565867。
-
#!/bin/bash
-
#DianDian
-
proconf=/usr/local/server/etc #要备份的主目录,参数传入的文件名和会这个路径合并起来
-
confpath=$proconf
-
bkpath=/usr/local/src/bkconfig/part #备份文件中部分内容的保存目录
-
bkpath_whole=/usr/local/src/bkconfig/whole #备份整个文件的保存目录
-
handle_date=$(date "+%y%m%d%H%M")
-
mkdir -p $bkpath $bkpath_whole
-
FJ='^\+'
-
FD='^\='
-
ALLFILE=""
-
-
function multidir(){ #dirname ##shell里面的一个递归函数,用来获得一个目录下的所有文件【如果文件名中包括空格,可能会出错】
-
-
local dirs=$1
-
local diri=0
-
if [ ! -d $dirs ];then
-
echo "$dirs is not a directory."
-
exit 1
-
fi
-
local lsfile=$(ls -d $dirs/* 2>/dev/null)
-
local dir_list=($lsfile)
-
for((diri=0;diri<${#dir_list[@]};diri++)){
-
if [ -d ${dir_list[$diri]} ];then
-
multidir ${dir_list[$diri]}
-
else
-
ALLFILE="$ALLFILE ${dir_list[$diri]}"
-
fi
-
}
-
}
-
-
if [ "X$1" == "Xbackup" ];then
-
num=0
-
if [ "X$2" != "X" ];then
-
OLD_IFS="$IFS"
-
IFS="#"
-
field=($2)
-
IFS="$OLD_IFS"
-
else
-
echo -e "\033[31m Error \033[0m"
-
exit 1
-
fi
-
SFS="+"
-
F_CONF="$confpath/${field[0]}"
-
B_CONF="$bkpath/${field[0]}"
-
B_CDIR=$(dirname $B_CONF)
-
if [ -e "$B_CONF" -a -s "$B_CONF" ];then
-
echo -e "\033[31m Error $B_CONF exist and no empty. \033[0m"
-
exit 1
-
fi
-
if [ ! -d $B_CDIR ];then
-
mkdir -p $B_CDIR
-
fi
-
if [ -f "$F_CONF" ];then
-
echo "backup @${field[0]}"
-
while read line
-
do
-
((num++))
-
for((i=1;i<${#field[@]};i++)){
-
if [[ ${field[$i]} =~ $FJ ]];then
-
ST=${field[$i]#+}
-
if [[ $line =~ ^$ST ]];then
-
sed -n "$num,/}/p" $F_CONF | sed '1s/^/&+/' >> $B_CONF
-
fi
-
elif [[ ${field[$i]} =~ $FD ]];then
-
ST=${field[$i]#=}
-
STLine=${line%%=*}
-
if [[ "$STLine" == "$ST" ]];then
-
sed -n "${num}p" $F_CONF | sed '1s/^/&=/' >> $B_CONF
-
fi
-
else
-
if [[ $line =~ ^${field[$i]} ]];then
-
sed -n "${num}p" $F_CONF | sed '1s/^/&-/' >> $B_CONF
-
fi
-
fi
-
}
-
done < $F_CONF
-
else
-
echo -e "\033[31m Error:Skip ${field[0]} \033[0m"
-
fi
-
elif [ "X$1" == "Xrestore" ];then
-
if [ "X$2" != "X" ];then
-
List=(`ls -f $bkpath/$2 2>/dev/null`)
-
else
-
#List=(`ls -d $bkpath/* 2>/dev/null`)
-
multidir $bkpath
-
List=($ALLFILE)
-
fi
-
if [ "$List" == "" ];then
-
echo -e "\033[31m restore:no valid file. \033[0m"
-
fi
-
for i in ${List[*]}
-
do
-
num=0
-
B_CONF="$i"
-
base=$(basename $i)
-
if [ "$base" == "" -a -s $B_CONF ];then
-
echo -e "\033[31m restore error @ $B_CONF \033[0m"
-
continue
-
fi
-
F_CONF=$(echo $i | sed -n "s#$bkpath#$confpath#p")
-
#F_CONF="$confpath/$base"
-
echo -n "@ $F_CONF "
-
if [ ! -f $F_CONF ];then
-
echo -e "\033[31m restore error @ $F_CONF \033[0m"
-
continue
-
fi
-
while read bconf
-
do
-
((num++))
-
TT=""
-
Str=""
-
if [[ $bconf =~ $FJ ]];then
-
Str=$(sed -n -e "${num},/}/p" $B_CONF | sed '1s/^+//' | awk '{S=S"\\n"$0;}END{sub(/^../,"",S);printf("%s",S);}')
-
TT="+"
-
elif [[ $bconf =~ $FD ]];then
-
Str=$(sed -n -e "${num}p" $B_CONF | sed '1s/^=//' | awk '{S=S"\\n"$0;}END{sub(/^../,"",S);printf("%s",S);}')
-
TT="="
-
elif [[ $bconf =~ ^- ]];then
-
Str=$(sed -n -e "${num}p" $B_CONF | sed '1s/^-//' | awk '{S=S"\\n"$0;}END{sub(/^../,"",S);printf("%s",S);}')
-
TT="-"
-
else
-
continue
-
fi
-
First=$(echo -e $Str | sed -n 1p)
-
seek=0
-
while read fconf
-
do
-
((seek++))
-
tmp_fconf=${fconf%%=*}
-
tmp_first=${First%%=*}
-
if [ "$tmp_fconf" == "$tmp_first" ];then
-
if [ "$TT" == "+" ];then
-
sed -i "${seek},/}/d" $F_CONF
-
if [ $seek -ne 1 ];then
-
sed -i "$[ ${seek} - 1 ]a$Str" $F_CONF
-
else
-
sed -i "${seek}a$Str" $F_CONF
-
fi
-
echo -n "$TT"
-
TT=""
-
break
-
elif [ "$TT" == "=" ];then
-
sed -i "${seek}s/.*/$Str/" $F_CONF
-
echo -n "$TT"
-
TT=""
-
break
-
elif [ "$TT" == "-" ];then
-
sed -i "${seek}s/.*/$Str/" $F_CONF
-
echo -n "$TT"
-
TT=""
-
break
-
fi
-
fi
-
done < $F_CONF
-
if [ "$TT" != "" ];then
-
Err=$Err" $First\n"
-
fi
-
done < $B_CONF
-
echo
-
done
-
if [ "$Err" != "" ];then
-
echo -e "\n\033[33mError: $Err\033[0m"
-
Err=""
-
fi
-
elif [ "X$1" == "Xinsert" ];then
-
num=0
-
snum=0
-
n=1
-
nn=0
-
OLD_IFS="$IFS"
-
IFS="#"
-
if [ "X$2" != "X" ];then
-
insert=($2)
-
else
-
echo -e "\033[31m Insert Error \033[0m"
-
exit 1
-
fi
-
IFS="$OLD_IFS"
-
if [ -f "$confpath/${insert[0]}" ];then
-
while read olc
-
do
-
((num++))
-
tmp_olc=$(echo "$olc" | sed 's/ //g')
-
tmp_olc=${tmp_olc%%=*}
-
tmp_insert=$(echo "${insert[$n]}" | sed 's/ //g')
-
tmp_insert=${tmp_insert%%=*}
-
if [[ "$tmp_olc" == $tmp_insert && $n -le ${#insert[@]} ]];then
-
((n++))
-
if [ $n -eq $[ ${#insert[@]} - 1 ] ];then
-
echo "Insert: ${insert[$n]} @ ${insert[0]}[$num]"
-
snum=$num
-
nn=$n
-
elif [ $n -eq ${#insert[@]} ];then
-
echo -e "\033[33m${insert[$nn]} exits.\033[0m"
-
exit 1
-
fi
-
else
-
if [[ $num -eq $[ $snum + 2 ] && $nn -eq $n ]];then
-
break
-
fi
-
fi
-
done < $confpath/${insert[0]}
-
if [ $nn -ne $[ ${#insert[@]} - 1 ] ];then
-
echo -e "\033[31m Insert Error: None ${insert[$nn]} \033[0m $[ $nn + 1 ]"
-
exit 1
-
fi
-
Str="${insert[$nn]}"
-
sed -i "${snum}a\\$Str" $confpath/${insert[0]}
-
else
-
echo -e "\033[31m Insert Error:File not exist $confpath/${insert[0]} \033[0m"
-
fi
-
elif [ "X$1" == "Xdelete" ];then
-
num=0
-
n=1
-
del=0
-
OLD_IFS="$IFS"
-
IFS="#"
-
if [ "X$2" != "X" ];then
-
delete=($2)
-
else
-
echo -e "\033[31m Delete Error \033[0m"
-
exit 1
-
fi
-
IFS="$OLD_IFS"
-
if [ -f "$confpath/${delete[0]}" ];then
-
while read olc
-
do
-
((num++))
-
tmp_olc=$(echo "$olc" | sed 's/ //g')
-
tmp_olc=${tmp_olc%%=*}
-
tmp_delete=$(echo "${delete[$n]}" | sed 's/ //g')
-
tmp_delete=${tmp_delete%%=*}
-
#echo "$tmp_olc"
-
if [[ $tmp_olc == $tmp_delete ]];then
-
((n++))
-
if [ $n -eq $[ ${#delete[@]} ] ];then
-
echo "Delete: ${delete[$n-1]} @ ${delete[0]}[$num]"
-
del=1
-
break
-
fi
-
fi
-
done < $confpath/${delete[0]}
-
if [ $n -ne $[ ${#delete[@]} ] ];then
-
echo -e "\033[33mCan't find:\"${delete[$n]}\"@ $[ $n + 1 ] \033[0m"
-
exit 1
-
fi
-
sed -i "${num}d" $confpath/${delete[0]}
-
else
-
echo -e "\033[31m Delete Error:File not exist $confpath/${delete[0]} \033[0m"
-
fi
-
elif [ "X$1" == "Xinsall" ];then
-
OLD_IFS="$IFS"
-
IFS="#"
-
if [ "X$2" != "X" ];then
-
insert=($2)
-
else
-
echo -e "\033[31m insall Error \033[0m"
-
exit 1
-
fi
-
IFS="$OLD_IFS"
-
if [ -f "$confpath/${insert[0]}" ];then
-
sed -i "/${insert[1]}/a\\${insert[2]}" $confpath/${insert[0]}
-
fi
-
elif [ "X$1" == "Xcopy" ];then
-
if [ "X$2" != "X" ];then
-
OLD_IFS="$IFS"
-
IFS="#"
-
field=($2)
-
IFS="$OLD_IFS"
-
else
-
echo -e "\033[31m Copy Error \033[0m"
-
exit 1
-
fi
-
for((i=0;i<${#field[@]};i++)){
-
Deep=$(dirname ${field[$i]} 2>/dev/null)
-
copied_dir=$confpath/$Deep
-
copied_file=$confpath/${field[$i]}
-
bk_dir=$bkpath_whole/$Deep
-
bk_file=$bkpath_whole/${field[$i]}
-
if [ ! -d "$copied_dir" -o ! -f "$copied_file" ];then
-
echo -e "\033[31m copy Error @ ${field[$i]}\033[0m"
-
exit 1
-
fi
-
if [ -e "$bk_file" -a -s "$bk_file" ];then
-
echo -e "\033[31m Error $bk_file exist and no empty. \033[0m"
-
exit 1
-
fi
-
mkdir -p $bkpath_whole/$Deep && /bin/cp -f $copied_file $bk_file
-
check=$(diff $bk_file $copied_file)
-
if [ "$check" == "" ];then
-
echo "copy $copied_file => $bk_file"
-
else
-
echo "error copy @ ${field[$i]}"
-
fi
-
}
-
elif [ "X$1" == "Xrcopy" ];then
-
if [ "X$2" != "X" ];then
-
OLD_IFS="$IFS"
-
IFS="#"
-
field=($2)
-
IFS="$OLD_IFS"
-
else
-
echo -e "\033[31m rcopy Error \033[0m"
-
exit 1
-
fi
-
for((i=0;i<${#field[@]};i++)){
-
if [ "${field[$i]}" == "" ];then
-
continue
-
fi
-
Deep=$(dirname ${field[$i]} >/dev/null)
-
rcopied_dir=$confpath/$Deep
-
rcopied_file=$confpath/${field[$i]}
-
bk_dir=$bkpath_whole/$Deep
-
bk_file=$bkpath_whole/${field[$i]}
-
if [ ! -d "$bk_dir" -o ! -f "$bk_file" ];then
-
echo -e "\033[31m rcopy error $bk_dir not dir or $bk_file not file.\033[0m"
-
exit 1
-
fi
-
if [ ! -s "$bk_file" ];then
-
echo -e "\033[31m rcopy error $bk_file exist but empty. \033[0m"
-
exit 1
-
fi
-
if [ ! -d "$rcopied_dir" ];then
-
echo -e "\033[31m rcopy error:$rcopied_dir not dir. \033[0m"
-
exit 1
-
fi
-
/bin/cp -f $rcopied_file $rcopied_file.$handle_date || ( echo -e "\033[31mrcopy: backup $rcopied_file failed.\033[0m" && exit 1)
-
/bin/cp -f $bk_file $rcopied_file || ( echo -e "\033[31mrcopy: rcopy: restore $rcopied_file failed.\033[0m" && rm -rf $rcopied_file.$handle_date && exit 1)
-
check=$(diff $bk_file $rcopied_file)
-
if [ "$check" == "" ];then
-
echo "restore $bk_file => $rcopied_file"
-
rm -rf $rcopied_file.$handle_date
-
else
-
echo "error rcopy @ ${field[$i]}"
-
/bin/cp -f $rcopied_file.$handle_date $rcopied_file
-
rm -rf $rcopied_file.$handle_date
-
fi
-
}
-
elif [ "X$1" == "Xversion" ];then
-
echo "Version:1.0.7"
-
else
-
echo -e "批量备份还原给定目录下的配置文件,可以备份某个文件中的一行或者多行、一个块或者多个块。恢复时,可以直接找到对应的行或者块还原。"
-
echo -e "插入字段时,可能精确到具体的某一行"
-
echo -e "要被备份的文件格式有两种:"
-
echo -e "如:"
-
echo -e "pattern_hot_switch=0 #行"
-
echo -e "define server_proxy_host1{ #块,块以}作为结束符号"
-
echo -e " part1=no1"
-
echo -e " part2=no2"
-
echo -e " part3=no3"
-
echo -e "}"
-
echo -e "Help:"
-
echo -e "Backup Dir:"
-
echo -e "\tServer Conf Dir: $confpath"
-
echo -e "\tPartBKP Conf Dir: $bkpath"
-
echo -e "\tWholeBKP Conf Dir: $bkpath_whole"
-
echo "Usage: $0 [backup|restore|insert|delete|insall|copy|rcopy|version]"
-
echo "backup:备份 restore:还原 insert:插入 delete:删除 insall:批量插入 copy:拷贝文件 rcopy:还原拷贝的文件"
-
echo -e "\tbackup 'server.config#+src pattern#=request_src_type#...#+src src_acl#'"
-
echo -e "\tbackup 'main.config#p_src_switch#url_log_switch#=url_log_switch#'"
-
echo -e "\trestore"
-
echo -e "\trestore main.config"
-
echo -e "\tinsert 'server.config#def p_r t_default#...#r_ww_switch# xxx_xxx_xxx=1-2-3-'"
-
echo -e "\tdelete 'server.config#def p_r t_default#...#r_ww_switch#xxx_xxx_xxx'"
-
echo -e "\tinsall 'server.config#def p_r t_default#xxx_xxx_xxx=1-2-3-'"
-
echo -e "\tcopy 'main.config#r.config#....'"
-
echo -e "\trcopy 'main.config#r.config#....'"
-
fi
-
阅读(8039) | 评论(0) | 转发(0) |