Liunx-09日志管理

日志文件的作用

日志文件用于记录linux系统的各种运行信息的文件,相当于linux主机的日记,不同的日志文件记载了不同类型的信息,如Linux内核消息、用户登录事件、程序错误等。日志文件对于诊断和解决问题很有帮助,因为linux运行的程序通常把系统的消息和错误写入对应的日志文件,这样系统可以有据可查, 此外,当主机遭受攻击时,日志文件还可以帮助寻找攻击者留下的痕迹。

查看大日志文件

  1. 如果文件比较小的话,使用 vim 或者cat 直接查看,如果文件比较大的话,使用 Vim 会直接卡死。

2.如果想要查看正在滚动的日志文件。这个命令可以查看大文件。

tail -f file

Ctrl + c 终止 tail 命令
Ctrl + s 暂停 tail 命令
Ctrl + q 继续 tail 命令

3.如果文件比较大的话,也可以使用 less 命令

less file

但是使用上述命令的坏处是,默认打开的位置在第一行,并且当切换到实时滚动模式(按 F ,实现效果类似 tail -f 效果 )或者想要滚动到最底部的时候(按 G ),会卡在计算行数一段时间。如果卡的时间比较长的话,可以直接按 Ctrl + c ,取消计算行数。 我更推荐打开文件的时候使用 -n :不计算行号(打开大文件的时候很有用)。

less  -n file 
less +G -n  file  // 打开文件的时候,直接定位到文件的最底部,默认情况下是在首行
less +F -n  file  // 打开文件的时候,使用实时滚动模式,Ctrl + c  退出实时滚动模式,按 F 切回实时滚动模式
less +1000g  -n  file  // 直接定位到第 1000 行,一般你提前通过 grep 命令,定位到行数后,再使用这个命令
less +50p   -n  file  // 直接定位到 50% 的位置

在使用less的时候可以使用=查看文件显示内容

[root@cpgl log]# less yum.log #之后按=
yum.log lines 1-24/53 byte 1437/3180 45%  (press RETURN)
当前屏幕显示1-24行/该文件一共有53行,该文件一共有3180 byte , 当前位置在文件的 45% 处。

不使用 -n 的坏处是:当你使用 = 的时候,会计算出当前光标所在的位置,但是务必记得,大文件计算行数会阻塞一段时间

当然如果文件比较小,你想在使用 less 打开文件,并显示文件行数的话,可以使用 :

less -N file

4.如果你已经知道日志输出的关键字的话,使用 grep , 通常需要打印关键字前后的日志。

grep 'key word' log.txt -A 20 // 列出包括匹配行之后 20 的行。
grep 'key word' log.txt -B 20 // 列出包括匹配行之前 20 的行。
grep 'key word' log.txt -C 20 // 列出包括匹配行前后各 20 行。

大文件的话,grep 出来的数据比较多的话,你可以和 less 一起使用

grep  'world' copy.log | less

5.有时候需要将 tail 和 less 命令结合起来使用

tail -n +10000 | less // 从第 10000 开始,使用 less 查看。
tail -n 10000 | less // 查看倒数第 1000 行到文件最后的数据。

6.切割文件 有时候想把一个大文件进行分割成多个小文件.(使用split 的时候,也是蛮耗时的,但是这里仍然提供一种解决方法吧) 按文件大小分割:

split -b 600m copy.log

分割后的文件默认是以 x 开头,例如我上述命令分割后文件为:

$ ls  x*  // 这里 * 是通配符,即列出以 x 开头的文件。
xae xad xac xab xaa

当然你可以按行数分割,具体的命令格式如下 :

split [选项]... [要切割的文件] [输出文件前缀]  // 输出文件前缀为可选项
	-a, --suffix-length=N | 使用长度为 N 的后缀 (默认 2)
	-b, --bytes=SIZE | 设置输出文件的大小。支持单位:m,k
	-C, --line-bytes=SIZE | 设置输出文件的最大行数。与 -b 类似,但会尽量维持每行的完整性 
	-d, --numeric-suffixes | 使用数字后缀代替字母
	-l, --lines=NUMBER | 设备输出文件的行数
	-help | 显示版本信息
	-version | 输出版本信息

