Linux&Shell宝典

Linux

介绍

image-20220728113114878

image-20220728113227441

内存

虚拟内存 = 物理内存 + 交换空间

交换空间 = 交换空间

当用户访问某一个程序内存时,需要访问物理内存,而不是交换内存,如果物理内存没有,而交换内存有,则会将交换内存中的程序

加载进物理内存供用户使用,同样,当一个程序长期未访问,内核会将物理内存中的程序放入到交换内存中,使用的时候再加载进来!

image-20220728110927654

GNU工具

GNU工具十分重要,是我们操作linux的关键桥梁,可以说我们写的所有linux命令和shell脚本都是通过GNU工具来处理linux内核!

image-20220728113258221

image-20220728113348161

GNU工具提供了很多种Shell,其中默认的是bash shell,也是我们要学习的

image-20220728113456329

Linux版本

image-20220728153509695

image-20220728153559040

核心发布版本大多数并不满足企业使用,故企业经常使用基于核心发布版本上构建的发行版:

如下CentOS就是基于Red Hat构建出的专用于企业的免费版本

image-20220728153659327

还有一种操作是电脑不用安装linux,而是将linux软件安装到一个移动硬盘上,电脑直接插入硬盘,开机时选择基于硬盘启动即可轻松使用linux操作系统,之前在哈尔滨出差时,那边的开发人员汪精忠就是用此方法使用linux:

image-20220728153925583

Shell

Shell本质

详细看:http://c.biancheng.net/view/706.html

image-20220801122405427

image-20220801143109410

shell连接其他程序不难理解,比如在shell中执行:java -cp xxx.jar 命令

实际上就是shell使用了java的命令

image-20220801144904813

Shell和bash关系

详细看:https://wangdoc.com/bash/intro.html

image-20220801163530178

image-20220801163540548

Shell 和 系统/bin 命令的异同

区别是:内部/外部命令

内部是shell自身提供的命令,例如exec history which命令等,这种命令which 查找是找不到的,因其是bash提供的shell内部命令,而外部就是 /bin/下linux内置的命令,当内部命令找不到时就会使用通过环境变量来使用外部命令,如果想判断一个命令是内部还是外部命令可以通过 type -a 命令查看

image-20220803114833988

image-20220803114714104

若要使用外部命令可以通过:/bin/pwd 实现

image-20220803114917064

文件系统

image-20220729143524315

基本命令

多个命令可以写在一行:

pwd; ll; who

image-20220729150222052

如果要查看目录下文件按照修改时间排序可以使用:ll -t [time的意思]。默认第一行为最近日期

image-20220809114620054

如果要按照日期倒序,可以使用 ll -rt [r是reverse]

image-20220809114731906

若要通过文件大小排序查看,则使用 ll -h , 如果倒序使用 ll -lr

-R 可以递归查看所有子目录及文件,十分方便

image-20220801112715721

image-20220801113837222

image-20220801111206490

image-20220801111240300

file是个挺强的命令,可以看到文件的编码和类型

image-20220801114256393

cat命令:

image-20220801115015064

image-20220801115118678

tail命令:

image-20220801115727537

image-20220801115955808

进程监控

ps

**ps命令:ps -ef **

image-20220801164740783

image-20220801164815114

小技巧:ps -ef --forest 可层级显示子父进程关系

image-20220801165105639

image-20220801165222653

top命令

image-20220802104229642

image-20220802103440759

image-20220802104006264

image-20220802104403902

top默认是CPU排序,若要想指定字段排序,需要按f键,此时会展示所有字段列表,上下键选择要排序的字段,然后按s键保存

后按q退出,此时就可以展示选中字段排序了

image-20220802110239061

image-20220802110259856

结束进程,开发的java程序应该有处理关闭进程的逻辑!如何优雅关闭进程看:https://blog.csdn.net/carlislelee/article/details/52688693

image-20220802110619646

top 高级用法

1、执行top -c ,显示进程运行信息列表

image-20221108195234800

2、top -Hp 10765 ,显示一个进程的线程运行信息列表

这点在用于排查java进程的时候尤其有用,例如通过top -c 发现第一个java进程[139270]占用了太多CPU,想看一下此进程下是哪些线程导致的问题时就可以用-Hp来查看

