在线man: http://www.linux.com/linux-man-pages
计算机硬件五大单元:
1、输入
2、输出
3、控制单元
4、算数逻辑单元
5、内存
CPU种类
1、RISC(Reduced Instruction Set Computing),SPARC、PowerPC、ARM
2、CSIC(Complex Instruction Set Computer),AMD、Intel、VIA等x86架构CPU
Intel主板芯片组
北桥:负责连接速度较快的CPU、内存与显卡
南桥:负责连接数独较慢的周边接口,包括硬盘、USB、网卡等
AMD与Intel不同地方在于,内存是直接与CPU通信而不通过北桥
CPU外频:指的是CPU与外部组件进行数据传输/运算时的速度,倍频则是CPU内部用来加速工作性能的一个倍数,两者相乘得出CPU频率
例如,CPU频率是3.0GHz,外频是333MHz,则 倍频就是9(3.0G=333M*9,其中1G=1000M)
如果想要超频,可以将外频333MHz调成400MHz,但可能会造成不稳定
系统内核(Kernel)
其实是一组程序,参考硬件规格写成,重点在于管理计算机所有活动以及驱动系统中的所有硬件,内核程序防止到内存中的区块是受保护的,并且开机之后就一直常驻于内存当中。
1、系统调用
2、程序管理
3、内存管理
4、文件系统管理
5、设备驱动
操作系统
内核与其提供的接口工具,也可包含相关的用户应用软件。例如windows的一大堆API
Linux就是一套操作系统,由于是开源的,所以具有非常高的“移植性”,N多人来帮助修改兼容
GPL开源协议并不代表没有商业空间,自由软件是可以销售的,软件是开源的,但是其中的说明,售后,工具等附加价值就是要收费的了,毕竟软件不是每个人都会写。
Linux系统中,所有文件硬件都被当成一个文件来对待
磁盘每个扇区为512bytes,第一个扇区主要记录了MBR和分区表
MBR:主引导分区,有446bytes
分区表:记录整块硬盘分区的状态,有64bytes,由于只有64bytes,所以只能容纳4个分区,分为主/扩展分区,扩展分区不能被格式化,要继续分区成逻辑分区
逻辑分区数量,linux中,IDE最多有59个(5到63号),SATA最多有11个(5到15号)
Ctrl+Alt+F1~F6 文字界面登录tty1~6终端,F7是图形界面
在Linux中root的默认提示符为#,一般身份的提示符为$,~代表用户的主文件夹。
一般最好设置两个账号,一个一般账号,需要动用系统功能修改时,才会转换身份成为root
基本命令操作:
用户用户组,账号管理:
groups:有效与支持用户组查看,第一个输出为有效用户组(新建文件默认用户组)
newgrp:有效用户组的切换
useradd:新建用户
passwd:密码设置
chage:详细密码参数显示
usermod:用户参数调整
userdel:删除用户相关数据
finger:查阅用户信息
chfn:修改用户个人信息
chsh:修改用户的shell
groupadd:添加用户组
groupmod:修改用户组参数
groupdel:删除用户组&
gpasswd:用户组管理员功能(root管理员没时间,你来)
setfacl:启动ACL后,单独设置针对某一用户或用户组来对文件设定特定的权限需求
getfacl:获取启动ACL后的权限
su:身份切换
sudo:用其他身份执行命令,并不切换
visudo:编辑其他账户可以通过sudo执行root权限
w/who:查询目前已登录在系统上的用户
lastlog:获取每个账号的最近登录时间
write:给别的用户发消息
mesg:开启关闭接受其他用户发过来的消息
wall:对所用用户广播
pwck:检查/etc/passwd配置文件信息
文件目录:
切换目录:cd
显示目前所在目录:pwd(print working directory)
新建目录:mkdir
mkdir -p test1/test2/test3,创建多层目录
mkdir -m 711 test,创建的时候附加权限
删除“空”目录:rmdir
删除目录:rm -r test
查看文件与目录:ls
复制:cp
移动:mv
取得路径文件名:basename
取得路径目录名:dirname
chattr:设置文件的隐藏属性(只能在Ext2/Ext3的文件系统生效)
lsattr:显示文件隐藏属性
文件查阅:
cat(concatenate):从第一行开始显示问文件内容
tac:从最后一行开始显示,与cat相反
nl:显示的时候,顺便输出行号
more:一页一页的显示内容
less:与more类似,可以翻页!
head -n 10:只看头n行
tail:只看结尾几行
od:以二进制方式读取文件内容
touch:修改文件时间或创建新文件
umask -s:默认权限,分数的意思是“该默认值需要减去的权限”,0022就是022意思是group和others被去掉了写权限,r4、w2,x1
file:查看文件类型
which:根据$path路径去查找“执行文件”的文件名
whereis:查找特定文件,利用数据库,查找相当快
locate:查找文件,根据/var/lib/mlocate内的数据库查找,updatedb用来更新这个数据库,不然新建文件找不到,默认每天会更新一次
find:无敌查找命令,只不过比较慢,参数很多
pringf:格式化打印
awk:数据处理
diff:文件比较(纯文本)
patch:使用diff生成的.patch来打补丁
cmp:主要利用“字节比较”,也可以比较二进制
pr:文件打印准备,比较复杂
文件系统:
df:列出文件系统的整体磁盘使用量
du:评估文件系统的磁盘使用量(常用语评估目录),会直接到文件系统去查找所有的文件数据。
ls -l /lib/modules/$(uname -r)/kernel/fs:
查看Linux支持的文件系统
cat /proc/filesystems:
查看目前已加载到内存中支持的文件系统
dumpe2fs:查看文件系统信息。
ln -[sf]:连接文件
fdisk [-l]:磁盘分区(只有root才能执行)
mkfs [-t 文件系统格式] 设备文件名:磁盘格式化
fsck:[-t 文件系统] [-ACay] 设备名称:检测文件系统是否出错
badblocks -[svw] 设备名称:检测硬盘或软盘扇区是否有坏道
mount:挂载磁盘
umount:卸载磁盘
mknod:磁盘参数修改
parted:分区2TB以上的磁盘
mkisofs:制作镜像文件
cdrecord:光盘刻录工具
压缩打包:
compress:已过时的压缩
gzip:可揭开compress,zip,gzip等软件压缩文件
bzip2:比gzip要好的压缩
tar:类似winrar直接打包压缩整个目录,上面的不方便弄。
备份恢复:
dump:-j参数可以降低备份占用空间
restore:恢复备份
dd:可以读取磁盘设备内容(扇区读取),其他指令做不到啊!
cpio:需要搭配find进行备份,它可以备份任何文件
bash shell:
sh:执行,追踪,调试脚本
source:在父进程中运行脚本
test:功能测试
type:查询命令是来自于外部,还是内置于bash
\[Enter]:如果指令太长,这样可以换行继续输入
echo $PATH:输出变量
export:变量输出为环境变量
unset:删除变量
env(environment):列出目前shell环境下的所有环境变量
set:查看所有变量
echo $$:显示当前shell的pid,$也是变量哟
echo $?:显示上一个命令的执行结果,0为正常,其他为错误代码
read:读取来自键盘输入的变量
declare:声明变量的类型
ulimit:限制用户的系统资源,包括可打开的文件数量,可使用的CPU时间,可使用的内存总量。
alias:别名
unalias:取消别名
history:查询曾经使用过的命令
source:读取环境配置文件
stty:终端机环境设置
cmd1&&cmd2:1对,2执行,1错,2不执行
cmd1||cmd2:1对,2不执行,1错,2执行
管道命令
cut:切割信息
grep:根据正则表达式,分析信息,提取显示
sort:排序信息
uniq:将重复的行删掉,只显示一个
wc:显示文件字数,行数,字符数
tee:双向重定向,转存输出到另一个文件,而其他命令同时处理
tr:删除一段信息中的文字,或者替换
col:将tab转换成对等空格,文字有/时,保留/最后接的字符
join:将两个文件中相同数据那一行加在一起
paste:与join类似直接将两行贴在一起,以[TAB]隔开
expand:将[tab]转换成空格
split:文件切割
xargs:参数带换,很多命令不支持管道命令,可以用xargs来提供该命令引用输入只用。
sed:可以分析输入,也可以将数据进行替换,删除,新增等
工作调度
at:单一工作调度,最好使用绝对路径来执行命令
atq:查询主机有多少个at工作调度
atrm:删除工作调度
batch:利用at执行任务,但是CPU负载小于0.8时,才执行工作任务
crontab:循环执行工作调度
anacron:唤醒停机期间的工作任务
进程管理
jobs:查看目前的后台工作状态
fg:将后台工作拿到前台处理
bg:让工作在后台下的状态变成运行中
kill:管理后台中的工作
nohup:在脱机或注销之后,还能继续工作任务
ps:将某个时间点的进程运行情况选取下来
psaux:查看系统所有进程
top:动态查看进程的变化
pstree:进程树
nice:新执行的命令即给予新的nice值
renice:已存在进程的nice重新调整
free:查看内存使用情况
uname:查看系统与内核相关信息
uptime:查看系统启动时间与工作负载
netstat:跟踪网络
dmesg:分析内核产生的信息
vmstat:检测系统资源变化
fuser:通过问卷查找出正在使用该文件的程序
lsof:列出被进程所打开的文件名
pidof:找出某个正在执行的进程PID
ldd:查看某个程序的动态函数库支持状态
其他:
Tab按键:自动完成
Ctrl+c:中断指令
Ctrl+d:结束输入,相当于Exit
显示日期:date
显示日历:cal 10 2015
计算器:bc (scale=3设置小数)
简单编辑器:nano ^为ctrl,M为Alt
查看有谁在线:who
查看网络的联机状态:netstat -a
查看后台执行的程序:ps -aux
关机:shutdowm -h 10 '关机'
#会告诉大家,这机子10分钟后关机,显示在登陆者的屏幕前方
重启:reboot
切换模式:init 0关机3纯命令行5含有图像界面6重启
查看实际内核版本:uname -r
查看distribution版本:lsb_release -a
dos2UNIX/UNIX2dos:转换断行格式,windows为CRLF,linux只有LF
iconv:编码转换
locale:语言设置与显示列表
在线帮助:man 或者 info(用?查看命令)
空格往下翻页
/string 向下查询字符串
?string 向上查询字符串
n,N 向下,向上继续查询
代号
1 用户在shell环境中可以操作的命令或可执行文件
2 系统内核可调用的函数与工具等
3 一些常用函数与函数库,大部分为C的函数库
4 设备文件的说明,通常在/dev下的文件
5 配置文件或者是某些文件的格式
6 游戏
7 惯例与协议
8 系统管理员可用的管理命令
9 根kernel有关的文件
用户与用户组
linux中,任何一个文件都有User,Group,Others权限设置
账号都记录在/etc/passwd这个文件内
/etc/passwd中一行记录对应着一个用户,每行记录又被冒号(:)分隔为7个字段,其格式和具体含义如下:
用户名:口令:用户标识号(uid):组标识号(gid):注释性描述:主目录:登录Shell
其中uid
0:系统管理员,1~499:系统账号,500~65535:可登陆账号
个人密码记录在/etc/shadow文件下
每行代表一个用户,:分隔9个字段,含义如下:
账号名称:密码(加密过):最近改动密码日期:密码不可被更改天数:密码需要重新更改天数:密码需要更改期限前的警告天数:密码过期后的账号宽限时间:账号失效日期:保留
用户组都记录在/etc/group内
:作为分隔,4个字段
用户组名称:用户组密码(具体位置在/etc/gshadow):GID:次用户组支持账号名称(,追加新用户)
/etc/gshadow,4个字段:
用户组名:密码列(!开头标识无合法密码,无用户组管理员):用户组管理员账号:用户组所属账户
Linux文件属性
-rw-r--r-- 1 root root 42304 Sep 4 18:26 install.log
【权限】 【文件名连接数】 【所有者账号】【所属用户组】【容量大小】【创建/修改日期】【文件名】
第一个字符
d 目录
- 文件
l 连接文件
b 设备文件里面可供存储的接口设备
c 设备文件里的串行端口设备
后面字符3个一组rwx(读,写,执行),代表所有者权限,用户组权限,其他非本用户组权限
注意:文件夹如果没有x权限,那么不能进入此目录
改变文件属性与权限
chgrp:改变文件所属用户组
循环递归将文件夹/文件所属用户组改为users
chgrp
-R
users dirname/filename
chown:改变文件所有者
循环遍历文件或目录将用户组改为root,用户名改为leestar
chown
-R
root:leestar dirname/filename
chmod:改变文件的权限,r4,w2,x1
循环遍历文件将权限改为所有都有
chmod -R 777 dirname/filename
linux文件种类
普通文件、纯文本文件、二进制文件、数据格式文件
目录、连接文件(类似快捷方式)、设备与设备文件(块设备文件,字符设备文件)
套接字、管道
linux是没有所谓“扩展名”的,能不能执行只与x属性有关,扩展名其实就是为了了解文件是什么东西。
linux目录配置
标准:FHS(Filesystem Hierarchy Standard)
|
可分享的 |
不可分享的 |
不可变的 |
/user(软件放置处) |
/etc(配置文件) |
/opt(第三方软件) |
/boot(开机与内核文件) |
可变的 |
/var/mail |
/var/run |
/var/spool/news |
/var/lock |
目录定义:
/(root根目录):与开机系统有关,所在分区越小越好,不要与应用程序安装的软件放在同一分区。
/bin:放置很多执行文件,cat,chmod等
/boot:放置开机会用到的文件
/dev:设备相关
/etc:配置文件
/home:系统默认用户主文件夹
/lib:系统函数库,开机时会用到
/media:媒体文件
/mnt:挂载额外设备
/opt:第三方软件目录
/root:管理员主文件夹
/sbin:只有管理员能利用的bin
/srv:服务器数据目录
/tmp:临时文件
/proc:虚拟文件,数据都是在内存中
/sys:虚拟文件,记录与内核相关的信息,不占用硬盘容量
(粗体目录一定不可与跟目录分开放在不同分区)
/usr(UNIX software resource):与软件安装/执行相关,类似windows的program files。
/bin:大部分用户可用命令再次,与根目录的bin不同在于,是否与开机过程有关
/include:安装文件使用到的头文件
/lib:应用软件函数库,不会经常被管理员用到
/local:系统管理员在本机自行安装自己下载的软件
/sbin:非系统正常运行所需的系统命令
/share:共享文件
/src:源码
/var:与系统运作过程相关
/cache:应用本身运行中产生的缓存
/lib:应用本身用到的lib,例如mysql就在/var/lib/mysql
/lock:资源锁
/log:日志文库
/mail:个人电子信箱目录
/run:程序或服务启动后,pid放置在此目录
/spool:放置队列数据,等待其他程序使用,被使用后通常会被删除。
绝对路径:由根目录(/)开始写起
相对路径:开头不是/写起的就是相对路径
.代表当前的目录
..代表上一次的目录
-代表前一个工作目录
~代表“目前用户身份”所在主文件夹
~account代表account这个用户的主文件夹
执行文件路径变量$path
echo $path
文件的三个主要时间:
modification time:内容数据更改时
status time:权限属性更改时
access time:内容被取用时
特殊文件权限:
4755,权限为-rwsr-xr-x,前面则是特殊权限
SUID(SetUID):4
所有者的x能变成s,仅对二进制程序有效,例如改密码的passwd,拥有x权限,执行的时候会临时获得程序所有者的权限
对目录无效
SGID(SetGID):2
用户组的x能变成s,SGID对目录有效,对程序作用和SUID类似,对目录的话,进入目录之后,就变成拥有该目录的用户组
Sticky Bit(SBIT):1
只针对目录有效,例如temp文件夹权限问drwxrwxrwt,加上SBIT权限,任何人可以在temp内添加、修改文件,但是之后文件/目录的创建者与root能够删除自己的文件或目录
Linux磁盘与文件系统管理(段页式)
date block(数据块):
block大小 |
1KB |
2KB |
4KB |
最大单一文件限制 |
16GB |
256GB |
2TB |
最大文件系统总容量 |
2TB |
8TB |
16TB |
- 原则上,block大小与数理在格式化完就不能改变了
- 每个block内最多只能放置一个文件
- 如果文件大于block大小,则一个文件会占用多个block数量
- 如果文件小于block大小,block的剩余空间就不会被使用(浪费空间),所以小文件系统建议block大小越小越好
inodetable(inode表格):
inode主要记录文件的属性以及该文件实际数据放置在哪几号block内,主要包括
- 文件访问模式(rwx)
- 文件所有者与组
- 文件大小
- 创建或状态改变时间
- 最近一次读取时间
- 最近一次修改时间
- 文件特性标识(flag),如SUID
- 文件真正内容指向(pointer)
inode在格式化的时候数量与大小已经确定
- 每个inode大小均固定128bytes,但是是段页式存储,所以可以记录很多个block,拿1KB的block来说,12个直接,1间接256,1二级间接256^2,1三级间接256^3
- 每个文件会占用一个inode
- 文件系统能够创建的数量与inode数量有关
- 系统读取文件的时候先找到inode,分析inode所记录的权限与用户是否符合,符合才能开始实际的读取block的内容。
Superblock(超级快)
记录整个文件系统相关信息的地方,没有Superblock,就没有这个文件系统。
- block与inode的总量;
- 为使用与已使用的block/inode数量;
- block与inode的大小(1K,2K,4K、128byte);
- 文件系统挂载时间、最近一次写入数据时间、最近一次检验磁盘(fsck)的时间等文件系统相关信息。
- 一个validbit数值,若此文件系统已被挂载,则valid bit为0,若未被挂载,则valid bit为1;
superblock挂了,文件系统就要花很多时间完救,一般来说superblock的大小为1024bytes
File system Description(文件系统描述说明)
block bitmap(块对照表)
inode bitmap(inode对照表)
挂载点一定是目录,该目录为进入该系统文件的入口
文件系统最顶层的目录的inode一般为2
- Linux中内存中的文件如果被修改了,会被标识为dirty,并不会立马写入磁盘,会不定时写入。
- 系统会将常用文件数据放置到主存储器缓冲区,加速文件系统读写,因此Linux的物理内存最后都会被用光,正常现象
- 你可以手动用sync来将内存中的dirty数据写回磁盘
- 如果正常关机,会主动调用sync,如果非正常关机,数据未写回磁盘,重启后会花很多时间检测磁盘,甚至文件系统崩溃
Ext3相比Ext2来说,得益于日志系统,有更好的可利用性、数据完整性、数据及易于转换。
hard link(硬连接/实际连接)ln
只是在某个目录下新建一条文件名连接到某inode号码关联的记录而已
symbolic link(符号连接,快捷方式)ln -s
就是在创建一个独立的文件,会占用inode和block,而这个文件会让数据的读取指向它连接的那个文件的文件名,和inode无关
压缩
常见的压缩文件扩展名:
.Z:compress程序压缩的文件
.gz:gzip程序压缩的文件
.bz2:bzip2程序压缩的文件
.tar:tar程序打包的数据,没有压缩
.tar.gz:tar程序打包文件,经过gzip压缩
.tar.bz2:tar程序打包文件,经过bzip2压缩
变量
命令别名,自定义变量在注销bash后就会消失,如果想保留,必须写入配置文件
变量是以一组文字或符号等, 来代替一些设置或者是一串保留的数据。
- 变量与变量以=来链接
- 等号两边不能直接接空格符号
- 变量名称只能是英文字母或数字,但是开头字符不能是数字
- 如果需要有空格,可以用'或"来保留,这两个区别一个是不解析,一个解析
- 可以通过\来转义特殊字符
- 可以使用$(命令)来调用其他命令提供的信息
- 若该变量需要在其他子进程执行,可以使用export来使变量变成环境变量
- 通常大写字符为系统默认变量,自定义变量可以使用小写,方便判断
变量类型默认为“字符串”
bash环境中的数值运算,默认最多仅能达到整数类型
var[index]=content声明数组
echo ${var[1]}读取数组
环境变量
HOME:用户主文件夹
SHELL:目前使用的shell,默认为/bin/shell
HISTSIZE:历史命令相关,记录条数
MAIL:使用mail命令会去读取邮件的文件
PATH:执行文件查找路径
LANG:语言
RANDOM:随机数变量,在bash环境下,random变量在0~32767之间
OSTYPE,HOSTTYPE,MACHTYPE:主机硬件与内核的等级
Bash Shell操作环境
新建/etc/nologin.txt,如果用户的shell为nologin,则提示txt的内容
登录与欢迎信息:
/etc/issue 进站界面
/etc/motd 登录后的提示信息
bash的login shell情况下所读取的整体环境配置文件其实只有/etc/profile
通配符:
*:0~N个任意字符
?:一定有一个任意字符
[abcd]:一定有一个字符,在[]之中任意一个
[0-9]:0~9直接所有字符
[^abc]:一定有一个字符,不在[^]中的任意一个
特殊符号:
#:批注
\:转义
|:管道,
每个管道后,必须是命令,这个命令必须要能就收输入数据,对于错误信息会忽略
;:连续执行分隔符,一个接着一个执行
~:用户主文件夹
$:变量前导符
&:作业控制,将命令变成背景下工作?
!:非
/:路径分隔
>,>>:数据流重定向,替换,累加,1为正确的数据,2位错误的数据,如果指向/dev/null,则吃掉信息
<,<<:输入,输入结束
'':不具备解析变量置换
"":具备解析变量置换
``:先执行的命令
():子shell起始结束
{}:命令块组合
管道命令中-号可以用来替代前一个命令的输入输出
正则表达式
使用表达式时,要注意系统环境语系,因为和编码顺序有关。
^word:待查找word在首行
word$:待查找word在尾行
e.e:代表中间一定有一个任意字符,如eve,eae,eee
\:转移字符,去除特殊符号的用途
ess*:重复0~N个前一个字符,如es(*可以是0),ess,esss
go+d:重复1个或一个以上,如god,good
go?d:0个或1个,如gd,god
[abc]:包含a或b或c
[0-9]:包含0~9的数字,和字符集的编码顺序有关哟!
[^abc]:不包含
go\{2,3\}g:g与g之间有2~3个o存在的字符串,如goog,gooog
|:或
():找出组字符串,如g(al|oo)d,结果位,gald或good
()+:重复多个组的判断
磁盘配额(Quota)
例如一个分区10G,30个账户,每个用户应该平均333M,如果有用户保存电影几个G,其他人都不用用了。
使用场景:
1、WWW server,个人网页空间的容量限制
2、mail server,每个人的邮件空间限制
3、file server,网络硬盘空间,结合Hadoop分布式文件系统?
使用限制:
1、仅针对整个文件系统,而不能仅设为目录
2、内核必须支持quota
设置选项:
1、容量限制或文件数量限制
- inode用量,管理用户可以新建的文件数
- block用量,管理用户磁盘容量。
2、soft/hard
- hard,用户觉得不能超过该限额,超过之后会锁住用户磁盘使用权
- soft,超过会报警,在宽限时间内必须减少容量,否则转化为hard。
quotacheck:扫描文件系统并新建Quota的配置文件
quotaon:启动quota的服务
quotaoff:关闭服务
edquota:编辑账号/用户组的限制于宽限时间
quota:单一用户的报表
repquota:针对文件系统的限额做报表
warnquota:对超过限额者发出警告值
setquota:直接于命令中设置quota的限额
软件磁盘阵列
RAID:RedundantArrays of inexpensive Disks,容错廉价磁盘阵列。
RAID-0:将文件切割成N分,分别放入N个磁盘,磁盘数量越多,性能越好,其中有一个损坏,全部玩完。
RAID-1:如果2个100G的磁盘组成,只有100G能用,另一个是备份空间,其中一块损坏,没事
RAID 0+1/1+0:先让2块磁盘组成RAID0,组成2组,这两组再组成RAID1,ABCD,AB,CD,性能提高,AB,CD又组成RAID1,互相备份,数据得到保护
RAID5:至少需要3块以上才能组成,写入的时候经过校验码计算,记录到不同磁盘,一个磁盘顺坏时,都能通过其他磁盘的校验码恢复数据,RAID5容量总会少一个磁盘块(因为用来做校验),当损坏的磁盘数大于等于2块时,就玩完
SELinux
由美国国家安全局开发,是在进程程序、文件等权限设置依据的一个内核模块
开发原因:很多企业发现,通常系统出现问题原因大部分在于“内部员工的资源误用”导致,实际由外部发动的攻击反而没那么严重。
root管理员权限太大,总爱给一些文件弄个777权限。
开发目的:防止root权限过大,以进程为主体,控制访问权限。
传统文件权限与账号关系:自主访问控制,DAC(Discretionary Access Control)
能否使用系统资源,和账号的rwx权限设置有关
以策略规则定制特定程序读取特定文件:委托访问控制,MAC(Mandatory AccessControl)
针对控制的“主体”变成了“进程”而不是用户,即使你是root,在不同的进程,你所能取得的权限不一定是root,要看当时进程的设置而定
如此一来,控制项目非常多,所以SELinux提供一些默认策略。
来自为知笔记(Wiz)