7.如果你已经知道需要的内容在第几行,但是想要显示指定行数之前或者之后的行。例如你想显示 499999900 到 500000000 这100 行的内容。 推荐使用这个方法

head -500000000 file | tail  -100

其中 head -500000000 : 显示文件的前 500000000 行。

tail -100 :显示最后 100行。 两者结合起来就是在前 500000000 行中显示后 100 行,即显示 499999900 到 500000000 这100 行的内容。

或者使用 sed 命令:

sed -n '500000000q;499999900,500000000p'  file

其中 -n 与 p : 表示只打印符合条件的行。 500000000q; : 表示当执行到第 500000000 行的时候停止执行。 如果不使用 500000000q; sed 默认会浏览整个文件。 499999900,500000000 : 表示499999900 到 500000000 行。其中 , 逗号表示范围。 整体结合起来就是打印 499999900 到 500000000 行,但是执行到第 500000000 行就不要再执行了。

或者使用 awk 命令

awk 'NR>=49999991 && NR<=50000000{print} NR==50000001{exit}' file

三者的执行效率

time (head -500000000  copy.log  | tail -100) > /dev/null
real    0m9.456s
user    0m8.854s
sys 0m3.501s

time (sed -n '500000000q;499999900,500000000p' copy.log) > /dev/null
real    0m25.968s
user    0m25.111s
sys 0m0.833s

time (awk 'NR>=499999900&& NR<=500000000{print} NR==500000001{exit}' copy.log) > /dev/null
real    1m4.743s
user    1m3.824s
sys 0m0.906s

与其说是查看大日志文件的方法,不如说是将 grep/awk/sed/head/less/tail 多个命令结合起来的方法。

其实最重要的不是怎么看大文件,还是在程序运行时候,就要对日志文件进行归档整理,例如,每天一次归档,或者每满 500M 就归档。 当然大公司会用例如 ELK 之类的日志处理系统。

常见的日志种类

内核及系统日志

主配置文件/etc/rsyslog.conf

日志默认存放目录 /var/log

下面是常见的日志说明

  • Messages 内核消息及各种应用程序的公共日志信息,包括启动、I/O错误、 网络错误
  • cron 记录crond计划任务服务执行情况
  • Secure 用户认证相关的安全事件信息
  • Dmesg 引导过程中的各种时间信息
  • maillog 进入或发出系统的电子邮件活动
  • lastlog 每个用户最近的登录事件
  • wtmp 每个用户登录注销及系统启动和停机事件
  • btmp 失败的、错误的登录尝试及验证事件
  • yum.log 包含使用yum安装的软件包信息
  • boot.log 包含系统启动时的日志

用户日志

用于记录Linux系统用户登录及退出系统的相关信息,包括用户名、登录的终端、登录时间、来源主机、正在使用的进程操作等。

存放位置: /var/log/wtmp. /var/log/btmp、 /var/log/lastlog

查询命令: users、who、w、last、 lastlog、 lastb等

users: 只是简单的输出当前登录的用户名, 每个显示的用户名对应一个会话。

who: 报告当前登录到系统的每个用户的信息,包括用户名,终端,登录日期,远程主机

w: 显示当前操作系统的每个用户及其远程所运行的进程信息

last: 用于查询成功登录到系统的用户记录,最近的登录情况在最前面。 通过last命令可以及时掌握Linux主机的登录情况,若发现未经授权的用户登陆过,则表示当前主机可能已被入侵。

 -a :把从何处登录系统的主机名称或IP地址,显示在最后一行 
 -d :将IP地址转换成主机名称 
 -f :记录指定文件 
 -R :不显示登入系统的主机名称或IP地址 
 -x :显示系统关闭,重新开机,以及执行等级的改变等 
 -n : n代表数字,表示最近n次登录的记录

lastlog :用于显示系统中所有用户最近一次登录信息

lastb :用于显显用户错误的登录列表,此指令可以发现系统的登录异常。如登录的用户名错误,密码不正确等情况都会记录在案,登录失败的情况属于安全事件,因此消失可能有人在尝试破解密码。除了使用lastb命令以外,可以直接从安全日志文件/var/log/secure中获得相关信息。