top -Hp 139270

image-20221108195522669

此时可以看到此进程下运行的所有线程,这里假设159483线程占用过多资源,此时就可以使用jstack来查看此线程的状态

磁盘管理

磁盘常用命令

查看物理机盘符情况:fdisk -l ; 需要结合lsblk命令查看,因为有些盘符是从大盘符上分出来的,如下的centos-root

image-20220802151419792

查看物理机磁盘大小:lsblk;可以看到磁盘依赖关系

image-20220802151219812

df -h 查看磁盘各个设备使用情况,此命令可以发现哪个目录导致磁盘满,十分有用

image-20220802143612532

du 命令用于查看特定目录磁盘的使用:当和df命令结合时,可以解决大部分磁盘满问题

image-20220802151955988

du -sh 命令可以查看当前目录和指定目录的使用大小,十分方便!

image-20220802151922111

du -sh * :查看当前目录所有文件或子目录使用大小,十分好用,可以看出是usr文件过大

image-20220802152821528

测试磁盘读写速度

一、测试写速度:
time dd if=/dev/zero of=/tmp/test bs=8k count=1000000
测试结果:1.3GB/s

image-20220802154626801

二、测试读速度:
time dd if=/tmp/test of=/dev/null bs=8k
测试结果:2.8GB/s

image-20220802154642675

三、测试读写速度:
time dd if=/tmp/test of=/var/test bs=64k
测试结果:1.3GB/s

image-20220802155149635

四、参数说明
①、time 有计时作用,dd 用于复制,从 if 读出,写到 of;

②、if=/dev/zero 不产生 IO,因此可以用来测试纯写速度;

③、同理 of=/dev/null 不产生 IO,可以用来测试纯读速度;

④、将/tmp/test 拷贝到/var 则同时测试了读写速度;

⑤、bs 是每次读或写的大小,即一个块的大小,count 是读写块的数量。

内存

# 以GB显示,如下物理机内存资源为125gb
$ free -g
total        used        free      shared  buff/cache   available
Mem:            125          48          26           0          50          76
Swap:             0           0           0

句柄数

# 查看文件句柄数
ulimit -n
# 查看有关句柄数的所有信息
ulimit -a
# 修改
sudo vim /etc/security/limits.conf

在这里插入图片描述

尾部增加:

*       soft    nofile  655350
*       hard    nofile  655350
*       soft    nproc   655350
*       hard    nproc   655350

CPU

# 总核数 = 物理CPU个数 X 每颗物理CPU的核数 
# 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数

# 查看物理CPU个数
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l

# 查看每个物理CPU中core的个数(即核数)
cat /proc/cpuinfo| grep "cpu cores"| uniq

# 查看逻辑CPU的个数
cat /proc/cpuinfo| grep "processor"| wc -l

排序-sort

sort命令默认按字符排序,若要改为数字排序需要加-n,若要降序需要-r

更多详细技巧看:https://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html

image-20220802161128072

搜索文本-grep

注意:grep后面跟要搜索的字符串,不加引号默认就是模糊匹配!如果想通过正则表达式查找需要用字符括起来!

grep命令是查找文本最常用的命令:grep aa test.txt

*grep aa .txt 通过通配符星查找到所有.txt结尾文件!可以通过通配符来查所有日志文件!十分好用

grep -v xxx 文件 去除包含xxx的行,这点在结合ps时非常好用

grep -n xxx 文件 通过-n找到匹配文本,显示其对应的行号

*grep -i aa .txt -C 5 通过-i忽略aa大小写并找到上下文5行

grep -m 10 aa xxx 查找符合aa条件的前10条,当匹配项很多的时候此命令非常好用

grep aa xxx | tail 查找符合aa条件的最后10条,结合管道符非常好用

grep “pattern” file.txt -A 2 查找匹配到的结果及其后2行

grep “pattern” file.txt -B 2 查找匹配到的结果及其前2行

*grep -e aa -e bb .txt -C 5 查找符合aa 或 bb 条件的行以及上下文5行

grep命令本身不提供AND功能。但是,但是我们可以使用管道符进行查找,十分方便:

