top,job,user,file,alias,jobalias


1、系统进程 2、系统资源管理 3、作业管理 4、用户管理 5、文件权限 6、别名定义       一、系统进程 1、进程的定义 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放。可以认为进程是一个程序的一次执行过程。 实际上,当计算机开机的时候,内核(kernel)只建立了一个init进程。Linux内核并不提供直接建立新进程的系统调用。剩下的所有进程都是init进程通过fork机制建立的。新的进程要通过老的进程复制自身得到,这就是fork。fork是一个系统调用。进程存活于内存中。每个进程都在内存中分配有属于自己的一片空间 (address space)。当进程fork的时候,Linux在内存中开辟出一片新的内存空间给新的进程,并将老的进程空间中的内容复制到新的空间中,此后两个进程同时运行。 老进程成为新进程的父进程(parent process),而相应的,新进程就是老的进程的子进程(child process)。一个进程除了有一个PID之外,还会有一个PPID(parent PID)来存储的父进程PID。如果我们循着PPID不断向上追溯的话,总会发现其源头是init进程。所以说,所有的进程也构成一个以init为根的树状结构。 2、查询进程——ps # ps -eo pid,ppid,nice --列出子进程与父进程,进程优先级,还可自己加要列出的项 # ps -aux | head --查看前十行进程,显示信息详情如下: USER: 执行者 PID: 进程号 %CPU: CPU资源百分比 %MEM: 物理内存百分比 VSZ: 使用虚拟内存 RSS: 占用的固定内存量 TTY: 在哪个终端机上运作 START: 该进程被触发的时间 TIME: 该进程实际使用CPU的时间 COMMAND: 创建该进程的程序的实际指令 STAT: 状态,主要状态有: R 正在运行,或在队列中的进程 S 处于休眠状态,可被 signal 唤醒 T 停止或被追踪 Z 僵尸进程(该程序应该已经终止,但是其父程序却无法正常的终止他) X 死掉的进程 < 高优先级 n 低优先级 L 分页在内存中锁定(对于实时和自定义IO) s 包含子进程 l 多线程(使用CLONE_THREAD,类似NPTL线程) + 位于后台的进程组 3、性能分析工具——top top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。 top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不断刷新当前状态; 如果在前台执行该命令,它将独占前台,直到用户终止该程序为止; 比较准确的说,top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表; 该命令可以按CPU使用.内存使用和执行时间对任务进行排序; 而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定.   # top --详解如下: @@第一行是任务队列信息,等同于单独命令 uptime: 11:14:54 (当前时间) up 1:42, (系统运行时间) 1 user, (当前登录用户数) load average: 0.00, 0.00, 0.00 (系统负载,即任务队列的平均长度。三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。) @@第二行为进程的信息。 153 total, (进程总数) 1 running, (正在运行数) 152 sleeping, (睡眠的进程数) 0 stopped, (停止的进程数) 0 zombie (僵尸进程数) @@第三行为CPU的信息。当有多个CPU时,这些内容可能会有甚至超过两行。 0.7%us, (用户空间占用CPU百分比) 0.3%sy, (内核空间占用CPU百分比) 0.0%ni, (用户进程空间内改变过优先级的进程占用CPU百分比) 99.3%id, (空闲CPU百分比) 0.0%wa, (等待输入输出的CPU时间百分比) 0.0%hi, (硬件CPU中断占用百分比) 0.0%si, (软中断占用百分比) 0.0%st (虚拟机占用百分比) @@最后两行为内存信息,类似于 free -m Mem: 1012348k total, (物理内存总量) 380664k used, (使用的物理内存总量) 631684k free, (空闲内存总量) 62524k buffers (用作内核缓存的内存量) Swap: 2047992k total, (交换区总量) 0k used, (使用的交换区总量) 2047992k free, (空闲交换区总量) 123636k cached (缓冲的交换区总量,内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖,该数值即为这些内容已存在于内存中的交换区的大小,相应的内存再次被换出时可不必再对交换区写入。) @@进程信息区统计信息区域的下方显示了各个进程的详细信息。首先,认识下各列含义 a PID 进程id b PPID 父进程id c RUSER Real user name d UID 进程所有者的用户id e USER 进程所有者的用户名 f GROUP 进程所有者的组名 g TTY 启动进程的终端名。不是从终端启动的进程则显示为 ? h PR 优先级 i NI nice值。负值表示高优先级,正值表示低优先级 j P 最后使用的CPU,仅在多CPU环境下有意义 k %CPU 上次更新到现在的CPU时间占用百分比 l TIME 进程使用的CPU时间总计,单位秒 m TIME+ 进程使用的CPU时间总计,单位1/100秒 n %MEM 进程使用的物理内存百分比 o VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES p SWAP 进程使用的虚拟内存中,被换出的大小,单位kb。 q RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA r CODE 可执行代码占用的物理内存大小,单位kb s DATA 可执行代码以外的部分(数据段+栈)占用的物理内存大小,单位kb t SHR 共享内存大小,单位kb u nFLT 页面错误次数 v nDRT 最后一次写入到现在,被修改过的页面数。 w S 进程状态(D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程) x COMMAND 命令名/命令行 y WCHAN 若该进程在睡眠,则显示睡眠中的系统函数名 z Flags 任务标志,参考 sched.h 默认情况下仅显示比较重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND 列; 更改显示内容通过 f 键可以选择显示的内容; 按 o 键可以改变列的显示顺序。 按大写的 F 或 O 键,然后按 a-z 可以将进程按照相应的列进行排序。而大写的 R 键可以将当前的排序倒转。 按 < > 翻页 # top -d 1 --1秒刷新一次 (默认是3秒) # top -n 10 --刷新10次就退出 # top -b -d 1 | grep -E 'root.*top' --持续监视 top 进程的信息变化 4、进程优先级控制——nice 进程优先级用nice 来表示,的范围是-20 至 19,数值越小,优先级越大 普通用户可以指定0-19这个范围之内的优先级来运行程序,如果普通用户要调整运行中的程序的话,只能把数值调大,不能调小。小于零的优先级只有root权限才能使用。 优先级对进程的执行有什么影响?优先级高的进程可以获得更多的系统资源,这个在系统处于高负荷的状态时比较明显。 # nice -n 19 gedit --以指定优先级(19)运行程序gedit # renice -n 19 1234 --把pid为1234的进程的优先级调为19 # ps -eo pid,nice | grep pid --可以通过相关进程号查看优先级是否为我们所设置 3.1、假设CPU有2个核心,可以用以下方法来测试优先级对程序执行的影响: # time nice -n 0 cat /dev/urandom > /dev/null --使用0优先级,占用第一个核心 # time nice -n 0 cat /dev/urandom > /dev/null --使用0优先级,占用第二个核心 # time nice -n 19 head -c 1m /dev/urandom > /dev/null # time nice -n 19 head -c 1m /dev/urandom > /dev/null 5、结束进程——kill/pkill kill命令用来终止指定的进程(terminate a process)的运行。一般,终止前台进程可以使用Ctrl+C键,但是,后台进程就须用kill命令来终止,我们需要先使用 ps/pidof/pstree/top/lsof 等工具获取进程PID,然后使用kill来杀掉进程。kill命令是通过向进程发送指定的信号来结束相应进程的。在默认情况下,kill会发出终止信号(15),这个信号可以被进程捕获,使得进程在退出之前可以清理并释放资源。也可以发送其他的信号。并且只有第9种信号(SIGKILL)才可以无条件终止进程,其他信号进程都有权利忽略。 # kill -l --列出全部的信号名称。如下为常用的信号: HUP 1 终端断线 INT 2 中断(同 Ctrl + C) QUIT 3 退出(同 Ctrl + \) TERM 15 终止 KILL 9 强制终止 CONT 18 继续(与STOP相反, fg/bg命令) STOP 19 暂停(同 Ctrl + Z) # pkill tail --根据正在运行的进程名杀死进程 6、进程拓展 # lsof /etc/passwd --查看一个文件被那个进程打开 # lsof -p pid --查看一个进程打开了哪些文件 # lsof -c tail --查看一个程序打开了哪些文件,这个与上面的进程号相对应 # lsof +d /etc --显示该目录下被进程打开的文件 # lsof +D /usr/local/ --显示该目录下被进程打开的文件;并且递归 # lsof -i[46] [protocol][@hostname|hostaddr][:service|port] 46 --IPv4 or IPv6 protocol --TCP or UDP hostname --Internet host name hostaddr --IPv4地址 service -- /etc/service中的 service name (可以不止一个) port --端口号 (可以不止一个) 6.1、恢复删除的文件 当系统中的某个文件被意外地删除了,只要这个时候系统中还有进程正在访问该文件,那么我们就可以通过lsof从/proc目录下恢复该文件的内容。 假如由于误操作将/var/log/messages文件删除掉了,那么这时要将/var/log/messages文件恢复的方法如下: # lsof /var/log/messages --我们看到该文件是正被进程打开着。pid: 1733 FD: 1w # rm -f /var/log/messages # lsof | grep /var/log/messages --会发现该文件已经被标记删除了,并且由该服务/进程打开 # head -n 20 /proc/1733/fd/1 --我们即可到相关的进程目录查看这个文件,记录了文件 /var/log/messages 的内容 # /etc/init.d/rsyslog restart --重启该服务/进程。重新让其打开我们的文件   二、系统资源管理 # free -m total used free shared buffers cached Mem: 988 381 606 0 61 123 -/+ buffers/cache: 196 792 Swap: 1999 0 1999 第一行 Mem。 total 内存总数;used 已使用内存数;free 空闲内存数;buffers buffers缓存内存数;cached Page缓存内存数。 第二行-/+ buffers/cache。used 真实使用的内存数(=Men.(used - buffers - cached)) free 真实空闲的内存数(=Men.(free + buffers + cached)) 第三行,指交换分区 # iostat -k 2 5 --每两秒刷新一次,输出5次;主要用于监控系统设备的IO负载情况 # vmstat 2 5 --服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况     三、作业管理 Linux的进程有前台后台的概念,前台进程会占用终端,一个终端只能有一个(一组)前台进程,可以有多个后台进程,在一个终端下只能管理该终端下的作业。 # gedit & --运行命令gedit 并把它放到后台执行 # jobs -l --列出当前终端里所有的后台进程 # bg 1 --把某个作业号为 1 并处于停止的后台进程改为运行状态 # fg 2 --把作业号为 2 的后台进程放到前台执行   四、用户管理 早期的操作系统比如DOS, Windows 98,同时只能允许一个用户使用操作系统,被称为单用户系统。Linux 是多用户系统,同时可以有多个用户使用系统。后面课程中的权限、进程、服务常常和用户这个实体之间存在关系。 1、用户管理常用操作 useradd, usermod , userdel,groupadd ,groupmod ,groupdel,passwd,gpasswd,id ,finger,chage 1.1、添加用户 # useradd frank --添加一个用户 # useradd -u 505 -d /home/frank -G george -s /bin/bash frank --使用参数添加一个用户 -u(指定用户uid) -g(如果不指定,系统默认会创建一个与用户名同名的组,并且加入该组,若指定,尽量不要指定已经存在的目录) -G(附加组) -d(家目录) -s(默认shell) # vim /etc/passwd --再一种创建用户的方法 bean:x:506:506::/home/bean:/bin/bash # vim /etc/shadow bean:!!:15564:2:14:5:2:: # vim /etc/group bean:x:506: # vim /etc/gshadow bean:!:: # passwd bean # touch /var/spool/mail/bean # chown bean:mail /var/spool/mail/bean # mkdir /home/bean # cp /etc/skel/.bash* /home/bean/ # chown bean:bean /home/bean -R -R 对文件和目录递归地进行操作 # chmod 700 /home/bean # id frank --输出的: gid,影响文件的创建; groups,影响文件的存取 注意: shell 概念,一个提供可以让用户输入指令的界面的程序。在命令界面模式下(文本终端模式),用户登录后第一个运行的程序就是shell # cat /etc/shells --常见的shell /bin/sh /bin/bash --开源的,Linux默认的shell /sbin/nologin -- 非交互式shell,不允许用户登录 /bin/tcsh /bin/csh 1.2、删除用户 # userdel frank -r --彻底删除一个用户。-r 参数是删除该用户的家目录与邮件文件。 # userdel frank --这三条其实就相当于上面一条 # rm -rf /home/frank/ # rm -rf /var/mail/frank 1.3、修改用户信息 # passwd frank --如果用户需要登录,首次建立必须给予密码 # echo '123' | passwd --stdin frank --这也是一种修改密码的方法 # passwd -e frank # chage -d 0 frank --用户下次登录之后,必须强制修改密码 # usermod -L frank --锁定用户密码,用户无法通过密码来登录,但是可以通过别的方式登录,比如ssh证书 # usermod -U frank --解锁用户密码 # usermod -e '2016-11-11' frank --设定账户过期日期。 # usermod -e '' frank --清除账户过期日期 # usermod -g george frank --修改用户初始组 # usermod -a -G g1,g2,g3 frank --将用户添加进某几个组 # usermod -l fran frank --将用户改名 1.4、组的管理 groupadd <group name> --添加组 groupdel <group name> --删除组 gpasswd -a <user name> <group name> --将用户添加进组 gpasswd -d <user name> <group name> --将用户从组删除 gpasswd -A u1,u2,u3 <group name> --设置组的管理员列表 gpasswd <group name> --设置组的密码 组的管理员的权限有: 修改组的密码; 往组里面添加用户;删除组里面的用户 2、Linux 中,系统用户的信息存放在如下几个文件中: /etc/passwd;/etc/shadow;/etc/group;/etc/gshadow 2.1、/etc/passwd 用户基本信息文件 # cat /etc/passwd fran:x:502:502::/home/frank:/bin/bash 第一列: 名字 第二列: 密码,为空的话,登录该用户不需要密码 第三列: uid, linux系统根据用户的uid来进行权限分配, 用uid来区分不同的用户 第四列: gid, gid的改变也会影响权限 第五列: 注释,可以根据需要修改 第六列: 家目录 第七列: 登录Shell, 登录shell只是一个程序 note: vim 的语法高亮和filetype有关, 如果我们直接打开/etc/passwd,语法高亮能正常显示,如果把/etc/passwd 复制到/tmp下面, 再打开/tmp/passwd, 则没有语法高亮显示,这个时候,需要运行一个vi的设置命令:set filetype=passwd,即可正常显示高亮的语法 2.2、/etc/shadow 用户的密码信息 # cat /etc/shadow fran:$6$tCVtLoJW$51V49x8CkvghMUJtdb1zoREFejppbi4bPbsdy0868wWENKNN6Y8EFUq8bkQYXwlG5PmT2Q0oQPi1rsCeFffd3.:0:0:99999:7::: 第一列: 名字 第二列: 加密后的密码,为空的话,登录该用户不需要密码 第三列: 最后一次密码修改时间 (距离1970-01-01的天数) 第四列: 密码的最小有效期(两次修改密码相隔的时间不能少于N天,0没有限制,任何时都能修改)。passwd -n 第五列: 密码的最大有效期,过了最大有效期,系统会强制用户修改密码,改完之后可以登录。passwd -x || chage -d 0 username 第六列: 密码过期之前,提前警告的天数。passwd -w 7 || chage -W 7 第七列: 密码过期后的宽限期,代表密码过期后是否还能修改密码后正常登录.为空,代表什么时候都可以修改密码然后正常登录. 如果密码过期了,宽限期也到了,用户就无法修改密码登录了,只能联系系统管理员。passwd -i 3 username || chage -I 3 username 第八列: 账户过期日期(距离1970-01-01的天数),如果账户过期了,就无法再登录系统. 不可设成0。usermod -e || chage -E 2015-07-19 bean 第九列: 保留字段,目前不使用. 以上属性,一般可以通过命令passwd修改,部分属性还能使用usermod修改。 note: 锁定用户密码,密码过期,账户过期三者的联系与区别 1. 锁定用户密码,本质上是在/etc/shadow里,用户密码那一栏加上一个感叹号,相当于改了一个密码 2. 密码过期就是密码失效了,分两种情况:如果宽限期字段为空的话,系统仍然允许用户先更新密码,再登录,如果宽限期字段设定了一个日期,那么当宽限期过后,账户就变为过期了。 3. 账户过期,账户一旦过期,就无法再登录了,需要管理员帮助恢复账户。密码过期+宽限期过期=账户过期 在红帽6.3中,锁定用户密码后,用户可以通过ssh的证书验证方式登录,账户过期后用ssh的证书验证才无法登录。然而,需要注意的是,账户过期之后是否还能登录是由系统上管理登录的程序决定的,不同的配置可能会有不同的结果,比如,同样是在红帽6.3中,如果配置sshd不使用PAM,那么就算账户过期来,仍然能够通过证书登录登录。 2.3、/etc/group 组的基本信息 # cat /etc/group frank:x:502: 第一列:组名 第二列:密码 第三列:组ID 第四列:组用户列表,当把用户添加进某个组后,就能在这个列看到该用户 2.4、/etc/gshadow 组的密码信息 # cat /etc/gshadow frank:!:: 第一列:组名 第二列:加密后的组密码 第三列:组管理员列表,管理员可以修改组的密码,往里面添加用户,或删除里面的用户 第四列:组用户列表(如果是直接修改配置文件的话,这里的内容应该设成与/etc/group第四列相同),在这里的用户可以不用输入密码而把有效组切换成该组,不在这里的用户则必须输入组的密码才能进行切换。   五、用户对文件权限 Linux 一切皆为文件。普通文件是文件。目录也是文件,目录里的文件列表以及相关信息就是目录这个特殊文件的内容。 # ls -l /var/ --接下来显示的信息就是 /var/ 这个目录文件的内容 1、九字符与八进制权限 # ls -l /etc/passwd -rw-r--r-- 1 root root 1922 Oct 24 22:48 /etc/passwd @@用户对文件的权限就体现在第一列的九个字符中。前面一个字符 '-' 是指文件类型,权限是接下来的九个字符,分为三组,每组三个字符。从左至右: 第一组的三个字符字符表示拥有者u(user)对该文件的权限。这里是 rw- 110 6 第二组的三个字符字符表示拥有组g(group)对该文件的权限。这里是 r-- 100 4 第三组的三个字符字符表示其他人o(other)对该文件的权限。这里是 r-- 100 4 @@固该文件相关权限可表示为: rw-r--r-- 644 @@每组的三个字符严格按顺序为: rwx 。若对应位置上为 - 。则没有相应权限。三字符详解: r 读(read) 针对常规文件: 是否允许可以查看文件的内容 针对目录: 是否允许可以查看目录里的列表 w 写(write) 针对常规文件: 能够修改文件的内容 针对目录: 是否能够删除目录下的文件,重命名文件、修改文件属性等 x 执行(execute) 针对常规文件: 是否可以执行该文件,一般为可执行文件(命令,程序,脚本等) 针对目录: 是否可以进入到该目录 总结: 正常操作一个目录,至少应该保证r-x @@文件的归属则体现在第二列与第三列。第二列为拥有者,第三列为拥有组。 2、权限设置——chmod # mkdir /tmp/test # touch /tmp/test/george # chmod 760 /tmp/test/george --改变权限 # useradd -G root u1 # useradd u2 --分别使用该两个用户去向 george 文件写入一个脚本,然后在使用 u1,u2,root 三个用户的身份执行脚本,验证权限的真正意义 # chmod u=rw,g-w,g+x,o+r george --然后根据这个文件的权限,我们使用三个用户一一验证。 注意:超级用户root,不管他对文件有什么权限,都不算数,他对文件绝对控制。 3、修改文件的所有者和属组——chown # chown u1:u2 george --修改文件的拥有者为u1;拥有组为u2。分隔符还可为字符 '.' # chown u2 george --修改文件拥有者 # chown .u1 george --修改文件拥有组 # chgrp u2 george --同上 # chown u1:u1 -R /tmp/test/ --递归修改,目录以及目录里的所有文件都更改。符号 -R 4、特权为、黏贴位——setuid/setgid/sticky 4.1、setuid特权 在默认情况下,系统运行的所有程序,其运行的过程,称它为进程。哪个用户执行该程序,那么该程序对应的进程的运行身份就是该用户。 setuid位能够使程序运行起来后,进程的euid 等于程序文件的uid,而不管是哪个用户运行了这个程序。 u1$ cat -当 u1 执行 cat 命令,我们可查看进程的运行身份为 u1 # chmod u+s /bin/cat # chmod 4755 /bin/cat --给 cat 命令加上 setuid。再使用用户 u1 执行 cat 命令 # ps -aux | grep cat --我们查看 cat 命令对应的进程由谁来执行 # ls -l /usr/bin/passwd --为什么命令 /usr/bin/passwd 设有setuid位 1. 用passwd 来修改密码,实质上就是修改/etc/shadow文件 2. 除了root用户,任何人都无法修改/etc/shadow文件 3. 根据上面两点,除了root用户,任何人都无法修改自己的密码 4. 但是实际工作中,普通用户应该具有修改密码的权限 5. setuid位能够使程序运行起来后,进程的euid 等于程序文件的uid,而不管是哪个用户运行了这个程序。 6. 因此我们可以利用setuid 这个技术 4.2、setgid特权位 如果针对可执行文件,改变的是命令运行过程中进程的组身份,使用的组身份命令文件的所属组 如果针对目录设定,那么任何人在该目录下创建子对象,这些对象的所属组身份都会继承该目录的所属组身份 # chown u1.u1 /tmp/test/ --先将实验目录的拥有者与所属组改为u1 # chmod g+s /tmp/test # chmod 2777 /tmp/test --给该目录加上组特权位。然后使用u2到该目录下创建文件 # ls -l /tmp/test/u2 --可见其所属组已经变为 u1 4.2、sticky粘贴位 当一个目录设了sticky位,那么在其下的文件,只有以下三个用户能删除:root、目录所有者、文件所有者。 # chown u1.u1 /tmp/test/ --先将实验目录的拥有者与所属组改为u1 # chmod 1777 /tmp/test/ # chmod o+t /tmp/test/ --给该目录设置粘贴位 然后使用不同身份做相关实验。 5、特殊文件属性——lsattr/chattr # lsattr george --查看文件的特殊属性 # chattr +a george --任何用户包括root,用户只能对添加a属性的文件进行内容追加(>>),并且文件不能被删除,修改。 # chattr +i george --任何用户包括root,都不能被删除添加i属性的文件,内容也不能修改。 6、目录与文件的默认权限——umask # umask --查看当前 umask;root 为 0022;普通用户为 0002 # usermod -g u1 u2 --当普通用户的默认组不同于用户名。则其 umask 为 0022 # umask 0077 --自己设置 umask。普通用户也可以自己设置   6.1、umask 的永久修改:   # vim ~/.bashrc --只针对某个用户永久修改umask   umask 0002   # vim /etc/bashrc --针对所有所用户修改   umaks 0022   6.2、创建文件   # touch test --权限为:0666 - umask = 0666 - 0022 = 0644   6.3、创建目录   # touch dir --权限为:0777 - umask = 0777 - 0022 = 0755 7、系统做读写权限检查的流程:   1. 检查进程的euid 是否为0,是则放行,否则检查下一步   2. 检查进程的euid 是否等于文件的uid,如果相等,则检查该文件权限位的左边三位是否有相应的权限,有则放行,否则拒绝   3. 检查进程的egid或者其中一个supplementary group id 是否等于文件的gid,如果相等,则检查该文件权限位的中间三位是否有相应的权限,有则放行,否则拒绝   4.检查该文件权限位的右边三位是否有相应的权限,有则放行,否则拒绝   六、别名定义 # alias --查看别名 # alias george='ls -l' --临时定义别名;只在当前终端生效 # unalias george --取消指定别名 # vim ~/.bashrc --为某个用户永久定义别名     alias grep='grep --color' # vim /etc/bashrc --为所有用户永久定义别名     alias grep='grep --color'  

相关内容

    暂无相关文章