ac: 查看用户连接时间

-p :查看每个用户的连接时间
-a :查看所有用户的连接时间
-d :查看用户每天的连接时间

程序日志

​ 有些应用程序会选择独立管理一份日志文件 ,而不是交给rsyslog服务管理,用于记录本程序运行过程中的各种事件信息。于这些程序只负责管理自己的日志文件,因此不同程序所使用的日志记录格式也会存在较大的差异。

​ 一般yum安装的应用,日志还是在/var/log/目录下面,可能有自己专属的目录,不过一般是可以修改日志位置的,二进制编译一般是编译时候指定的。

rsyslog配置

Linux日志机制的核心是rsyslog守护进程,该服务负责监听Linux下的日志信息,并把日志信息追加到对应的日志文件中,一般在/var/log目录下。它还可以把日志信息通过网络协议发送到另一台Linux服务器上,或者将日志存储在MySQL或Oracle等数据库中。本文将简要介绍一下rsyslog的配置文件的配置,以及如何使用logrotate进行日志滚动。

rsyslog的配置文件为/etc/rsyslog.conf和/etc/rsyslog.d/目录内的文件。 rsyslog.conf文件配置了rsyslog守护进程在哪里保存日志信息。

[root@cpgl log]# grep -Ev "^$|^#" /etc/rsyslog.conf   
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command) #加载imuxsock模块
$ModLoad imjournal # provides access to the systemd journal  #加载imjournal模块
$WorkDirectory /var/lib/rsyslog
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat  #默认模板RSYSLOG_TraditionalFileFormat
$IncludeConfig /etc/rsyslog.d/*.conf
$OmitLocalLogging on
$IMJournalStateFile imjournal.state
*.info;mail.none;authpriv.none;cron.none                /var/log/messages
#表示info级别的任何消息都发送到/var/log/messages日志文件,但邮件系统、验证系统和计划任务不发送(none表示禁止)
authpriv.*                                              /var/log/secure
#认证信息发送到/var/log/secure
mail.*                                                  -/var/log/maillog
#邮件系统发送到/var/log/maillog
cron.*                                                  /var/log/cron
#cron.* /var/log/cron 表示所有级别的cron信息发到/var/log/cron文件
*.emerg                                                 :omusrmsg:*
#*.emerg * 表示emerg错误级别(危险状态)的所有消息类型发给所有用户
uucp,news.crit                                          /var/log/spooler
local7.*                                                /var/log/boot.log

其余配置
#$ModLoad imudp.so       #加载imudp模块支持udp
#$UDPServerRun 514       # 允许514端口接收使用UDP协议转发过来的日志
#$ModLoad imtcp.so       #加载imtcp模块支持tcp
#$InputTCPServerRun 514  # 允许514端口接收使用TCP协议转发过来的日志

rsyslog配置的规则是(选择器+动作)

每个规则行由两部分组成,selector部分和action部分,这两部分由一个或多个空格或tab分隔,selector部分指定源和日志等级,action部分指定对应的操作。

选择器(SELECTORS)

selector也由两部分组成,消息源和日志级别,由点号.分隔。第一部分为消息源或称为日志设施,第二部分为日志级别。 下面给出一个rsyslog.conf的例子:

  • 消息类型
auth(security), authpriv: 授权和安全相关的消息
kern: 来自Linux内核的消息
mail: 由mail子系统产生的消息
cron: cron守护进程相关的信息
daemon: 守护进程产生的信息
news: 网络消息子系统
lpr: 打印相关的日志信息
user: 用户进程相关的信息
uucp: unix to unix copy, unix主机之间相关的通讯
local0 to local7: 保留,本地使用
  • 日志错误级别
日志错误级别错误级别:(8)debug,info,notice,warning|warn;err|error;crit,alert,emerg|panic
根据日志信息的重要程度不同,分为不同的级别 **数字级别越小,优先级越高,消息越重要
级别 英文表示 意义
0 EMERG(紧急) 导致主机系统不可用的情况
1 ALERT(警告) 必须马上采取解决措施
2 CRIT 严重 比较严重的情况
3 ERR 错误 运行出现错误
4 WARNING 提醒 提醒用户的重要事件
5 NOTICE 注意 不会儿影响系统,提醒用户
6 INFO 信息 一般信息
7 DEBUG 调式 程序调式
8 None 没有 不做记录
  • 日志级别设置
.xxx: 表示大于等于xxx级别的信息
.=xxx:表示等于xxx级别的信息
.!xxx:表示在xxx之外的等级的信息

选择器使用注意事项

#例子1
mail.crit,*.err					/var/log/syslog_err.log
# 这样的情况,最终的结果还是会把mail的err级别日志输出到syslog_err.log

#例子2
mail.!warn						/var/log/mail.log
# 看起来是将mail的warn以下级别的日志输出到/var/log/mail.log,其实不然,你会发现你什么也得不到。
# 官方的解释是,感叹号(就是形似这个的符号 ==> !) 就是个过滤器,你得先有东西,才能去过去,比如:
mail.*;mail.!warn	

动作(ACTION)

action是规则描述的一部分,规则用于处理消息。总的来说,消息内容被写到一种日志文件上,但也可以执行其他动作,比如写到数据库表中或转发到其他主机。

动作域:file,user,console,@remote_ip

#忽略,丢弃
local3.*   ~    # 忽略所有local3类型的所有级别的日志

#执行脚本
local3.*    ^/tmp/a.sh      # ^号后跟可执行脚本或程序的绝对路径

#过滤日志, 由:号开头
:msg, contains, “error” /var/log/error.log
:msg, contains, “error” ~         # 忽略包含error的日志
:msg, contains, “user nagios”   ~
:msg, contains, “user kadefor”   ~
:msg, contains, “module-alsa-sink.c: ALSA woke us up to write new data to the device, but there was actually nothing to write” ~
local3.*    ~
&   ~       # 忽略所有的日志

转发到远程机器

有3种方式转发消息:

  • 传统方式的UDP传输,有损耗
  • 基于TCP明文的传输,只在特定情况下丢失信息,并被广泛使用
  • RELP传输,不会丢失信息,但只在rsyslogd 3.15.0及以上版本中可用

写法:

  • UDP 在主机名前加"@"
  • TCP 在主机名前加"@@"
  • RELP 在主机名前加":omrelp:"

例:

*.* @192.168.0.1    #将所有日志信息通过UDP协议发送到192.168.0.1
如果要修改为非514的端口, 需要设置selinux
只要在rsyslog.conf中加入
*.* @192.168.0.10          #UDP
*.* @192.168.0.10:10514    #带端口号
*.* @@192.168.0.10         #TCP
*.* :omrelp:192.168.0.10   #RELP 

模板(template)

rsyslog属性

常用的rsyslog属性,其他额外的信息可以使用man rsyslog.conf 命令去查看rsyslog.conf手册。

msg: 即消息源进程调用syslog家族函数,所传递的文本信息
rawmsg: 从套接字接收到的消息完全相同。应该对调试有用。
HOSTNAME:来自消息的主机名
FROMHOST:接收到消息的系统的主机名(在中继链中,这是直接在我们面前的系统,但 不一定原始发件者)。
syslogtag:来自消息的标签,通常来说,要么是消息源进程的用户名。
programname:标签的“静态”部分,通常%programname%是输出的值和%syslogtag%是相同的。
PRI:消息的下划线部分-未解码(单值)
syslogseverity-text:消息等级的严重性-文本形式
timegenerated:接收消息时的时间戳。
timereported:消息中的时间戳。 解析精度取决于消息中提供的内容(在大多数情况下,仅精确到秒)
TIMESTAMP:timereported的别名
PROTOCOL-VERSION:协议版本
以$符号开头的属性是所谓的系统属性。 这些不是消息产生的,而是Linux系统内部产生的。

$NOW当前日期戳,格式为YYYY-MM-DD
$YEAR当前年份(4位数字)
$MONTH当前月份(2位数字)
$DAY月的当前日期(两位数)
$HOUR当前的军事时数(24小时)(2位数字)
$MINUTE当前分钟(2位数字)

模板允许你指定日志信息的格式,可用于生成动态文件名,或在规则中使用。其定义如下所示,其中TEMPLATE_NAME是模板的名字,PROPERTY是rsyslog本身支持的一些属性参数。

#示例模板
$template TEMPLATE_NAME,"text %PROPERTY% more text", [OPTION]
#设置模板名为 myFormat  格式为 %rawmsg%\n
$template myFormat,”%rawmsg%\n”  

新版定义模板的方式

#自定义模板
template(name="myFormat" type="list"){
  property(name="$now")
  constant(value=" ")
  property(name="timegenerated")
  constant(value=" ")
  property(name="hostname")
  constant(value=" ")
  property(name="programname")
  constant(value=" ")
  property(name="msg" spifno1stsp="on")
  property(name="msg" droplastlf="on")
  constant(value="\n")
}

模板定义及使用的例子

$template DynamicFile,"/var/log/test_logs/%timegenerated%-test.log"

*.* ?DynamicFile

规则中绑定模板

在日志规则的动作字段,按照如下所示,添加一个:<模板名称>,其他步骤跟上面一个示例一致。

local1.*        /var/log/test.log:myFormat   #myFormat这个就是设置的模板,前面必须定义

当然下面还有一条等效的规则,如下所示

local1.*     action(type="omfile" file="/varlog/test.log" template="myFormat")

输出模板

输出模板为用户可能想要的输出类型提供了保护,在规则中使用前要先定义.其定义如下所示,其中NAME指定输出频道的名称,FILENAME指定输出文件,MAXSIZE指定日志文件的大小,单位是bytes, ACTION指定日志文件到达MAX_SIZE时的操作。

$outchannel NAME, FILE_NAME, MAX_SIZE, ACTION

在规则中使用输出频道按照如下的格式:

FILTER :omfile:$NAME

下面给出使用输出频道的一个例子:

$outchannel log_rotation, /var/log/test_log.log, 104857600, /home/aaa/log_rotation_script

*.* :omfile:$log_rotation

日志测试

logger -p local3.info 'KadeFor is testing the rsyslog and logger'  #logger 命令用于产生日志

logrotate配置

日志转储(rotate)

储方式可以设为每年转储、每月转储、每周转储、达到一定大小转储。

在Linux系统,经常使用**“logrotate”工具进行日志转储,结合cron**计划任务,可以轻松

实现日志文件的转储。转储方式的设置由**“/etc/logrotate.conf”**配置文件控制

[root@cpgl ~]# cat /etc/logrotate.conf 
# see "man logrotate" for details
# rotate log files weekly
weekly  #设置每周转储

# keep 4 weeks worth of backlogs
rotate 4  #最多转储4次

# create new (empty) log files after rotating old ones
create  #当转储后文件不存储时创建它

# use date as a suffix of the rotated file
dateext # 指定切割文件的后缀名,这里以日期为后缀名

# uncomment this if you want your log files compressed
#compress  #以压缩方式转储

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d  #其他日志文件的转储方式,包含在该目录下

#minsize 1M # 文件容量超过这个值时才进行切割

# no packages own wtmp and btmp -- we'll rotate them here
/var/log/wtmp {
    monthly   #每月转储
    create 0664 root utmp  #转储后文件不存在时创建它,文件所有者为root所属组为utmp,对应的权限为0664
        minsize 1M   # 文件容量超过1M时才进行切割
    rotate 1 #转储一次
}

/var/log/btmp {
    missingok  #如果日志丢失, 不报错
    monthly
    create 0600 root utmp
    rotate 1
}

# system-specific logs may be also be configured here.

转储(rotate)例子

#为/var/log/httpd/access.log和/var/log/httpd/error.log日志设置转储参数。转储5次,转储时发送邮件给root@localhost用户,当日志文件达到100KB时才转储,转储后重启httpd服务
/var/log/httpd/access.log /var/log/http/error.log{
	rotate 5
	mail root@localhost
	size=100k
	sharedscripts #表示切换时脚本只执行一次
	systemctl restart httpd
	endscript
}
#rsyslog的日志文件每天被rotated,保留7份旧的日志。其他的日志文件每周进行一次rotate,并保留4份旧的日志。
/var/log/mail.info
/var/log/mail.warn
/var/log/mail.err
/var/log/mail.log
/var/log/daemon.log
/var/log/kern.log
/var/log/auth.log
/var/log/user.log
/var/log/lpr.log
/var/log/cron.log
/var/log/debug
/var/log/messages  #  指定多个文件, 如果有特殊字符需要用单引号
{
    rotate 4
    weekly
    missingok #如果日志丢失, 不报错
    notifempty
    compress # 全局设置, 压缩
    delaycompress
    sharedscripts # 共享脚本. 下面的postrotate脚本只运行一次.
    postrotate # 表示rotate后执行的脚本
    	systemctl restart  rsyslog
    endscript #表示脚本结束
}

自定义日志处理

#将所有类型错误级别为info的日志转储到/var/log/test.log日志文件中,并设置/var/log/test.log达到50KB后进行转储,转储10次,转储时压缩,转储后重启syslog服务
#1.修改/etc/syslog.conf文件使得如下:
[root@cpgl log]#tail -1 /etc/rsyslog.conf //查看该文件的最后一行
*.info /var/log/test.log

#2.重启rsyslog服务: 
[root@cpgl log]# systemctl restart rsyslog

#3.创建/etc/logrotate.d/test.log日志转储参数配置文件
[root@helle ~]# cat /etc/logrotate.d/test.log
/var/log/test.log{
        rotate 10
        size = 50k
        compress
        postrotate
          /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
          # 可查看/etc/logrotate.d/下的配置文件
        endscript
}

#4.查看文件/etc/cron.daily/logrotate确保如下
[root@cpgl cron.daily]# cat /etc/cron.daily/logrotate 
#!/bin/sh

/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

#查看转储后的文件
[root@cpgl log]# pwd
/var/log
[root@cpgl log]# ls test.log*  #结果等要转储的时候会发现压缩文件和原本的test.log文件
test.log  test.log-20220924.gz

转储(rotate)测试

logrotate -f /etc/logrotate.conf  –强制轮转
logrotate -vf /etc/logrotate.conf   –再加一个-v参数查看轮转的过程

日志发送与接收

配置服务端(接收)

#配置服务端(接收)
vi /etc/rsyslog.conf        #在文件开始加上,同时确保514端口能够被客户端用tcp访问
$ModLoad imtcp.so              # needs to be done just once #使用tcp方式
$InputTCPMaxSessions 500    # tcp接收连接数为500个
$InputTCPServerRun 514      # tcp接收信息的端口
$template logformat,”%TIMESTAMP:::date-mysql% %FROMHOST-IP%%msg%\n”     # 定义一个名为logformat模板, 为信息加上日志时间
$template DynFile,”/var/log/tlog%$year%%$month%%$day%.log”     # 定义日志文件的名称,按照年月日
:rawmsg, contains, “sdns_log” ?DynFile;logformat    # 把rawmsg(也可以使用msg)日志中包含sdns_log标志的信息写到DynFile定义的日志文件里
:rawmsg, contains, “sdns_log”  ~   # 这个表示丢弃包含sdns_log标志的信息, 一般都加上它, 以免多个日志文件记录重复的日志

———————————————————————
补充:
如果要把不同服务器发送过来的日志保存到不同的文件, 可以这样操作:
:fromhost-ip, isequal, “192.168.0.160″ /var/log/host160.log
:FROMHOST-IP, isequal, “192.168.0.161″ /var/log/host161.log
:FROMHOST-IP, startswith, “192.168.1.” /var/log/network1.log
:FROMHOST-IP, startswith, “192.168.2.” /var/log/network2.log

配置客户端(发送)

#配置客户端(发送)
vi /etc/rsyslog.conf  #在文件开始加上
#把包含sdns_log的信息通过tcp发到xxx @@表示tcp @表示udp
:rawmsg, contains, “sdns_log”       @@xxx     # 默认514端口
#这个表示丢弃包含sdns_log标志的信息,防止这个信息写到本机的/var/log/message
:rawmsg, contains, “sdns_log”       ~
#测试

———————————————————————
在客户端上执行
logger -p user.info “sdns_log 34334″
在服务端的/var/log/目录里是否有tlog*日志产生
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值