grep “357e” pentagon/pentagon.log | grep tb_025ccc7986054544b675a9a776db5e5e

还可以使用 -E 正则选项可以实现AND操作:

*grep -m 10 -E '357e.tb_025ccc7986054544b675a9a776db5e5e’ pentagon/pentagon.log

image-20220824145346105

其他操作:

image-20220802162244608

在实战中grep还常常和ps 结合使用,例如:

$ ps -efl | grep 16364
1 S root     16364     2  0  80   0 -     0 worker 8月16 ?       00:00:00 [kworker/16:0]
0 S dig      19719 17485  0  80   0 - 28164 pipe_w 11:08 pts/2    00:00:00 grep --color=auto 16364

$ ps -efl | grep 16364 | grep -v grep
1 S root     16364     2  0  80   0 -     0 worker 8月16 ?       00:00:00 [kworker/16:0]

wc计数

wc在计数层面十分常见,使用频率较高
在这里插入图片描述
在这里插入图片描述

除了统计文件数量外,更多情况我们是结合管道符与其他命令配合使用,如下: 统计当前服务器打开文件数:

lsof

在查看服务器文件句柄数 和 查看端口进程时经常使用lsof命令
在这里插入图片描述

lsof 命令根据进程名称查看该进程打开的文件句柄数及使用情况,如下:
sudo lsof -p <pid>

-n 参数可以避免解析主机名和端口号在这里插入图片描述
如果只输入lsof命令,则会打印该服务器当前系统中打开的文件(或者说句柄)的信息
在这里插入图片描述

压缩

最常用的还是tar 命令:

解压: tar -zxvf xxx.tar.gz -C /tmp/xxx

压缩: tar -zcvf xxx.tar.gz a.txt b/

压缩时要压缩的文件在最后面空格分割

image-20220802173412573

image-20220802172651455

image-20220802172707541

jar包解压

unzip xxx.jar -d 解压到的目录下【此目录可以自动创建】

反编译class文件

javap xx.class

shell子父进程

image-20220802182817969

通过–forest可以很清楚的看到子父进程关系:

在生成子shell进程时,只有部分父进程的环境被复制到子shell环境中。这会对包括变量在内的一些东西造成影响,后面会详细讲

image-20220803103756950

创建子进程

()括号虽然可以创建子进程,但是会阻塞当前进程的使用,比如: (sleep 10)命令会让主进程阻塞10秒,若想解决此问题可以通过子进程后台运行的方式解决,后面会讲

image-20220803104117976

image-20220803104244531

进程后台运行

后台运行的核心在于 & 字符,可以将任务置于后台,此时可以通过ps查看

还有就是&的后台运行只会在当前主进程存在的基础上,如果此终端退出,则进程直接结束,故一般生产上会使用nohub命令

关于生产使用后台运行的方式详细看:https://app.yinxiang.com/shard/s34/nl/31250097/cbd56fcf-9f3c-42cd-a7e9-c63a1f34e694/

image-20220803112254690

image-20220803112203493

history命令

bash命令的历史记录是先存放在内存中,当shell退出时才被写入到历史文件中,文件位置为当前用户家目录下的.bash_history

当当前bash退出时就会写入到.bash_history文件中,若想强行写入需要执行: history -a选项

假如用户打开多个相同用户的bash窗口,多个窗口之间并不会共享历史数据,这是因为每个窗口的历史记录都在内存中,如果想要共享可以先通过history -a强制写入到历史文件,然后在别的窗口中通过history -n重新加载历史文件,即可完成复用

image-20220803140759894

image-20220803141000364

alias别名

别名命令十分好用,就像sql中的视图一样,将负责的命令起一个别名,可以大大减少我们命令的输入量,例如切换用户:

image-20220803123632711

通过alias命令可以看到内置的别名,可以发现常用的:ll 和 ls 也被内置了,其中ls成了ls --color=auto

这才导致我们使用ls看到的列表式有颜色的,如果使用原生的/bin/ls是没有颜色的

image-20220803123432922

image-20220803123315465

image-20220803123509470

创建别名:alias ll=‘ls -lF’

若别名已存在,则自动覆盖已存在的别名

