运维常用shell脚本

运维shell脚本

1.判断/tmp/run目录是否存在,如果不存在就建立,如果存在就删除目录里所有文件
#!/bin/bash
dir=/tmp/run
[ -f $dir ] && mv $dir $dir.bak
[  -d $dir ] && rm -rf $dir/* || mkdir $dir
2.输入一个文件的绝对路径,判断路径是否存在,而且输出是文件还是目录,如果是字符连接,还得输出是有效的连接还是无效的连接
#!/bin/bash
read -p "Input a path:" path
if [ -L $path -a -e $path ];then
	echo "this is effective link"
elif [ -L $path -a ! -e $path ];then
	echo "this is not effective link"
elif [ -d $path ];then
	echo "this is a director"
elif [ -f $path ];then
	echo "this is file"
elif [ -e $path ];then
	echo "this is a other type file"
else
	echo "the file is not exist"
fi
3.交互模式要求输入一个ip,然后脚本判断这个IP 对应的主机是否 能ping 通,输出结果类似于:
Server  10.1.1.20 is Down! 最后要求把结果邮件到本地管理员root@localhost和mail01@localhost

方法一:

#!/bin/bash
read -p "输入IP地址:" ip
ping -c 2 $ip  > /dev/null 2>&1
if [ $? -eq 0 ];then
  echo "Server $ip is OK. " |mail -s 'check server' root@localhost
else
  echo "Server $ip is Down!" |mail -s 'check server' root@localhost
fi

方法二:

#!/bin/bash
read -p "Input your ip:" ip
ping -c 1 $ip &>/dev/null
[ $? -eq 0 ] && echo "server $ip is ok"|mail -s "check server" root@localhost || echo "server $ip is down" |mail -s "check server" root@localhost

方法三:

#!/bin/bash
tmpfile=`mktemp`
mailaddr="root@localhost mail@localhost"
read -p "输入IP地址:" ip
ping -c 2 $ip  > /dev/null 2>&1
if [ $? -eq 0 ];then
    echo "Server $ip is Up! " >> $tmpfile
else
    echo "Server $ip is Down!" >> $tmpfile
fi 
cat $tmpfile
mail -s "ping server" $mailaddr < $tmpfile
rm -rf $tmpfile

方法四:

#!/bin/bash

rootmail="root@localhost"
tmpfile=`mktemp`
read -p "Input a ip : " ip

ping -c 1 "$ip" &>/dev/null

retval=$?

if [ $retval -eq  0 ];then
	echo "Server $ip is up" > $tmpfile
else
	echo "Server $ip is down" > $tmpfile
fi

cat $tmpfile
mail -s "ping result" $rootmail < $tmpfile
rm -rf $tmpfile
4.写一个脚本,局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里(如果例举整个网段的254个IP花的时间比较长,可以只分类10个ip10.1.1.1~10) 这只是一个局域网内机器检查通讯的一个思路。
#!/bin/bash
#清空原来ip文件里的列表
>/tmp/ip_ok
>/tmp/ip_down
ip=10.1.1
#循环去ping局域网内的主机
for ((i=1;i<=10;i++))
do
ping -c1 $ip.$i &>/dev/null
test $? -eq 0 && echo "$ip.$i" |tee -a /tmp/ip_ok || echo "$ip.$i" |tee -a /tmp/ip_down
done

思考:以上方法可以实现,但是速度很慢,希望并行执行

#!/bin/bash
#清空原来ip文件里的列表
>/tmp/ip_ok
>/tmp/ip_down
ip=10.1.1
#循环去ping局域网内的主机
for ((i=1;i<=10;i++))
do
{
ping -c1 $ip.$i &>/dev/null
test $? -eq 0 && echo "$ip.$i" |tee -a /tmp/ip_ok || echo "$ip.$i" |tee -a /tmp/ip_down
}&
done
wait
echo "ip is ok..."
5.写一个脚本/home/hello.sh,要求当给脚本输入参数hello时,脚本返回world,给脚本输入参数world时,脚本返回hello。而脚本没有参数或者参数错误时,屏幕上输出“usage:/home/hello.sh hello or world”
#!/bin/bash
#read -p "Input a string:" a

if [  $# -eq 0 -o $# -gt 1 ];then
        echo "usage:/home/program/test4.sh world|hello"
        # echo "usage:`basename $0` world|hello" # 更常用的报错写法
elif [ "$1" = "hello" ];then
        echo "world"
elif [ "$1" = "world" ];then
        echo "hello"
else
        echo "usage:/home/program/test4.sh world|hello"
fi
6.自动搭建nfs服务
#!/bin/bash
#关闭防火墙和selinux
service iptables stop
chkconfig iptables off
setenforce 0 &>/dev/null
echo "########防火墙和selinux已经关闭########"
#测试网络,配置内网yum源
ping -c 1 192.168.1.10 &>/dev/null
if [ $? -eq 0 ];then
    echo "########网络ok########"
else
   echo "########请检查你的网络########"
   exit
fi
wget -P /etc/yum.repos.d/ ftp://192.168.1.10/demo.repo &>/dev/null
#安装相关软件
yum -y install 'nfs*' rpcbind &> /dev/null && echo "########软件安装ok#######"
#发布共享目录并授权
read -p "Input your share dir:" dir
[ ! -d $dir ] && mkdir $dir -p 
#授权
chmod 1777 $dir
read -p "Input your share host(192.168.0.0/24(ro)):" host
cat >> /etc/exports << end
$dir $host
end
#启动服务,开机自启动
service rpcbind restart &>/dev/null && echo "##########rpcbind服务启动成功#############"
service nfs restart &>/dev/null && echo "############nfs服务启动成功#############"
chkconfig rpcbind on
chkconfig nfs on
#测试验证
mkdir /u01 &>/dev/null
mount.nfs  localhost:$dir /u01
[ $? -eq 0 ] && echo "nfs服务测试ok,可以正常使用!"
umount /u01
7.将/etc/passwd里的用户名分类,分为管理员用户,系统用户,普通用户。
分析:
1. 根据用户的uid来判断用户种类
2.用户的信息保存在/etc/passwd文件中,需要在该文件中获取UID
3.根据用户的uid去判断
管理员:root 0
系统用户:1-499	ftp apache ...  65534 nfsnobody
普通用户:500-60000
#!/bin/bash
for i in `cat /etc/passwd|cut -d: -f1,3`
	do
		uid=`echo $i |cut -d: -f2`
		name=`echo $i |cut -d: -f1`
		[ $uid -eq 0 ] && echo $name >>/tmp/adminuser
		[ $uid -gt 0 -a $uid -lt 500 -o $uid -eq 65534 ] && echo $name >>/tmp/systemuser
		[ $uid -ge 500 -a $uid -ne 65534 ] && echo $name >>/tmp/normaluser
	done
8.写一个倒计时脚本,要求显示离2018年1月1日(元旦节)的凌晨0点,还有多少天,多少时,多少分,多少秒。
分析:
1. 该脚本应该是一个死循环,除非当前系统时间等于1月1日的凌晨0点,要退出循环,并且打印元旦快乐  break
2. 计算未来时间(1月1日的凌晨0点)和当前系统时间的时间差     时间单位相同并且以相同的时间为一个基准  
需要定义2个变量:
现在时间和未来时间
date命令 -d  %s
3. 计算
假如1月1日和现在时间相差100000s
1天=86400s
1小时=3600s
1分钟=60
$[  100000/86400  ]=天
$[ $[100000%86400] /3600   ]=小时
$[   $[ 100000%3600] /60     ]=分钟
#!/bin/bash
goal=`date +%s -d 20181001`

while true 或者until false
do
        	now=`date +%s`
	if [ $[$goal-$now] -eq 0 ];then
		break
	fi
        day=$[($goal-$now)/86400]
        hour=$[($goal-$now)%86400/3600]
        minute=$[($goal-$now)%3600/60]
        second=$[($goal-$now)%60]
	clear
        echo "离2018年1月1日还有$day天:$hour时:$minute分:$second秒"
        sleep 1
done
echo "元旦节快乐!!!"
9.写一个脚本把一个目录内的所有空文件都删除,最后输出删除的文件的个数。
分析:
1. 如何判断文件是空文件  -s 判断文件内容为非空;判断空文件则 ! -s    eg:[ ! -s file ]
2. 定义一个变量count=0来保存删除文件的个数,掌握四则运算  let count++
3. 交互式定义变量让用户自己决定清理哪个目录  /data/logs/   10个文件		循环次数由目录里的文件个数决定	find命令
#!/bin/bash
read -p "输入一个你要删除空文件的目录:" dir

count=0
for i in `find $dir -type f`
do
	[ ! -s $i ] && rm -rf $i && let count++     ##-s表示非空
done

echo "删除的个数为:" $count	
10.写一个脚本,将跳板机上yunwei用户的公钥推送到局域网内可以ping通的所有机器上 10.1.1.1~10.1.1.254
分析:
环境:
jumper-server	有yunwei用户
app1-appn  局域网内所有可以ping通的机器


1. 在跳板上创建yunwei用户,并且生成一对秘钥
2. 检测当前局域网中哪些ip是能ping通哪些是不能ping通		循环语句并发的去检查
3. 在脚本中所有的交互动作需要用到expect实现

yunwei用户sudo授权:
visudo
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
yunwei  ALL=(root)      NOPASSWD:ALL,!/sbin/shutdown,!/sbin/init,!/bin/rm -rf /
#!/bin/bash
#检查局域网中哪些ip是可以ping通,并保存到一个文件
ip1=10.1.1
for ((i=1;i<=10;i++))
do
	{
      ping -c1 $ip1.$i &>/dev/null
      [ $? -eq 0 ] && echo "$ip1.$i" >> ip_up.txt
	}&
done
wait

#yunwei用户生成一对秘钥(有交互)
[ ! -f ~/.ssh/id_rsa ] && ssh-keygen -P '' -f ~/.ssh/id_rsa

#将yunwe用户的公钥远程拷贝到指定的服务器 100	循环
##判断expect程序是否安装
{
rpm -q expect
[ $? -ne 0 ] && sudo yum -y install expect
while read ip2
do
	/usr/bin/expect<<-EOF
	spawn ssh-copy-id  root@$ip2
	expect {
      "yes/no" {send "yes\r";exp_continue}
      "password:" {send "123\r"}
      }
	expect eof
	EOF
done<ip_up.txt
} &>/dev/null

#测试验证
remote_ip=`tail -1 ip_up.txt`
ssh root@$remote_ip hostname
[ $? -eq 0 ] && echo "公钥推送完毕...."
#!/bin/bash
#push publickey to aap-servers
#将局域网内可以ping通的主机ip保存到一个文件
> ip_up.txt
for i in {2..10}
do
	{
	ip=10.1.1.$i
	ping -c1 $ip &>/dev/null
	[ $? -eq 0 ] && echo $ip |tee -a ip_up.txt
	}&			//并行放到后台运行
done
wait			//等待进程结束
#将yunwei用户目录下的公钥推送到可以ping的服务器上
#1. 判断yunwei用户下有没有公钥
[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -P "" -f ~/.ssh/id_rsa

#2.将id_rsa.pub公钥远程推送到指定服务器
#2.1 判断expect程序是否安装,没安装则安装它
{
rpm -q expect
[ $? -ne 0 ] && sudo yum -y install expect

for remote_ip in `cat ip_up.txt`
do
	/usr/bin/expect <<-EOF
	spawn ssh-copy-id root@$remote_ip
	expect {
      	"yes/no" { send "yes\r";exp_continue }
      	"password:" { send "123\r" }
	}
	 expect eof
	EOF
done
} &>/dev/null
#测试验证
test_ip=`tail -1 ip_up.txt`
ssh root@$test_ip hostname
test $? -eq 0 && echo "公钥推送成功。"
#!/bin/bash
[ ! -f ~/.ssh/id_rsa.pub ] && ssh-keygen -P "" -f ~/.ssh/id_rsa
rpm -q expect
[ $? -ne 0 ] && sudo yum -y install expect
for i in {130..140}
do
        ip=192.168.44.$i
        ping -c1 $ip
        [ $? -ne 0 ] && continue
        echo $ip >>ip_up.txt
        /usr/bin/expect <<-EOF
        spawn ssh-copy-id root@$ip
        expect {
        "yes/no" { send "yes\r";exp_continue }
        "password:" { send "123456\r" }
        }
        expect eof
        EOF
done
#测试验证
test_ip=`tail -1 ip_up.txt`
ssh root@$test_ip hostname
test $? -eq 0 && echo "公钥推送成功。"
11.

任务/背景:
现有的跳板机虽然实现了统一入口来访问生产服务器,yunwei用户权限太大可以操作跳板机上的所有目录文件,存在数据被误删的安全隐患,所以希望你做一些安全策略来保证跳板机的正常使用。

具体要求:

  1. 只允许yunwei用户通过跳板机远程连接后台的应用服务器做一些维护操作
  2. 公司运维人员远程通过yunwei用户连接跳板机时,跳出以下菜单供选择:
    欢迎使用Jumper-server,请选择你要操作的主机:
    1. DB1-Master
    2. DB2-Slave
    3. Web1
    4. Web2
    q. exit
  1. 当用户选择相应主机后,直接免密码登录成功
  2. 如果用户不输入一直提示用户输入,直到用户选择退出

思路:

  1. 需要当yunwei用户登录时执行一个脚本(该脚本放到哪里?)yunwei用户的家目录里的.bashrc
  2. 脚本中需要打印一个菜单供用户选择(case…esac)
  3. 免密码登录(上面第10个脚本推公钥的脚本)
#!/bin/bash
#公钥推送成功
trap '' 1 2 3 19
#打印菜单用户选择
menu(){
cat <<-EOF
欢迎使用Jumper-server,请选择你要操作的主机:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
h. help
q. exit
EOF
}

#调用函数来打印菜单
menu
while true
do
read -p "请输入你要选择的主机[h for help]:" host

#通过case语句来匹配用户所输入的主机
case $host in
	1|DB1)
	ssh root@10.1.1.1
	;;
	2|DB2)
	ssh root@10.1.1.2
	;;
	3|web1)
	ssh root@10.1.1.250
	;;
	h|help)
	clear;menu
	;;
	q|quit)
	exit
	;;
esac
done


#!/bin/bash
#jumper-server
#菜单打印
trap '' 1 2 3 
while true
do
cat <<-END
欢迎使用Jumper-server,请选择你要操作的主机:
1. DB1-Master
2. DB2-Slave
3. Web1
4. Web2
5. exit
END
#让用户选择相应的操作
read -p "请输入你要操作的主机:" host
case $host in
	1)
	ssh root@10.1.1.2
	;;
	2)
	ssh root@10.1.1.3
	;;
	3)
	ssh root@10.1.1.4
	;;
	5)
	exit
	;;
	*)
	clear
	echo "输入错误,请重新输入..."
	;;
esac
done
12.写一个脚本,统计web服务的不同连接状态个数
#!/bin/bash
#count_http_80_state
#统计每个状态的个数
declare -A STATE
states=`ss -ant|grep 80|cut -d' ' -f1`
for i in $states
do
        let STATE[$i]++
done
#通过遍历数组里的索引和元素打印出来
for j in ${!STATE[@]}
do
        echo $j:${STATE[$j]}
done
13.写一个自动搭建apache服务的脚本,要求如下:
1、用户输入web服务器的IP、域名以及数据根目录
2、如果用户不输入则一直提示输入,直到输入为止
3、当访问www.test.cc时可以访问到数据根目录里的首页文件“this is test page” 
#!/bin/bash
#定义函数实现用户不输入则一直提示输入,直到输入为止
input_fun(){
        input_var=''
        while [ -z $input_var ]
                do
                read -p "$1" input_var
                done
                echo $input_var
}
#调用函数并且获取用户输入web服务器的IP、域名以及数据根目录
IP=`input_fun 请输入你的IP地址:`
name=`input_fun 请输入你的域名:`
dir=`input_fun 请输入你的数据根目录:`
#将ip与主机名输入到hosts文件里
cat>>/etc/hosts<<EOF
$IP $name
EOF
#创建数据根目录和首页文件
[ -f $dir ] && mv $dir $dir.bak
[ ! -d $dir ] && mkdir -p $dir
echo "this is $name test page" > $dir/index.html
#yum安装apache
yum -y install httpd &>/dev/null
#发布虚拟主机
cat>>/etc/httpd/conf/httpd.conf<<-EOF
NameVirtualHost *:80
<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot $dir
    ServerName $name
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common
</VirtualHost>
EOF
#启动
service httpd restart &>/dev/null
echo "====apache启动成功===="
#测试验证
curl http://$name
14.需求:写一个脚本让用户输入基本信息(姓名,性别,年龄),如不输入一直提示输入,最后根据用户的信息输出相对应的内容

思路:

  • 循环直到输入字符串不为空 -z -n
  • 根据用户输入信息做出匹配判断
#!/bin/bash
#该函数实现用户如果不输入内容则一直循环直到用户输入为止,并且将用户输入的内容打印出来
input_fun()
{
  input_var=""
  output_var=$1
  while [ -z $input_var ]
	do
	read -p "$output_var" input_var
	done
	echo $input_var
}


或者
fun(){
read -p "请输入您的姓名:" name
if [ -z $name ];then
fun
else
echo "你好,$name!"
fi
}
fun


#调用函数并且获取用户的姓名、性别、年龄分别赋值给name、sex、age变量
name=$(input_fun 请输入你的姓名:)
sex=$(input_fun 请输入你的性别:)
age=$(input_fun 请输入你的年龄:)

#根据用户输入的性别进行匹配判断
#根据用户所输入的内容进行判断输入
case $sex in
	man|)
	if [ $age -ge 18 -a $age -le 25 ];then
		echo "哥们,娶媳妇了吗"
	elif [ $age -gt 25 -a $age -le 35 ];then
		echo "要担起家庭的责任"
	elif [ $age -lt 18 ];then
		echo "小伙子不错"
	else
		echo "$name先生,你油腻了吗?"

	fi
	;;
	woman|)
	echo "$name 小姐姐你好漂亮"
	;;
	*)
	echo "你是泰国来的吗?"
	;;

esac
15.写一个初始化系统的脚本
1)自动修改主机名(如:ip是192.168.0.88,则主机名改为server88.itcast.cc)
a. 更改文件非交互式 sed
/etc/sysconfig/network
b.将本主机的IP截取出来赋值给一个变量ip;再然后将ip变量里以.分割的最后一位赋值给另一个变量ip1
2)自动配置可用的yum源
3)自动关闭防火墙和selinux
#!/bin/bash
ip=`ifconfig eth1|sed -n '2p'|sed 's/.*addr:\(.*\) Bcast.*/\1/g'`
ip1=`echo $ip|cut -d. -f4`
#修改主机名
sed -i "/HOSTNAME=/c HOSTNAME=server$ip1.itcast.cc" /etc/sysconfig/network
echo "$ip       server$ip1.itcast.cc" >> /etc/hosts
#配置yum源
mount /dev/sr0 /mnt/ &> /dev/null
cat > /etc/yum.repos.d/local.repo <<-EOF
[local]
name=local yum
baseurl=file:///mnt
enabled=1
gpgcheck=0
EOF
#关闭防火墙和selinux
service iptables stop &>/dev/null
setenforce 0 &>/dev/null
#sed -i '/SELINUX=/c SELINUX=disabled' /etc/selinux/config
16.写一个搭建ftp服务的脚本,要求如下:
1)不支持本地用户登录
2) 匿名用户可以上传 新建 删除
3) 匿名用户限速500KBps
#!/bin/bash
#安装软件
read -p "请输入需要安装的软件:" s
yum -y install $s &>/dev/null
#备份配置文件
c=/etc/vsftpd/vsftpd.conf
cp $c $c.bak
#修改配置文件
sed -i '/local_enable/c local_enable=NO' $c
sed -i '$a anon_upload_enable=YES' $c
sed -i '$a anon_mkdir_write_enable=YES' $c
sed -i '$a anon_other_write_enable=YES' $c
sed -i '$a anon_max_rate=512000' $c
#启动服务
service vsftpd restart &>/dev/null
echo 'vsftpd启动成功'
#测试验证
chmod 777 /var/ftp/pub
touch /var/ftp/pub/1.txt
ip=`ifconfig eth1|sed -n '2p'|sed 's/.*addr:\(.*\) Bcast.*/\1/g'`
cd /tmp
lftp $ip <<EOF
cd pub
get 1.txt
put /etc/hosts
mkdir aaa
mkdir bbb
rmdir bbb
exit
EOF
[ -f /tmp/1.txt ] && echo "匿名用户下载文件成功" || echo "匿名用户下载文件失败"
[ -f /var/ftp/pub/hosts ] && echo "文件上传成功" || echo "文件上传失败"
[ -d /var/ftp/pub/aaa ] && echo "创建目录成功" || echo "目录创建失败"
[ ! -d /var/ftp/pub/bbb ] && echo "目录删除成功"
17.写一个自动检测磁盘使用率的脚本,当磁盘使用空间达到90%以上时,需要发送邮件给相关人员
#!/bin/bash
#Name:check_space.sh
#Desc:check disk space
/bin/df -h > df.txt
use=`cat df.txt|awk '{print $5}'|grep -o '[0-9]\+'`
for i in $use
  do
   [ $i -ge 90 ] && echo notice disk space:`grep $i df.txt` |mail tom
 done