注意:如果只到这一步,则此别名不是永久别名,终端退出后就会消失,永久别名方式参考下图:

image-20220803173649599

环境变量

全局&局部变量
前言

linux中氛围全局变量和局部变量,全局变量是可以在子父进程中共享,但是局部变量不可以共享

并且子进程中对全局变量的删除或者修改,不会影响父进程,注意这里指的删除修改并不是改配置文件,而是命令行中创建的全局变量!

注意:通过命令的方式创建的全局变量并不会永久保存,当终端关闭后就会消失!

注意:全局变量要大写,而局部变量要小写

image-20220803180154950

设置局部变量

命令:xx=xx

设置全局变量

设置命令:export xx=xx

子进程中对全局变量的删除或者修改,不会影响父进程,注意这里指的删除修改并不是改配置文件,而是命令行中创建的全局变量

删除环境变量

unset 变量名

PATH变量

path变量是用来查找命令的默认变量,当你输入一个外部shell命令例如spark-shell,系统就会从path变量中查找了

image-20220803184452135

image-20220803184641929

系统环境变量&用户环境变量
理解

若想设置永久环境变量就需要保存在文件中,文件由以下几种组成

image-20220803185541568

注意:/etc/profile是一定会加载的,至于其他文件则会根据当前shell情况来加载环境变量,大致分为三种

image-20220803185308891

/etc/profile文件中有for循环,去循环调用/etc/profile.d目录下的脚本文件,用来加载环境变量,故如果我们要创建系统环境变量,不要直接更改/etc/profile文件,而是应该在/etc/profile.d目录下新增脚本文件即可

image-20220804110512167

登录shell

在加载完/etc/profile文件后,登录shell就会获取用户目录下的其他文件,这里注意,如果找到其中一个文件,余下文件则会被忽略,这里没有.bashrc文件,这是因为bashrc文件是在.bash_profile文件中指定加载的!

image-20220804110810685

可以看出.bashrc文件是在.bash_profile文件中加载的!

image-20220803160150294

交互式shell

image-20220804111045521

非交互式shell【即子shell】

非交互式也就是子shell进程[sh xxx.sh],当用户通过 sh xxx.sh方式执行脚本任务时,其实就是子shell进程,此时子shell会获取父进程的所有全局环境变量!

image-20220803164446312

子shell验证

先上结论:在脚本内部通过 $() () 来执行的子shell是可以获取到局部变量的,只有像sh xxx.sh 这种是获取不到局部变量的

# 看一下脚本,根据外部aaa全局变量获取值
$ cat test.sh
#!/bin/bash
echo $aaa

bbb=$(ls /${
    aaa})
echo $bbb

# 此时定义一个局部变量
$ aaa=tmp

$ echo $aaa
tmp

# 然后执行,可以发现子shell没有获取到
$ sh test.sh

Applications Library System Users Volumes bin cores dev etc home opt private sbin tmp usr var

# 此时再设置成全局变量,可以证明子shell只能继承全局变量
$ export aaa=tmp

$ sh test.sh
tmp
com.adobe.AdobeIPCBroker.ctrl-hzxt com.apple.launchd.qisYqyWdTz com.sogou.inputmethod ev-6ca1cF ev-KDyAuV mysql.sock

但是注意,这里说的子shell是真的 ./ 这种启动一个子shell,如果只是当前脚本中的 $() `` 或者 (;😉 的子shell依然可以获取到局部变量!子shell无法更改父类的任何变量

# father脚本
$ cat father.sh
#!/bin/bash

dir=tmp
echo father: $(ls /$dir) # 使用子shell,然而这种子shell是可以获取到局部变量的

# ()括起来默认是使用子shell执行多个命令,尝试使用父shell局部变量;然而这种子shell是可以获取到局部变量的
(echo $dir; dir=asdf)
# 再次打印dir变量
echo $dir
# 执行真正的子shell,这种子shell不能获取到局部变量
sh ./child.sh

# child子脚本
$ cat child.sh
#!/bin/bash

echo child: ${dir}

# 执行命令
$ sh father.sh
father: com.adobe.AdobeIPCBroker.ctrl-hzxt com.apple.launchd.qisYqyWdTz com.sogou.inputmethod ev-6ca1cF ev-KDyAuV mysql.sock
tmp
tmp
child:
永久化系统变量和用户变量设置

image-20220803172409366

source命令

我们修改环境变量文件后的srouce, 其实就是将文件中的内容在当前环境执行一遍

source命令和sh 执行脚本文件不同,sh执行脚本是通过子shell执行脚本内容,而source是在当前bash环境下读取并执行FileName中的命令。

还有环境变量的区别,source中设置的全局环境变量在当前服务中生效,但如果是sh 启动脚本则是子进程创建全局环境变量,当子进程退出后全局变量失效,故source可以在当前进程中加载环境变量!也是我们常用的原因

image-20220803174740825

image-20220803174235257

比如新建一个文件:tsource

ls
aa=aa
bb=bb
pwd

然后执行:source tsource 或者 . tsource

image-20220803174542226

可以看出在source命令是读取文件中的每一样在当前环境中执行

文件权限

用户

image-20220804161415004

image-20220804161711397

创建用户的时候,如果不指定参数,则默认不会创建家目录!需要加上 -m参数,此外建议加上 -c 说明此用户的作用作用

常见命令:useradd -c xxx -m 用户名

默认创建时没有密码,需要通过passwd设置密码:passwd 用户名

image-20220804143330901

通过useradd -D 可以看到系统创建用户时默认参数!其中有意思的是skel,默认新建用户目录的文件

image-20220804161802265

image-20220804162951697

删除用户使用userdel命令,默认只会删除passwd中的数据,并不会删除用户目录!注意不建议使用-r 参数,因为别的用户可能使用此用户目录

image-20220804143159740

用户组

组密码极少情况才会用到,故可以忽略不计;

image-20220804163054210

当新建一个用户时就会产生一个默认组,组名和用户名保持一致,默认组在etc/group文件中不会显示用户列表,在使用useradd创建用户时可以指定将新用户加入某个组中,即一个用户可以加入多个组中!

image-20220804145021961

image-20220804163152848

删除组命令是:groupdel 详细配置通过man groupdel 查看

文件权限

权限更改主要就两个命令:chmod 和 chown

详细使用都可以通过man去查看

image-20220804163222119

父目录权限对子目录的影响

如果子目录child权限是777,但父目录user目录权限是700,则其他目录也无法进入到child目录下!

解决方案:只需要给user目录其他用户增加执行权限即可:chmod o+x user

image-20220804152307124

共享文件

比如我现在bdp/cluster目录下新建一个share共享目录,让所有属于docker组的用户都可以访问,其实很简单,要保证四点:

1、share目录要设置所属组为docker: chown bdp:docker share

2、share目录的组执行权限要改为s,这样在share目录下创建的任何文件或目录都将是docker所属组: chmod g+s share

3、需要访问share目录的用户要加入docker组:usermod -G docker xx用户名

4、share目录的父目录要有其他用户的执行权限,否则其他用户进不来:chmod o+x cluser ; chmod o+x bdp

image-20220804153713688

image-20220804152407074

完成以上操作后,share目录即可对所有docker组用户使用

软件安装及卸载

理解

linux软件安装主要分为两种,这里主要记录redhat的rpm安装方式

image-20220804182215415

image-20220804182229529

image-20220804182244499

yum软件仓库

yum和maven很像,也需要远程仓库,不然从哪下载对应的软件呢?通过yum repolist即可查看远程库

image-20220805112826127

image-20220805112900339

可以看到我们有clickhouse库,这是clickhouse官网提供的

yum查看软件

image-20220804182113600

yum安装

可以加 -y参数,回答全部问题为是

image-20220804182000728

yum更新

image-20220804182024959

yum卸载

image-20220804181937625

yum 依赖冲突

yum和maven很像,在下载一个软件时,如果该软件需要依赖其他软件时会一同下载,那么和maven一样,也可能会出现依赖冲突问题,解决方案如下:

image-20220805113142725

image-20220805113201169

vim编辑文件

基本知识

1、vim 编辑页面中会显示重要信息:会显示当前行数和已读百分比

2、此外,进入到编页面后,没有内容的行会用~波浪线替代:

image-20220805150500835

3、vim不支持并发编辑同一文件,会有冲突

image-20220805150605597

编辑技巧

1、快速定位到文件第一行:gg

2、快速定位到文件最后一行:G

3、快速定位到某一行:num G

4、显示行号::set nu

5、将更改后的文件保存到其他文件::w filename

6、命令模式下删除光标所在的字符:x

7、命令模式下撤回到上一步:u

8、编辑模式下撤回到上一步需要先退出编辑模式然后按:u

9、删除当前行:dd

10、删除指定数量的行:num dd

11、编辑模式下删除光标前的单词:control + w

12、删除所有行,进入命令模式: :%d

13、删除当前行到文件首行:dgg

14、删除当前行到文件末尾:dG

15、删除当前行字符到该行最后一个字符:d$

16、删除当前行字符到该行第一个字符:d0

16、剪切和粘贴,vim模式下删除操作就是剪切,只需按p键即可粘贴

17、复制:v可视模式

image-20220805160750695

18、命令模式下快速换新行并可以编辑:o

19、当查找某个字符串时,需要在命令模式下: /xxx 即可查到,通过n键进行下一个匹配项

20、关于文件内容替换,常用全部替换::%s/old/new/g

image-20220805165649367

21、vim中使用外部命令:!命令

22、通过python格式化文件

:%!python -m json.tool

diff查看两个文件的差异性

$ echo -e aa\\nbb\\ncc > diff1.txt
$ echo -e aa\\nbb\\ndd > diff2.txt

$ diff diff1.txt diff2.txt
3c3
< cc
---
> dd

实战查询进程 | 进程端口 | 进程jar包

1、查看8088端口是被哪个进程占用:lsof -i:8088

2、查看某个进程占用了什么端口:

netstat -nltp | grep pid

3、查看某个微服务名称的进程PID:

ps -ef | grep 微服务名称

4、查看进程详情:

jps -l

5、通过pid找到程序jar包所在目录:ll /proc/27998

B3970BA1-CB6D-437C-A75F-01928864CD30

find查找文件

find最常用来查找文件,故常用命令为: find 要查找的目录 -name “文件正则表达式”

 find ./bdp-dev/ -name  "*.c"

image-20220808142238098

image-20220808142352623

netstat

Linux netstat 命令用于显示网络状态。

利用 netstat 指令可让你得知整个 Linux 系统的网络情况。

而我们使用netstat主要是用来查看某个进程占用了什么端口:

netstat -nltp | grep pid

更多使用看:https://www.runoob.com/linux/linux-comm-netstat.html

SSH

ssh主要是用来登录其他服务器,有两种方式:

用户密码登录
# 用户密码的方式顾名思义需要知道用户密码
$ ssh [email protected]
passwd:
Last login: Tue Aug 23 18:44:55 2022 from kube-node5.stargraph
[bdp@kube-node5 ~]$
公钥登录

核心:A想登录到B,就需要将A的公钥发送给B;谁想连,谁发送

公钥登录就很简单,只需要去请求端中将.ssh/id_rsa.pub 中的数据复制到目标服务器的.ssh/authorized_keys中即可无密码登录
为了避免复制错误,我们采用ssh-copy-id 用户名@ip 命令; 两台服务器双向复制这样就可以互相登录

若只是单项,例如mac电脑只想单独登录远程服务,则只需要在mac电脑上将自己的公钥上传到目标服务器即可

# 请求宿主机
ssh-copy-id [email protected]
ssh 192.168.1.5
Last login: Tue Aug 23 19:10:08 2022 from 10.10.10.73

原理:

image-20220830173240895

SCP

scp是远程拷贝的常用命令,常用于本地复制文件或目录到远程服务器上
scp远程拷贝时需要输入用户名密码, 如果已经设置ssh无密码登陆了,则无需输入密码

# 拷贝文件:
scp test.log [email protected]:~/

# 拷贝目录:
$ scp -r logs/ [email protected]:~/
.DS_Store                                                                                                                                                                                                                                100% 6148   271.3KB/s   00:00
naming.log                                                                                                                                                                               
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Light Gao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值