rm -f df.txt
18.写一个脚本监控系统内存和交换分区使用情况
#!/bin/bash
OIFS=$IFS  初始化默认分隔符
IFS="\n"  定义默认分隔符
file=`free -m|sed -nr '/Mem|Swap/p'|awk '{print $4,$2}'`
mem=`echo $file|head -1`
swap=`echo $file|tail -1`
  echo $mem |awk '{if(($1/$2)*100<=50) print "物理内存空间需要留意,剩余"$1"M";else print "物理内存在正常范围"}'
  echo $swap |awk '{if(($1/$2)*100<=50) print "交换空间需要留意,剩余"$1"M";else print "交换空间在正常范围"}'
#!/bin/bash
#监控系统内存和交换分区使用情况
#/shell05/free.sh
#取当前时间
date >> /tmp/date.txt
#取物理内存free值
echo "Mem-free:`free -m | grep Mem | awk '{print $4}'`M" >> /tmp/mem-free.txt
#取缓冲区free值
echo "buffers/cache-free:`free -m | grep - | awk '{print $4}'`M" >> /tmp/buffers-free.txt
#取Swap区free值
echo "Swap-free:`free -m | grep Swap | awk '{print $4}'`M" >> /tmp/swap-free.txt
#将时间与相关数据重新写入新文件
paste /tmp/date.txt /tmp/mem-free.txt /tmp/buffers-free.txt /tmp/swap-free.txt > /tmp/free.txt
#发送监控邮件
mail -s "内存监控报告" root@localhost < /tmp/free.txt
19.输入一个IP地址,使用脚本判断其合法性:必须符合ip地址规范,第1、4位不能以0开头,不能大于255不能小于0
#!/bin/bash
#Valid IP
#/shell05/valid.sh
read -p "请输入要检查的IP:" IP
if echo $IP|grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}$" &>/dev/null;then
	a1=`echo $IP | cut -d. -f1`
	a2=`echo $IP | cut -d. -f2`
	a3=`echo $IP | cut -d. -f3`
	a4=`echo $IP | cut -d. -f4`
	if [ $a1 -gt 0 -a $a1 -le 255 -a $a2 -le 255 -a $a3 -le 255 -a $a4 -gt 0 -a $a4 -le 255 ];then
		echo "$IP available!"
	else
		echo "$IP not available!"
	fi
else
	echo "IP format error!"
fi
  • 15
    点赞
  • 134
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值