Linux 系统管理常用命令
1. 系统状况
2. 系统安全
3. 系统优化
1. 系统状况
1.1 用户管理
whoami:查看自己是什么用户
[root@localhost ~]# whoami root [root@localhost ~]# su - zhang [zhang@localhost ~]$ whoami zhang
logname:查看自己是以什么用户登录的
[root@localhost ~]# logname root [root@localhost ~]# su - zhang [zhang@localhost ~]$ logname root
注意,logname 和 whoami 将是运维工作中自定义审计系统的重要命令。
who 或 w:查看当前登录账户
[root@localhost ~]# who root tty1 2012-08-14 17:38 root pts/0 2012-08-14 23:03 (192.168.1.100) zhang pts/1 2012-08-15 02:58 (192.168.1.100)
[root@localhost ~]# w 03:00:43 up 9:28, 3 users, load average: 0.45, 0.43, 0.37 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root tty1 - 17:38 3:58m 0.06s 0.06s -bash root pts/0 192.168.1.100 23:03 0.00s 0.13s 0.01s w zhang pts/1 192.168.1.100 02:58 8.00s 0.05s 0.03s sshd: zhang [priv]
第一行显示当前时间,机器启动时长,当前有多少用户在线,和 1 分钟、5 分钟、15 分钟 load。
第二行开始:
- USER:指的是 logname。
- TTY:指登录模式:tty1 是从本地登录;pts 从远程登录;from 是登录来源 IP。
- login@:指登录时间。
- IDLE:指空闲时间,也就是上一次执行命令的时间。
- JCPU:指占用 CPU 的时间总和。
- PCPU:指当前进程占用 CPU 时间。
- WHAT:指当前这个链接在执行什么程序(不准确)。
last:查看历史登录用户
[root@localhost ~]# last zhang pts/1 192.168.1.100 Wed Aug 15 02:58 still logged in root pts/1 192.168.1.100 Wed Aug 15 02:57 - 02:58 (00:00) root pts/0 192.168.1.100 Tue Aug 14 23:03 still logged in root tty1 Tue Aug 14 17:38 still logged in reboot system boot 2.6.18-308.el5 Tue Aug 14 17:32 (09:48) root pts/0 192.168.1.100 Mon Aug 13 10:17 - crash (1+07:14) root tty1 Mon Aug 13 10:15 - crash (1+07:17) reboot system boot 2.6.18-308.el5 Mon Aug 13 10:14 (1+17:05) tianyu pts/9 192.168.1.116 Sun Aug 12 17:28 - 17:29 (00:00) tianyu pts/9 192.168.1.116 Sun Aug 12 17:10 - 17:28 (00:18) sungui pts/8 192.168.1.114 Sun Aug 12 17:09 - down (00:42) sungui pts/8 192.168.1.114 Sun Aug 12 17:08 - 17:09 (00:01)
- 第一列:logname。
- 第二列:登录方式。system boot 意味着这时候启动机器。
- 第三列:来源 IP。
- 第四列之后:登录时间,结束登录时间和持续时间,括号中为持续时间,小时:分钟的格式。其中 down 代表该用户非主动退出,而是关机造成。
useradd 和 passwd:添加用户和修改用户密码
useradd 需要 root 用户来执行,普通用户没有权限。
passwd 如果使用 root 用户执行,可对所有用户修改密码;如果是用普通用户,只能对该用户本身修改密码,并且在修改密码前需要输入原有密码。
一般使用 root 执行 useradd 命令后,紧接着使用 passwd 命令为用户设置密码。
passwd 命令跟用户名为指定用户修改密码,不加参数为自己修改密码。
[root@localhost ~]# useradd trainingtest [root@localhost ~]# passwd trainingtest Changing password for user trainingtest. New UNIX password: Retype new UNIX password: passwd: all authentication tokens updated successfully.
如下所示,用户为自己修改密码受到严格的限制,除了要给出原有密码外,新密码还要受到系统的控制。
[trainingtest@localhost ~]$ passwd Changing password for user trainingtest. Changing password for trainingtest (current) UNIX password: New UNIX password: BAD PASSWORD: it is too simplistic/systematic New UNIX password: Retype new UNIX password: passwd: all authentication tokens updated successfully.
useradd 命令实际上是在 /etc/passwd 文件和 /etc/shadow 文件中增加一行,从而建立用户。
[root@localhost ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash …… tianyu:x:5017:5017::/home/tianyu:/bin/bash trainingtest:x:5018:5018::/home/trainingtest:/bin/bash
上述文件内容以冒号分隔,其中:
- 第一列是用户名,在 useradd 命令执行时指定用户名是已经确定;
- 第二列是密码,由于现在 linux 都使用 shadow 文件加密存放密码,这一列已经没有实际作用;
- 第三列是用户 id,如果在建用户时没有指定,就按照系统规则顺序排序;
- 第四列是用户组 id,如果在建用户时没有指定组,就默认新建一个和用户名一样的组名,如果指定,用户将有指定的默认组;
- 第五列是用户的家目录,没有指定的话默认在 /home/username 下;
- 第六列是用户默认使用的 shell,默认是 bash。
除用户名外,其它属性均可以使用 usermod 等命令改变。
[root@localhost ~]# cat /etc/shadow root:$1$7WOoeLaI$nvDWL8uRxN36Y8mm/tKmn0:15554:0:99999:7::: …… tianyu:$1$e8ZVT1Su$oy7IPJV5Uj8xvJt8CTWCS/:15564:0:99999:7::: trainingtest:$1$0vLhOWid$MVxqbAfvyM43RD.LihP08/:15566:0:99999:7::: test:!!:15566:0:99999:7:::
上述文件内容以冒号分隔,其中:
- 第一列:用户名;
- 第二列:密码的MD5加密码,可以认为就是密码;
- 第三列:密码最近一次修改的时间,使用标准时间。标准时间指从1970.1.1日期到这个时间的天数(秒数);
- 第四列:指密码可被修改的最少天数,0代表可随时修改;
- 第五列:密码的有效期,99999(274年)可以认为永不过期;
- 第六列:提示密码过期的天数,这里是前七天开始提示密码过期;
- 第七列:密码过期后,系统禁用账户的天数,空表示一直禁用;
- 第八列:密码过期后,账户已经被禁用的天数;
- 第九列:暂时没有使用,供以后新增功能。
该文件为用户密码限制的文件,以上参数可以通过 change 和 usermod 命令修改。感兴趣可以 man usermod 和 change。
userdel:删除用户
[root@localhost ~]# userdel dzhxc
[root@localhost ~]# rm -rf /home/dzhxc/
su:切换用户
su 使一个用户跳转到另外一个用户,如果是从 root 用户向其他用户跳转,不需要目标用户密码;如果从普通用户向其他用户跳转,需要目标用户密码。
格式:
su <-options> <username>
示例:
[root@localhost ~]# su zhang
[zhang@localhost root]$ su root
Password:
[root@localhost ~]#
可以看到,root 到普通用户不需要密码;普通用户到 root 需要密码,这里普通用户到其他普通用户也需要密码。
切换用户后,相当于进入一个新的 shell,如果要退出,exit 或者 [ctrl]+d。
su -
su - 命令可以使用目标用户的环境变量。环境变量定义了用户可执行命令的目录,被定义目录中的命令可以直接执行而不必输入路径。查看环境变量可以简单地使用 echo $PATH。
[root@localhost ~]# echo $PATH /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [root@localhost ~]# su zhang [zhang@localhost root]$ echo $PATH /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [zhang@localhost root]$ exit exit [root@localhost ~]# su - zhang [zhang@localhost ~]$ echo $PATH /usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/zhang/bin [zhang@localhost ~]$
可以看到,如果不使用”-”参数,环境变量不发生变化,即使从 root 账户 su 到普通账户,仍然使用的是 root 账户的环境变量,但这个时候有些命令就没有权限执行了;使用”-”参数后,切换用户后将使用新用户的环境变量。
注意:推荐使用 su - 命令来切换用户。每个用户的环境变量都是不一样的,都是有目的的。用自己的环境变量套用其他的账户会出现一些麻烦。在 shell script 中尤为明显。
1.2 查看硬件
1)raid 基础
服务器或者存储都会提供一块或者多块 raid 卡,用来管理磁盘。使得整个磁盘组有更好的组合方式,不再是单独的一块块磁盘,组合后可以提供完整的空间和相互备份。
Raid0:将所有磁盘整合在一起,空间叠加,没有冗余。
- 优点:磁盘空间利用率最大,可以获得最大的存储空间。读写速度略高于裸盘。
- 缺点:任何一块磁盘损坏,所有数据丢失。
Raid1:两块磁盘可做 raid1,相互备份,损坏一块阵列可以照常运行。当两块磁盘大小和速度不一致时,容量和读写速度依照小容量和低速盘。
- 优点:两块磁盘互备,高可用。无法扩展。读速度略高于裸盘。
- 缺点:损失一半磁盘空间。
Raid10:四块和以上磁盘的偶数磁盘可以做 raid10。结合 raid1 和 raid0 优势,所有磁盘两两分组,组成 raid1,然后多个 raid1 组成 raid10。
- 优点:每组磁盘两两互备,高可用。磁盘空间可以扩展。读写速度略高于裸盘。
- 缺点:损失一半磁盘空间。
Raid5:三块以上磁盘可以做 raid5。Raid5 用校验的方式写数据和读数据。提供 n-1 的磁盘空间和 1 块磁盘冗余。
- 优点:磁盘空间利用率高,无论多少磁盘组成raid,仅损失一块磁盘空间。读速度略高于裸盘,略高于raid0,是所有raid方式中读速度最好的。
- 缺点:如果磁盘数量过多,冗余度不够,有可能丢失数据。写速度仅有裸盘四分之一。
Raid6:在 raid5 基础上增加一块热备盘,可以提供 n-2 空间和两块磁盘的冗余。在磁盘数量较多的情况下使用 raid6,可以弥补 raid5 冗余度不够的缺点。
2)磁盘
fdisk:磁盘管理
fdisk 是一个强大的危险命令,所有涉及磁盘的操作都由该命令完成,包括:新增磁盘、增删改磁盘分区等。
fdisk -l 查看磁盘分区情况:
[root@localhost ~]# fdisk -l Disk /dev/sda: 27.8 GB, 27896315904 bytes 255 heads, 63 sectors/track, 3391 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/sda1 * 1 3260 26185918+ 83 Linux /dev/sda2 3261 3391 1052257+ 82 Linux swap / Solaris
可以看到,该机器上的硬盘只有一块,命名为 /dev/sda,可用 27.8G。在 fdisk 中以柱面为单位计数,该硬盘被分为 3391 个柱面,每个柱面 8225280 bytes(现代硬盘容量超大,导致 fdisk 运算失准,虽然最后计算的数值是准确的,但是磁头(heads)、分段(sectors)都是不准确的,准确的是柱面数量)。
该磁盘分为两个分区,第一个分区从第一个柱面开始到第 3260 个柱面结束,占据 26185918 个数据块,为 linux 分区……这样的信息在某些紧急情况下是有用的。
df:查看分区使用情况
[root@localhost ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 25G 8.3G 15G 36% / tmpfs 379M 0 379M 0% /dev/shm
-h 参数是以人类可理解方式显示磁盘空间。第一列为分区,第二列为分区大小,第三列为使用量,第四列为剩余量,第五列为使用百分比,最后是挂载点。一目了然,反应磁盘使用情况。
其中 tmpfs 是个特殊分区,可以理解为 2.6 内核带来的新特性,更高效率的使用内存和虚拟空间的技术。系统偶尔用到,某些特殊应用有需求,比如:oracle。
du:显示文件目录大小命令
格式:
du <-options> <file or directory>
- -s 对每个参数只显示总和。
du -h filename
[root@localhost ~]# du -h install.log 32K install.log [root@localhost ~]# du -sh install.log 32K install.log
对于文件,无论加不加 -s 参数,都是显示其大小。
[root@localhost training]# du -h cp_test/ 4.0K cp_test/lixionggang 4.0K cp_test/lixionggang1 4.0K cp_test/dir3 8.0K cp_test/dir4 8.0K cp_test/dir1 4.0K cp_test/dir2 36K cp_test/ [root@localhost training]# du -sh cp_test/ 36K cp_test/
对于目录,不加 -s 参数会将目录下所有目录依次列出。加了 -s 参数后仅仅显示目标目录的大小。
经典用法:du -sk *|sort -nr,即看看哪个目录占空间大。
[root@localhost home]# du -sk *|sort -nr 10184 liuzhongping 10140 chenchong 10084 zhaowei 10060 chenwenrong 10056 sungui 10020 zhangyanyan 10016 wangfei 10000 liubaiyu 9996 wanghao 9996 lixionggang 9988 tianyu 9988 guanchuang 9984 zouzhenguang 7752 training 2336 training.tar.gz
3)内存
free:查看当前内存使用情况
free 命令显示系统内存的使用情况,包括物理内存、交换内存(swap)和内核缓冲区内存。
- 加上 -h 选项(控制显示单位),输出的结果会友好很多。
- 有时我们需要持续的观察内存的状况,此时可以使用 -s 选项并指定间隔的秒数:free -h -s 3
输出简介
- Mem 行:物理内存的使用情况。
- Swap 行:交换空间的使用情况。
- total 列:系统总的可用物理内存和交换空间大小。
- used 列:已经被使用的物理内存和交换空间大小。
- free 列:还有多少物理内存和交换空间可供使用(真正尚未被使用的物理内存数量)。
- shared 列:被共享使用的物理内存大小。
- buffer/cache 列:被 buffer 和 cache 使用的物理内存大小。
- available 列:还可以被应用程序使用的物理内存大小。
buff/cache
Linux 内核为了提升磁盘操作的性能,会消耗一部分内存去缓存磁盘数据,就是 buffer 和 cache。
如果给所有应用分配足够内存后,物理内存还有剩余,linux 会尽量再利用这些空闲内存,以提高整体 I/O 效率,其方法是把这部分剩余内存再划分为 cache 及 buffer 两部分加以利用。
-
cache:从磁盘读取到内存的数据在被相关应用程序读取后,如果有剩余内存,则这部分数据会存入 cache,以备第 2 次读取时,避免重新读取磁盘。
-
buffer:当一个应用程序在内存中修改过数据后,因为写入磁盘速度相对较低,在有空闲内存的情况下,这些数据先存入 buffer,在以后某个时间再写入磁盘,从而应用程序可以继续后面的操作,而不必等待这些数据写入磁盘的操作完成。
如果在某个时刻,系统需要更多的内存,则会把 cache 部分擦除,并把 buffer 中的内容写入磁盘,从而把这两部分内存释放给系统使用,这样再次读取 cache 中的内容时,就需要重新从磁盘读取了。
通过以上分析可以得知,空闲物理内存不多,不一定表示系统运行状态很差,因为内存的 cache 及 buffer 部分可以随时被重用,在某种意义上,这两部分内存也可以看作是额外的空闲内存。
free 与 available
在 free 命令的输出中,有一个 free 列,同时还有一个 available 列。这二者到底有何区别?
free 是真正尚未被使用的物理内存数量。至于 available 就比较有意思了,它是从应用程序的角度看到的可用内存数量。
Linux 内核为了提升磁盘操作的性能,会消耗一部分内存去缓存磁盘数据,就是我们介绍的 buffer 和 cache。所以对于内核来说,buffer 和 cache 都属于已经被使用的内存。当应用程序需要内存时,如果没有足够的 free 内存可以用,内核就会从 buffer 和 cache 中回收内存来满足应用程序的请求。
所以从应用程序的角度来说,available = free + buffer + cache。请注意,这只是一个很理想的计算方式,实际中的数据往往有较大的误差。
交换空间(swap space)
swap space 是磁盘上的一块区域,可以是一个分区,也可以是一个文件,所以具体的实现可以是 swap 分区也可以是 swap 文件。当系统物理内存吃紧时,Linux 会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为各个进程服务,而当系统需要访问 swap 上存储的内容时,再将 swap 上的数据加载到内存中,这就是常说的换出和换入。
交换空间可以在一定程度上缓解内存不足的情况,但是它需要读写磁盘数据,所以性能不是很高。
现在的机器一般都不太缺内存,如果系统默认还是使用了 swap 是不是会拖累系统的性能?理论上是的,但实际上可能性并不是很大。并且内核提供了一个叫做 swappiness 的参数,用于配置需要将内存中不常用的数据移到 swap 中去的紧迫程度。这个参数的取值范围是 0~100,0 告诉内核尽可能的不要将内存数据移到 swap 中,也即只有在迫不得已的情况下才这么做,而 100 告诉内核只要有可能,尽量的将内存中不常访问的数据移到 swap 中。在 ubuntu 系统中,swappiness 的默认值是 60。
如果我们觉着内存充足,可以在 /etc/sysctl.conf 文件中设置 swappiness。如果系统的内存不足,则需要根据物理内存的大小来设置交换空间的大小,具体的策略网上有很丰富的资料。
4)LOAD(CPU 负载)
Linux 的系统负载指在特定时间间隔内(一个 CPU 周期)运行队列中的平均进程数。
从服务器负载的定义可以看出,服务器运行最理想的状态是所有 CPU 核心的运行队列都为 1,即所有活动进程都在运行,没有等待。这种状态下服务器运行在负载阈值下。
通常情况下,按照经验值,服务器的负载应位于阈值的 70%~80%,这样既能利用服务器大部分性能,又留有一定的性能冗余应对流量增长。
Linux 提供了很多查看系统负载的命令,最常用的是 top 和 uptime。
top 和 uptime 针对负载的输出内容相同,都是系统最近 1 分钟、5 分钟、15 分钟的负载均值:
这三个数值的使用方法和 CPU 核数相关,首先确认 CPU 总核数:CPU 总核数指的是物理核数。
- /proc/cpuinfo 中的 processors 的最大值不一定是 CPU 的核数,有可能该 CPU 支持超线程技术,从而 processors 是物理核数的 2 倍。
- 这里我们需要准确的核数,具体方法为:找到 /proc/cpuinfo 文件中所有的 physical id 后的数值,取得最大的数值,加一后就是实际的 CPU 个数。然后查找任意一个 processors 下的 cpu cores,即是该颗 CPU 的核数,实际 CPU 个数乘以核数即为 CPU 的物理总核数。
示例:
[root@localhost home]# cat /proc/cpuinfo |grep "physical id" physical id : 0 physical id : 0 [root@localhost home]# cat /proc/cpuinfo |grep "cpu cores" cpu cores : 2 cpu cores : 2
物理 CPU 个数为 0+1=1 个,每个 CPU 的核数为 2 个,所以总的物理核数为 2x1=2。
计算结果说明该机器的在单位时间内可以处理的进程数是 2 个,如果单位时间内进程数超过 2 个,就会出现拥堵的情况,load 就会持续增高,增高到一定程度,就会出现系统崩溃等异常情况。
查看系统负载阈值的命令如下:
一般经验上,将 load 的预警值设置为物理核数 x 0.7 。报警值为物理核数。
另外,机器针对突发情况的处理:
- 如果 1 分钟 load 很高,5 分钟 load 较高,15 分钟 load 起伏不大的情况下,说明该次高 load 为突发情况,可以容忍。
- 如果高 load 持续,导致 5 分钟和 15 分钟 load 都已经超过报警值,这时候需要考虑进行处理。
- 如果 15 分钟 load 高于 1 分钟 load,说明高 load 情况已经得到缓解。
5)CPU
top:主要用于监控系统的性能状态。比如 CPU、内存的使用以及进程的运行状况。
top 命令是 Linux 下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况。
top 是一个动态显示过程(默认在一个特定间隔 3 秒后刷新显示),即可以通过用户按键来不断刷新当前状态。如果在前台执行该命令,它将独占前台,直到用户终止该进程为止。
比较准确的说,top 命令提供了实时的对系统处理器的状态监视。它将显示系统中 CPU 最“敏感”的任务列表。该命令可以按 CPU 使用、内存使用和执行时间对任务进行排序;而且该命令的很多特性都可以通过交互式命令或者在个人定制文件中进行设定。
第一行:系统运行时间和平均负载
与 uptime 命令的执行结果一致。这些字段显示:
- 当前时间。
- 系统已运行的时间。
- 当前登录用户的数量相应。
- 最近 5、10 和 15 分钟内的平均负载。
load average 数据每隔 5 秒钟检查一次活跃的进程数,然后按特定算法计算出的数值。
第二行:任务信息汇总
在 linux 系统中,一般把进程统称为任务。第二行信息是对当前系统中所有任务的统计:
- 全部进程的数量。
- 正在运行的进程的数量。
- 睡眠状态的进程的数量。
- 停止状态的进程的数量。
- 僵尸进程的数量(僵尸是一种进程的状态)。
小写字母 t 可以控制是否显示任务信息汇总和 CPU 信息。没错,它能控制是否显示两行信息。
第三行:CPU 信息
这里显示不同模式下所占 CPU 时间百分比,共有 8 个字段,是我们了解 CPU 负载的主要依据。这些不同的 CPU 时间表示如下:
- us(user): 运行(未调整优先级的)用户进程所消耗的 CPU 时间的百分比。
- 像 shell 程序、各种语言的编译器、数据库应用、web 服务器和各种桌面应用都算是运行在用户地址空间的进程。
- 这些程序如果不是处于 idle 状态,那么绝大多数的 CPU 时间都是运行在用户态。
- sy(system):运行内核进程所消耗的CPU时间的百分比。
- 所有进程要使用的系统资源都是由 Linux 内核处理的。当处于用户态(用户地址空间)的进程需要使用系统的资源时,比如需要分配一些内存、或是执行 I/O 操作、再或者是去创建一个子进程,此时就会进入内核态(内核地址空间)运行。事实上,决定进程在下一时刻是否会被运行的进程调度程序就运行在内核态。
- 对于操作系统的设计来说,消耗在内核态的时间应该是越少越好。通常 sy 比例过高意味着被测服务在用户态和系统态之间切换比较频繁,此时系统整体性能会有一定下降。
- 在实践中有一类典型的情况会使 sy 变大,那就是大量的 I/O 操作,因此在调查 I/O 相关的问题时需要着重关注它。
- 大部分后台服务使用的 CPU 时间片中 us 和 sy 的占用比例是最高的。同时这两个指标又是互相影响的,us 的比例高了,sy 的比例就低,反之亦然。
- 另外,在使用多核 CPU 的服务器上,CPU 0 负责 CPU 各核间的调度,CPU 0 上的使用率过高会导致其他 CPU 核心之间的调度效率变低。因此测试过程中需要重点关注 CPU 0。
- ni(niced):用做 nice 加权的进程分配的用户态 cpu 时间百分比。
- 每个 Linux 进程都有个优先级,优先级高的进程有优先执行的权利,这个叫做 pri。进程除了优先级外,还有个优先级的修正值。这个修正值就叫做进程的 nice 值。
- 这里显示的 ni 表示调整过 nice 值的进程消耗掉的 CPU 时间。如果系统中没有进程被调整过 nice 值,那么 ni 就显示为 0。
- 一般来说,被测服务和服务器整体的 ni 值不会很高。如果测试过程中 ni 的值比较高,需要从服务器 Linux 系统配置、被测服务运行参数查找原因。
- id(idle):空闲的 cpu 时间百分比。
- 一般情况下, us + ni + id 应该接近 100%。
- 线上服务运行过程中,需要保留一定的 id 冗余来应对突发的流量激增。
- 在性能测试过程中,如果 id 一直很低,吞吐量上不去,需要检查被测服务线程/进程配置、服务器系统配置等。
- wa(I/O wait):cpu 等待 I/O 完成时间百分比。
- 和 CPU 的处理速度相比,磁盘 I/O 操作是非常慢的。有很多这样的操作,比如:CPU 在启动一个磁盘读写操作后,需要等待磁盘读写操作的结果。在磁盘读写操作完成前,CPU 只能处于空闲状态。
- Linux 系统在计算系统平均负载时会把 CPU 等待 I/O 操作的时间也计算进去,所以在我们看到系统平均负载过高时,可以通过 wa 来判断系统的性能瓶颈是不是过多的 I/O 操作造成的。
- 磁盘、网络等 I/O 操作会导致 CPU 的 wa 指标提高。通常情况下,网络 I/O 占用的 wa 资源不会很高,而频繁的磁盘读写会导致 wa 激增。
- 如果被测服务不是 I/O 密集型的服务,那需要检查被测服务的日志量、数据载入频率等。
- 如果 wa 高于 10% 则系统开始出现卡顿;若高于 20% 则系统几乎动不了;若高于 50% 则很可能磁盘出现故障。
- hi:硬中断消耗时间百分比。
- si:软中断消耗时间百分比。
- 硬中断是外设对 CPU 的中断,即外围硬件发给 CPU 或者内存的异步信号就是硬中断信号;软中断由软件本身发给操作系统内核的中断信号。
- 通常是由硬中断处理程序或进程调度程序对操作系统内核的中断,也就是我们常说的系统调用(System Call)。
- 在性能测试过程中,hi 会有一定的 CPU 占用率,但不会太高。对于 I/O 密集型的服务,si 的 CPU 占用率会高一些。
-
st:虚拟机等待 CPU 资源的时间
- 只有 Linux 在作为虚拟机运行时 st 才是有意义的。它表示虚机等待 CPU 资源的时间(虚机分到的是虚拟 CPU,当需要真实的 CPU 时,可能真实的 CPU 正在运行其它虚机的任务,所以需要等待)。
第四、五行:内存信息
内存信息包含两行内容,物理内存和交换空间:
top 命令中这部分的输出和 free 命令的输出基本相同。
控制显示单位
top 命令默认以 K 为单位显示内存大小,我们可以通过大写字母 E 来切换内存信息区域的显示单位(注意:E 不能控制任务区域中的内存单位)。下图以 GB 显示内存大小:
小写字母 m 可以控制是否显示内存信息。
第六行开始:进程(任务)信息
- PID:表示进程 ID。
- USER:表示进程所有者的有效用户名称。简单说就是以哪个用户权限启动的进程。
- PR:表示进程调度的优先级,PR 的值是以 Linux 内核的视角看到的进程执行的优先级。这个字段的一些值是“rt”,意味这些进程运行在实时态。
- NI:进程的 nice 值(优先级),即从用户视角看到的进程执行优先级。越小的值意味着越高的优先级。负值表示高优先级,正值表示低优先级。
- VIRT:进程使用的虚拟内存大小(单位 kb)。VIRT=SWAP+RES。
- RES:进程使用的物理内存大小。RES=CODE+DATA。
- SHR:进程使用的共享内存的大小(可能被其他程序用到的)。
- S:进程当前的状态。S 值有下面几种:
- D:不可中断的睡眠状态(uninterruptible sleep)
- R:正在运行的状态(running)
- S:睡眠状态(sleeping)
- T:跟踪或停止状态(traced or stopped)
- Z:僵尸状态(zombie)
- %CPU:进程使用 CPU 的百分比。
- %MEM:进程使用内存的百分比。
- TIME+:进程累计使用的 CPU 时间。
- COMMAND:运行进程对应的程序。
以上是默认显示的进程信息,另外还有更多的进程信息可供选择:
可选择显示的信息
PPID |
父进程 id |
UID |
启动该进程的用户的 id |
RUID |
真实用户的 id |
RUSER |
真实用户的用户名 |
SUID |
Saved user id |
SUSER |
Saved user name |
USER |
进程所有者的用户名 |
GID |
进程所有者所在组 id |
GROUP |
进程所有者的组名 |
PGRP |
进程组 ID |
TTY |
启动进程的终端名。不是从终端启动的进程则显示为 ? |
TPGID |
tty 进程所在 group id |
SID |
Session id |
nTH |
线程数 |
P |
最后使用的 CPU,仅在多 CPU 环境下有意义 |
TIME |
进程使用的 CPU 时间总计,单位秒 |
SWAP |
进程使用的虚拟内存中,被换出的大小,单位 kb |
增加显示信息和改变显示信息的顺序
在 top 显示视图中,按字母“f”,进入增加\减少信息和排序选项。如下图所示:
增加或减少列信息
上下移动光标,比如选中“TIME+”,再按空格,可以将 TIME+ 清除,然后输入“q”,可退回到信息页面。
如下图,TIME+ 列没有了
再次按下“f”,回到选择页面。
上下调整光标到 TIME 项,按空格选中。
按下方向键“左”,可以退出对 TIME 的顺序调整。然后“q”退出,可以看到用 TIME 代替了 TIME+。
默认进程的排序是按照 CPU 使用量,如果需要按照 MEM 排序,做法如下:
按下 f 键,进入选择页面,注意看右上角位置:
上下移动光标,选中 MEM,然后按键“s”,就可将排序改为 MEM:
按“q”,退回显示页面,即为使用 mem 排序显示进程:
1.3 ps:查看进程
[root@localhost cd_test]# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 2164 648 ? Ss 09:10 0:02 init [3] root 2 0.0 0.0 0 0 ? S< 09:10 0:00 [migration/0] root 3 0.0 0.0 0 0 ? SN 09:10 0:00 [ksoftirqd/0] root 4 0.0 0.0 0 0 ? S< 09:10 0:01 [watchdog/0] root 5 0.0 0.0 0 0 ? S< 09:10 0:00 [migration/1] root 6 0.0 0.0 0 0 ? SN 09:10 0:00 [ksoftirqd/1] root 7 0.0 0.0 0 0 ? S< 09:10 0:00 [watchdog/1] root 8 0.0 0.0 0 0 ? S< 09:10 0:17 [events/0] root 9 0.0 0.0 0 0 ? S< 09:10 0:00 [events/1] root 10 0.0 0.0 0 0 ? S< 09:10 0:00 [khelper] root 11 0.0 0.0 0 0 ? S< 09:10 0:00 [kthread] root 15 0.0 0.0 0 0 ? S< 09:10 0:00 [kblockd/0] root 16 0.0 0.0 0 0 ? S< 09:10 0:00 [kblockd/1] root 17 0.0 0.0 0 0 ? S< 09:10 0:00 [kacpid]
字段说明:
- USER:进程的属主。
- PID:进程的 ID。
- PPID:父进程。
- %CPU:进程占用的 CPU 百分比。
- %MEM占用内存的百分比。
- VSZ:进程使用的虚拟內存量(KB)。
- RSS:进程占用的固定內存量(KB)(驻留中页的数量)。
- TTY:进程在哪个终端上运行,若与终端无关,则显示(?)。
- START:进程启动时间。
- TIME:进程实际使用 CPU 运行的时间。
- COMMAND:命令的名称和参数。
STAT 状态位含义:
- D:无法中断的休眠状态(通常 I/O 的进程)。
- R:正在运行可中在队列中可过行的。
- S:处于休眠状态。
- T:停止或被追踪。
- W:进入内存交换(从内核 2.6 开始无效)。
- X:死掉的进程:(基本很少見)。
- Z:僵尸进程。
- <:优先级高的进程。
- N:优先级较低的进程。
- L:有些页被锁进内存。
- s:进程的领导者(在它之下有子进程)。
- l:多进程的(使用 CLONE_THREAD,类似 NPTLpthreads)。
- +:位于后台的进程组。
[root@localhost cd_test]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 09:10 ? 00:00:02 init [3] root 2 1 0 09:10 ? 00:00:00 [migration/0] root 3 1 0 09:10 ? 00:00:00 [ksoftirqd/0] root 4 1 0 09:10 ? 00:00:01 [watchdog/0] root 5 1 0 09:10 ? 00:00:00 [migration/1] root 6 1 0 09:10 ? 00:00:00 [ksoftirqd/1] root 7 1 0 09:10 ? 00:00:00 [watchdog/1] root 8 1 0 09:10 ? 00:00:18 [events/0] root 9 1 0 09:10 ? 00:00:00 [events/1]
- PPID:父进程 id 号。
- C:占用 CPU 百分比。
注意:ps 参数和含义很复杂,一般不去记忆。ps 有两套参数,一个是标准参数,一个是基于 BSD 的参数。
ps -ef 命令就能满足日常需要,ps aux 可提供不少的扩展,这两个命令就能基本满足运维需求,使用好这两个组合即可。
1.4 查看网络
ip:网络配置命令
注意:不提倡使用 ip 命令来直接更改适配器的配置。一方面,命令比较复杂,存在大量误操作的风险,误操作后往往失去和主机的链接而无法修正错误;另一方面,ip 命令配置的网络参数无法保存,在重启机器后失效。
通常用 ip a 命令查看 IP 地址:
[root@training ~]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:5f:ec:24 brd ff:ff:ff:ff:ff:ff inet 10.73.82.100/20 brd 10.73.95.255 scope global dynamic enp0s3 valid_lft 685046sec preferred_lft 685046sec inet6 fe80::9190:237:e629:e003/64 scope link valid_lft forever preferred_lft forever
ifconfig:网络配置命令
ifconfig 命令功能很多,主要是查看网络适配器情况和配置网络适配器。
注意:不提倡使用 ifconfig 命令来直接更改适配器的配置。一方面,命令比较复杂,存在大量误操作的风险,误操作后往往失去和主机的链接而无法修正错误;另一方面,ifconfig 命令配置的网络参数无法保存,在重启机器后失效。
一般使用 ifconfig 命令查看网络适配器的配置情况:
[root@localhost ~]# ifconfig eth0 Link encap:Ethernet HWaddr 08:00:27:33:55:2D inet addr:192.168.1.102 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe33:552d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8866 errors:0 dropped:0 overruns:0 frame:0 TX packets:11263 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:675881 (660.0 KiB) TX bytes:9797565 (9.3 MiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
其中,比较重要的信息包括:
- ip 地址、mac 地址等网络基本信息。
- RX packets、接收包、以及该行的 errors,dropped 等信息。
- TX packets、发送包、以及该行的 errors,dropped 等信息。
- 最后一行:开机以来接收、发送字节数。
errors 和 dropped 是判断网络异常的第一个检查点。在碰到网络异常的时候,应该首先从终端检查,然后排查网络设备。对 linux 服务器,从终端检查往往是查看 ifconfig 中的 dropped 值。
最后发送和接受的字节数可以清楚地知道该机器的流量压力。
ss:查看网络、连接情况
ss -ant:命令查看当前连接情况
如上中图 ESTAB 状态这一行,表示当前 SSH 有连接接入,是 establish 状态,即正在连接状态。本机使用 10.73.82.100 的 ssh 端口,对端使用 10.73.81.28 的 59115 端口。
除了 ESTAB 状态,还有 LISTEN 状态、TIMEWAIT 状态等。
- Listen:监听状态。
- ESTABLISHED:已连接状态。
- TIME_WAIT:连接断开,处于等待释放阶段。
netstat:查看网络、连接情况
格式:
netstat <-options>
- -a:显示所有监听和非监听连接。
- -l:只显示监听端口。
- -p:显示监听的名称。
- -n:直接显示ip,不尝试显示机器名等信息。
一般直接使用组合 -anp 或者 -lnp:
字段解释:
- 第一列表示:该连接是 tcp 还是 udp 连接。
- Recv-Q:本地已经开始缓存,但还没有读取的数据。
- Send-Q:在本地缓存,还没有被对方拿走的数据。
- Local Address:本地 ip 和连接的端口。
- Foreign Address:对方的 ip 和连接的端口(listen 状态一般是所有 ip 的所有端口)。
- State:状态。
- Listen:监听状态。
- ESTABLISHED:已连接状态。
- TIME_WAIT:连接断开,处于等待释放阶段。
- PID/Program name:该连接的 pid 和名字。
如果不加参数 p,将只能看到每条连接,无法获知该链接来自哪个pid或者进程名称:
如果不加参数 n,netstat 将尝试解析所有远端连接的机器名等信息。如果对方机器没有名字或者反向解析功能,对每一个连接解析需要将近 20 秒,如果有上千个连接,等待时间将是无法忍受的。
1.5 查看系统日志
在系统 /var/log 中存放着大量系统日志,用来记录系统中的重大事件。所有默认安装的软件都会在这里记录日志。一般情况下,即使有自定义安装的软件且日志不在此目录下,也会在此目录做一个软连接指向日志所在。
这个目录下的日志会按照时间和大小自动轮转、删除。
- messages:系统最常用的日志,各种故障、报警、安全、性能等都会在此记录。无论查任何日志,看一眼该日志是好习惯。
- Secure:安全相关,比如登录信息、登录失败信息等。
- Dmesg:硬件信息。
- Boot:启动过程中的日志。
- cron:自动运行的日志。
- Maillog:邮件系统日志。
- Audit:安全方面的审计日志。
- 其它日志。
1.6 查看系统信息
uname -a:打印系统信息
[root@localhost log]# uname -a Linux localhost 2.6.18-308.el5 #1 SMP Tue Feb 21 20:05:41 EST 2012 i686 i686 i386 GNU/Linux
查看系统版本
[root@localhost log]# cat /etc/redhat-release CentOS release 5.8 (Final)
查看、修改机器名
[root@localhost audit]# hostname
localhost
[root@localhost audit]# hostname training
[root@localhost audit]# hostname
training
使用命令修改用户名,只能在关机前生效,而且需要重新连接终端才能看到 root@training。
[root@localhost audit]# vi /etc/sysconfig/network
修改这个文件可以在系统配置层面修改机器名。同时也需要在 /etc/hosts 中做相应修改,以让机器自己知道 training 指向自己。
2. 系统安全
2.1 密码管理
一、root 密码
root 密码比较特殊,由于 root 用户拥有超级权限,所以 root 用户的密码可以绕开层层系统强制限制,用很简单的字符用来做密码。建议 root 密码不要太短、不要有含义、要有一定得复杂性。由于 root 的特殊性,多复杂的密码都不过分。
root 密码理论上只有一个人知道,即该机器的系统管理员,其他用户都被 root 授予不同的权限用来操作管理服务器。
root 密码要经常改动。
二、普通用户密码管理
普通用户的密码,由 root 用户重置时,也可以绕开各种限制,所以一般不推荐使用 root 对普通用户的密码进行管理。应该让用户自己按照规则自行管理。
普通用户的密码管理主要涉及两个文件:/etc/login.defs 和 /etc/pam.d/system-auth 。其中,/etc/pam.d/ 目录下提供大量的安全和审计功能,为服务器的认证提供了一个可选择的强大工具组。具体可以参考红帽官方网站或者在 google 上搜索,使用比较复杂。这里只讲和密码强度有关的一个文件。
1)密码时间控制:/etc/login.defs
打开 /etc/login.defs 文件,这里面定义了用户建立后的一些基本参数,包括密码时间特性、用户家目录、用户 uid 和 gid 的起始数值等。在建立用户时,如果没有指定参数,均会采用该文件中限制的默认值。
主要看密码特性的四个参数:
PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_MIN_LEN 5 PASS_WARN_AGE 7
- PASS_MAX_DAYS:密码的最长有效期,单位为天。密码使用超过这个期限而没有修改的话,账户将被锁定,只有 root 才可以重新解开该账户。
- PASS_MIN_DAYS:密码的最短有效期,也就是密码更新后,在规定的天数内不得再次修改。
- PASS_MIN_LEN:密码的最小长度,root 用户可以不按照这个值设定自己或普通用户的密码,其他用户设置密码必须长于这个值。
- PASS_WARN_AGE:密码到期前的提醒日期,也就是密码在达到最大日期前几天开始提醒用户修改密码。
2)密码强度控制:/etc/pam.d/system-auth
在这个文件中,找到 password requisite pam_cracklib.so 这一行。在后面添加参数:
retry=5 difok=3 minlen=10 ucredit=-1 lcredit=-3 dcredit=-3
一般经典的配置如下:
password requisite pam_cracklib.so retry=5 difok=3 minlen=10 ucredit=-1 lcredit=-3 dcredit=-3
其中:
- retry:尝试修改密码的次数,由于限制繁多,一般不能一次输入成功。
- difok:与旧密码相比较,不同字符限制。正数为至少不同的字符数,负数为最多相同的字符数。
- minlen:长度限制,和 /etc/login.defs 相比较,取大的值。
- ucredit:大写字母数限制,正数和 0 为最多几个,负数为最少几个。
- lcredit:小写字母限制,正数和 0 为最多几个,负数为最少几个。
- dcredit:数字限制,正数和 0 为最多几个,负数为最少几个。
另外,这个文件中的其它几行也对密码做了相应的限制,比如不能给予用户名设置密码等。具体可以查找资料,一般来说,用上述两个文件就可以对密码管理作出比较详尽的限制。
注意:
- 在实际运维工作中,在多机器环境下,一般不使用机器自带的密码管理策略,而一般使用域技术或者用户管理系统来限制用户。
- 域技术有专门的密码策略,所有用户都在网络上添加,实际服务器上没有用户。
- 用户管理系统一般为自行开发,有各种参数来限制 useradd 命令,使用户的添加有统一的规则。另外,在用户添加后,也可以使用 usermod 来改变各种属性。
2.2 权限管理
1)组管理
Linux 的组管理很灵活,每一个用户都有一个初始组。该用户新建的文件和目录的组属性都会是该初始组。另外,linux 还可以建立很多其它的组,然后将不同的用户添加进这个组中,可以通过控制组的权限完成不同的权限控制。
在 linux 中,添加用户时如果不加参数限制,默认的初始组就是该用户本身,即新建用户的同时,新建一个以该用户命名的组,并且该用户的初始组就是这个组。
系统默认会有各种组,比如 bin、wheel 等。如果没有单独的新建一个组(groupadd),那么所有的 uid 和 gid 都会依次从 5000 开始累加。
建议:在系统管理中,如果需要新增一个组,最好是新增一个以这个组名命名的用户。这样系统默认生成这个组,而且 uid 和 gid 同时增加一。如果这个用户不需要,可以在 /etc/passwd 中禁用。这样在日后的管理中,所有用户和其初始组 uid 和 gid 保持一致,不容易混淆。
groups:查看当前用户所属组
[root@training tmp]# groups root bin daemon sys adm disk wheel [root@training tmp]# su - zhang [zhang@training ~]$ groups zhang
group 命令列出当前用户的所有属组,第一个为初始属组,剩余的是该用户的所属组。普通用户如果没有添加组,只有默认的初始组。
usermod:改变用户属组
- usermod -g groupname username:改变用户初始组
- usermod -G groupname username:将用户添加至组
usermod 命令功能比较复杂,可以改变用户的所有属性,时间属性也可以由这个命令修改,具体请查看 man。
usermod 一般只有 root 用户可以使用。
[root@training ~]# useradd testgroup [root@training ~]# cat /etc/passwd|egrep "zhang|testgroup" zhang:x:5002:5002::/home/zhang:/bin/bash testgroup:x:5035:5035::/home/testgroup:/bin/bash [root@training ~]# usermod -g testgroup zhang [root@training ~]# cat /etc/passwd|egrep "zhang|testgroup" zhang:x:5002:5035::/home/zhang:/bin/bash testgroup:x:5035:5035::/home/testgroup:/bin/bash [root@training ~]# su - zhang [zhang@training ~]$ touch b.txt [zhang@training ~]$ ls -al * -rw-rw-r-- 1 zhang zhang 0 Sep 2 15:47 a.txt -rw-r--r-- 1 zhang testgroup 0 Sep 2 15:54 b.txt [zhang@training ~]$ groups testgroup
上述操作说明,新建一个用户后,系统会默认新建一个以该用户命名的组,并且该用的初始组就是这个组。
- testgroup 可以添加其它用户,甚至其它用的初始组可以是该组。
- zhang 用户默认的初始组为 zhang,所以新建的文件拥有者和拥有组默认的都是 zhang。
- 在执行过 usermod -g 后,zhang 用户的初始组变为 testgroup,新建的文件默认的拥有者和拥有组变为 zhang 和 testgroup。
[root@training ~]# usermod -G testgroup zhang [root@training ~]# su - zhang [zhang@training ~]$ groups zhang testgroup
也可以将某个用户加入到特定组中,但不是以初始组的方式。这种情况下,该用户仍然拥有这个组的权限,只是该用户新建的文件、目录等默认显示的不是该组的属组。
批量增加和删除组成员
可以通过修改 /etc/group 文件来达到增加和删除组成员的目的(修改前一定要备份)。
[root@training ~]# cat /etc/group|grep testgroup testgroup:x:5035:zhang,wu,liuzhongping [root@training ~]# su - liuzhongping [liuzhongping@training ~]$ groups liuzhongping testgroup
使用 vi,在 /etc/group 文件中找到 testgroup 这一行,在最后一个“:”后面添加用户名,以”,”分隔,保存退出后,相应的用户就增加到这个组中。
注意:/etc/group 文件默认不显示和组名相同的用户名。比如,testgroup 用户新建时生成了 testgroup 组,但是在 /etc/group 中 testgroup 这一行却并没有显示 testgroup 用户属于该组,实际上,testgroup 用户当然属于 testgroup 组,无论 testgroup 用户是否被禁用。
这就是不使用 groupadd 的一个原因,这样我们在检查某个组中的成员时,我们知道默认的用户也存在于这个组。一旦使用 groupadd 增加新组,在检查组成员的时候,我们无法得知某个组是否有默认的用户在该组中。
[root@training ~]# cat /etc/group|grep testgroup testgroup:x:5035:zhang,wu [root@training ~]# su - liuzhongping [liuzhongping@training ~]$ groups Liuzhongping
使用 vi 将某个用户从 testgroup 中删除,保存退出后,该用户从这个组中删除。
2) chown:属组权限管理
在 linux 下,谁建的文件或者目录,该文件或者目录就有相应的所有者属性。例如,使用 root 用户建立的文件,其所有者就是 root,其所有组也是 root。
在很多情况下,尤其是 root 用户所做的新建操作,需要把新建的文件或者目录所有者交给普通用户,这时候需要用到 chown 命令。
格式:
chown <-option> username.groupname /path/to/file
参数 –R 递归参数,对目录下的所有目录和文件进行操作。
[root@training tmp]# ls -al a.txt -rw-r--r-- 1 root root 8 Aug 12 17:19 a.txt [root@training tmp]# su - zhang [zhang@training ~]$ cd /tmp/ [zhang@training tmp]$ cat a.txt a b c d [zhang@training tmp]$ echo "e" >> a.txt -bash: a.txt: Permission denied [zhang@training tmp]$ exit logout [root@training tmp]# chown zhang.zhang a.txt [root@training tmp]# su - zhang [zhang@training ~]$ cd /tmp/ [zhang@training tmp]$ echo "e" >> a.txt [zhang@training tmp]$ cat a.txt a b c d e [zhang@training tmp]$ ls -al a.txt -rw-r--r-- 1 zhang zhang 10 Sep 2 15:14 a.txt
上述一系列操作可以看出,root 建立的文件默认普通用户只有读的权限,没有写的权限。将这个文件的拥有者改变后,目标用户将有这个文件的所有权限。
注意,chown 只改变文件或者目录的所有者属性,不改变文件或目录的读写属性。比如:上述例子中,该文件默认为拥有者(root)可读可写、本组成员(root 组)可读、其它用户可读;改变用户后,仍然是拥有者(zhang)可读可写、本组成员(zhang 组)可读、其它用户可读。
chown 也可以将某个文件或者目录给一个用户和非该用户初始组的组。
[root@training tmp]# mkdir testgrp [root@training tmp]# ls -l|grep testgrp drwxr-xr-x 2 root root 4096 Sep 2 16:32 testgrp [root@training tmp]# chown -R zhang.testgroup testgrp/ [root@training tmp]# ls -l|grep testgrp drwxr-xr-x 2 zhang testgroup 4096 Sep 2 16:32 testgrp
这样,testgroup 中的成员享有该目录的读和执行权限。
chown 命令和下面将要介绍的 chmod 命令配合,可以细化目录和文件的权限管理。
3)chmod:文件权限管理
格式:
chmod <-option> mode /path/to/file
-R 递归参数。
chmod <-option> +/- [xwr] /path/to/file
但是使用 +/- 的话,三组数据都会同时增加或减少某个权限,这通常是不希望看到的。
回忆 ls -l 中的第一列数值:drwxr-xr-x,除第一个字母外,其余 9 个代表三个范围的权限,三个一组:拥有者权限、拥有组权限和其他人权限。其中 r 代表可读、w 代表可写、x 代表可执行,- 代表不具有该权限。
为了在执行 chmod 时方便表述这三种权限,linux 规定:r 的数值是 4,w 的数值是 2,x 的数值是 1、不具有权限为 0,同一组权限的三个数值相加,得出一个代表该组权限的数字。
那么,rwxr-xr-x 用数值表示就是 755,其中 7 代表拥有者具有可读(4)+可写(2)+可执行(1)=7;5 代表可读(4)+可执行(1)=5
各种组合:
- 7=w+r+x=4+2+1:可读可写可执行,最高权限。
- 6=w+r=4+2+0:可读可写,几乎是最高权限,只是不能直接执行该文件或目录(无法打开目录)。
- 5=r+x=4+0+1:可读可执行,受限制的权限,只是可以看、可以用,但是不能改,比较常用。
- 4=r=4+0+0:可读,受限制的权限,仅仅能看。
- 3=w+x=0+2+1:可写可执行,受限制的权限,一般少用,常见于日志文件存放的目录。只是让用户可以进入目录并向文件中写入内容,但是无法查看目录内容。
- 2=w=0+2+0:和3类似,受限制的权限,用于日志文件。
- 1=x=0+0+1:仅可执行,只用于目录,对于文件来说,仅有可执行权限没有意义,任何可执行的文件都必须有可读权限才可以顺利执行。对于目录意义也不大,仅仅是可以进入目录,进入后不可浏览目录内容,也无法创建文件或者目录。
- 0=-+-+-=0+0+0:完全没有权限,常用。
chmod –R 755 /path/to/dir 可以将一个文件夹的权限属性改为拥有者可读可写可执行,拥有组可读可执行,其他用户可读可执行;
chmod 644 /path/to/file 可以将一个文件的权限属性改为拥有者可读可写,拥有组可读,其他用户可读。
常用权限注意事项:
- root 对任何文件都有可读、可写权限,并有权更改其所属属性和权限属性。
[root@training tmp]# ls -l a.txt -rwxr-xr-x 1 zhang zhang 5 Sep 4 22:23 a.txt [root@training tmp]# chmod 000 a.txt # 对于不是自己的文件,root可以修改其权限属性 [root@training tmp]# ls -l a.txt ---------- 1 zhang zhang 5 Sep 4 22:23 a.txt [root@training tmp]# cat a.txt # 对于不可读文件,root可以读取其内容 aaaa [root@training tmp]# echo "haha" >> a.txt # 对于不可写文件,root可以写内容到该文件 [root@training tmp]# cat a.txt aaaa haha [root@training tmp]# chmod 755 a.txt [root@training tmp]# ls -l a.txt -rwxr-xr-x 1 zhang zhang 22 Sep 4 22:34 a.txt
- 文件拥有者对自己的文件有权利更改其权限属性,但是如果不具有读写权限的话无法读或者写。但是,由于拥有者可以更改文件的权限属性,所以虽然不能直接读写无读写权限的文件,却可以修改权限属性后读写该文件。
[zhang@training tmp]$ ls -l a.txt # zhang 用户对 a.txt 权限为 0,但是 a.txt 属于zhang ---------- 1 zhang zhang 22 Sep 4 22:34 a.txt [zhang@training tmp]$ cat a.txt cat: a.txt: Permission denied # 无法读取 [zhang@training tmp]$ echo "hello" >> a.txt -bash: a.txt: Permission denied # 无法写入 [zhang@training tmp]$ chmod 700 a.txt # 但是可以修改权限 [zhang@training tmp]$ ls -l a.txt -rwx------ 1 zhang zhang 28 Sep 4 22:45 a.txt [zhang@training tmp]$ cat a.txt # 修改后就可以读写,也可以让别人读写,比如 777 权限 #!/bin/bash aaaa haha [zhang@training tmp]$ echo "hello">>a.txt [zhang@training tmp]$ cat a.txt #!/bin/bash aaaa haha hello
- 非 root 的用户不能修改文件的所有者。
[zhang@training tmp]$ chown wu.wu a.txt
chown: changing ownership of `a.txt': Operation not permitted
- 组用户只能遵守规定了的读写执行权限,无法修改文件的权限属性。
[root@training tmp]# cat /etc/group|grep testgroup # wu为testgroup组成员 testgroup:x:5035:zhang,wu [root@training tmp]# chown zhang.testgroup a.txt # 将a.txt的所有组变更为testgroup [root@training tmp]# ls -l a.txt -rwx------ 1 zhang testgroup 28 Sep 4 22:45 a.txt [root@training tmp]# su - wu [wu@training ~]$ cd /tmp/ [wu@training tmp]$ cat a.txt # testgroup不具有读写执行权限,所以不能查看 cat: a.txt: Permission denied [wu@training tmp]$ chmod 770 a.txt # 组内的成员不具有修改文件权限的权力 chmod: changing permissions of `a.txt': Operation not permitted
- 其他用户的权力和拥有组的权力类似,也是只能遵守规定的权限,不能修改权限属性。
- 权限对于目录和文件的区别:
- 对于目录来说,可读可以在该目录下列出所有内容;可写意味着可以在该目录下新建内容;可执行意味着可以打开该目录。
- 对于文件来说,可读可以查看该文件内容;可写可以修改该文件内容;可执行意味着可以直接输入该文件路径和名称,然后系统自动执行文件中的内容。
- 对于可执行文件:系统在第一行开头找形如:“#!/bin/bash”或者”#!/usr/bin/perl”的字样,这是可执行文件的语言解释器标示,即以下文字用什么语言来执行。如果有这样的文字,系统自动的以解释器中的语言或者命令执行之后的文字,如果没有这样的文字,系统默认使用当前的 shell(默认为 bash)执行之后的文字。
[root@training tmp]# ls -l aa.sh -rw-r--r-- 1 root root 27 Sep 2 21:37 aa.sh [root@training tmp]# ./aa.sh # 没有可执行权限 -bash: ./aa.sh: Permission denied [root@training tmp]# cat aa.sh #!/bin/bash # 解释器 echo "haha" # 正确语句 aa # 错误语句 [root@training tmp]# chmod 755 aa.sh [root@training tmp]# ./aa.sh Haha # 正确语句可以执行出结果 ./aa.sh: line 3: aa: command not found # 错误语句会报错
2.3 sudo:超级权限
经典的 linux 或者 unix 权限管理里面,有一个很重要的思想:root 身份一般不需要登录,普通用户通过提权命令获得部分权限,即可完成所有系统级的操作。
这个提权命令就是 sudo,sudo 的含义就是当前用户要以 root 身份执行之后的命令。前提是 root 在 /etc/sudoers 文件中规定了某个用户具有某些权限。
sudo 有以下特点:
- sudo 能够限制用户只在某台主机上运行某些命令。
- sudo 提供了丰富的日志,详细地记录了每个用户干了什么。它能够将日志传到中心主机或者日志服务器。
- sudo 使用时间戳文件来执行类似的“检票”系统。当用户调用 sudo 并且输入它的密码时,用户获得了一张存活期为 5 分钟的票(这个值可以在编译的时候改变)。
- sudo 的配置文件是 sudoers 文件,它允许系统管理员集中的管理用户的使用权限和使用的主机。它所存放的位置默认是在 /etc/sudoers,属性必须为 0411。
sudo 命令格式:
sudo [command]
当然,sudo 的前提是在 /etc/sudoers 中正确的设置了各种权限。打开该文件,有很多已经定义了的 alias,包括命令、用户组、权限、机器等。但是没有授权的信息,授权的文字习惯性的添加在这个文件的最后一行,格式为:
[root@training tmp]# tail -1 /etc/sudoers zhang ALL=(root) NOPASSWD: /bin/vi
其中:
- “zhang”为用户名,即为哪个用户授权,这里可以是自定义或系统预定义的 alias。
- “ALL”为可执行机器,这里即为所有机器。这个字段可以定义多台机器,多个网络地址,但是在非域控的机器上,即使填写 ALL 也只能对自己本机操作。如果在非域控机器上,这个字段建议填写 ALL 或者本机 hostname。
- “=”是个分隔符,必须有的,可以理解为固定格式。
- “(root)”这个字段表示以谁的身份来执行,可以不填,默认是 root。在有些机器上可以是 sysdba 等角色。
- “NPPASSWD:”这个字段代表该用户执行以下命令时,可以不用再次输入密码,可以不填写。
- “/bin/vi”表示可以执行的命令,必须使用绝对路径,可以填写多个,以“,”分割。也可以使用 alias 做预定义。
sudoers 中的各种预定义:
第一部分:用户定义,将用户分为 SYSADMINS 和 PARTSYS 两类。
User_Alias SYSADMINS = zhang,wu
User_Alias PARTSYS = zhaowei
注意:预定义的各种名字需要大写,预定义的组里面可以有一个元素,也可以由多个元素,多个元素用”,”隔开。
第二部分,将操作类型分类(意义不大,不建议使用,可以直接只用 root,oracle 等)。
Runas_Alias OP = root, operator
Runas_Alias DB = oracle, Sybase
第三部分,将主机分类(涉及到域控机器,目前意义不大,建议不操作)。
Host_Alias SERVERS = master, mail, www, ns
第四部分,定义命令和命令地路径。命令一定要使用绝对路径,避免其他目录的同名命令被执行,造成安全隐患 。
Cmnd_Alias USERADD = /usr/sbin/useradd,/usr/sbin/passwd
Cmnd_Alias SHUTDOWN = /sbin/shutdown,/sbin/reboot
系统本身带有一部分 alias,可以使用。自定义的 alias 放在任何位置都可以,不想使用的可以在行首加“#”注释掉。将上述行加入 /etc/sudoers.
[root@training ~]# tail -10 /etc/sudoers User_Alias SYSADMINS = zhang,wu User_Alias PARTSYS = zhaowei Runas_Alias OP = root, operator Runas_Alias DB = oracle, Sybase Cmnd_Alias USERADD = /usr/sbin/useradd,/usr/sbin/passwd Cmnd_Alias SHUTDOWN = /sbin/shutdown,/sbin/reboot
sudo 的功能很强大,有兴趣的可以继续研究,sudo 甚至支持部分的正则表达,让 root 的权限真正细分。
注意:sudo对于权限管理很有用,但是往往在实际工作中却并没有将 sudo 的功能发挥出来。一般只是系统工程师简单地使用一些功能。原因如下:
- 在域环境下,sudoers 文件对于域内所有机器有效,但是如果域控机器出现问题,整个域机器的权限管理立刻混乱,风险太大。
- 在非域环境下,sudoers 文件对本机有效,所有的机器都是个性化配置,工作量大、维护困难。
2.4 iptables:防火墙
iptables 功能强大、完整,几乎是所有防火墙的底层协议。如果在局域网的接口处放置一台功能强大的 linux 主机,上面运行 iptables,可以为整个局域网提供防火墙功能。
注意:对于非防火墙功能的服务器而言,开启 iptables 意味着牺牲大量机器性能。局域网中,如果前端有防火墙,建议关闭 iptables。
为了验证 iptables 的功能,首先安装 apache 和制作简单地页面:
yum -y install httpd
service httpd start
echo "it works" > /var/www/index.html
在浏览器中输入 http://ip 查看是否有页面:
一、准备工作
检查当前 iptables 状态,在新服务器上启用 iptables 之前,需要将所有系统默认的规则(如果有)清空。
如果不是上面的状态,需要执行:
[root@training html]# iptables -F # 清除预设表 filter 中的所有规则链的规则。 [root@training html]# iptables -X # 清除预设表 filter 中使用者自定链中的规则。
在增加规则之前,一定要找到一种绕开端口和 ip 的操作 linux 的方法,比如直接在机器(虚拟机)上操作,比如 hp、dell 等服务器的远程管理 ilo 系统。
二、iptables 常用规则添加
iptables 遵循不被允许的就是禁止的规则。所以加入的前三条规则,会让这台机器完全与外界隔离(至少访问被隔离)。
1)添加初始规则,将访问本机的包全部禁止、外出的包全部放开、需要转发的包全部禁止。外出的包也可以禁止,之后所有向外访问都需要增加额外的规则,这样安全性更好,可以防止木马程序向外发送数据包。
- iptables 为命令,只有 root 可以使用。
- -P 参数为新建 iptables 规则链。
- “INPUT”、“OUTPUT”、“FORWARD”为三种主要 iptables 规则类型,在 iptables 中被称为“链”。这里分别对应“对本级访问”、“对外部访问”、“转发”,转发一般用作 nat 或者路由器,普通服务器只有选择包的网络出口时才使用。
- “DROP”、“ACCEPT”表示丢弃或者允许。
此时使用 ssh 连接机器是不通的,已经联通的 ssh 进程也会断开。
2)添加 sshd 规则,使机器可以远程访问。
- “-A INPUT”是向 INPUT 这个链中添加规则,该参数包括:-P 新建链、-A 增加规则、-D 删除规则、-I 插入规则(默认插到第一条规则,也可以指定规则号。iptables 按照顺序由上而下执行,所以有顺序区别)。这个参数必须紧跟 iptables 命令,不可以挪动顺序。
- “-d 192.168.1.0/24”指定目标或者源 ip。其中 -d 参数也可写为 -destination,来源 ip,代表从哪个 ip 访问进来。相对的有 -s 参数也可以写为 -source,目标 ip 代表要访问哪个 ip。后跟 ip 地址或者 ip 段,ip 段的掩码用数字表示。
- “-p tcp”指定使用什么样的协议,有 tcp 和 udp 和 icmp。
- “-dport 22”指定端口,有访问来源需要访问端口—dport和外出目标需要经过的端口 -sport。(注意,这里均指本机的端口,无论进出,都指通过的本机端口)。如果 ssh 开的不是默认的 22 端口,需要修改端口号。
- “-j ACCEPT”需要执行的动作,一般这里都用 -j 参数,后面有两个动作“ACCEPT”和“DROP”。
这时候,又可以使用 crt 访问 linux 了。
注意:所有规则都需要保存,保存后重启才能保留所有规则,如果不保存,只能当前生效,重启后失效。
另外,service 这个命令其实是一个调用,使用 iptables 的路径也可以执行保存。
思考:/etc/init.d/iptables 和 /sbin/iptables 有什么区别和联系?
注意:如果在最初新建链的时候,执行了 iptables -p OUTPUT DROP,那么每增加一条进来的 accept 规则,基本上要对应的增加一条或者多条出去的 accept 规则。就 ssh 来说,需要增加:
iptables -A OUTPUT -s 192.168.1.0/24 -p tcp –-sport 22 -j accept
注意:除了第一组参数外,其它参数顺序可变,也可以缺省。但是每缺省一个参数,都是多放开了一些权限,如果所有的参数缺省了,iptables 就没有意义了。
如图中所示,一条缺省的 accept 规则一般是黑客才干的事情。可以让本机所有端口对所有的机器开放。删除操作可以使用其序列号直接删除,如 iptables -D INPUT 2。
3)添加 http 的访问权限
目前是访问不了的:
打开权限:
80 端口一般是对所有人开放的,这里就不需要对来源 ip 做限制了。
iptables 功能强大,可以在防火墙、路由、nat 转发等领域使用。
2.5 让服务器可以暴露于公网
一台新装的机器,做怎样的操作才能放到公网上?一般需要以下几个步骤(只列举安全的步骤):
1)使用在维护的操作系统和软件的最新最稳定版本。root 密码和普通用户密码都要符合强密码规范,用户尽量少。
2)修改 ssh 默认端口,使用 20000-30000 之间的一个端口。
修改 /etc/ssh/sshd_config 如下图所示:
- Port 22 前的 # 去掉,将 22 端口进行修改。
保存退出后执行 service sshd restart。
3)禁止 root 直接登录,只能通过 su - root和 sudo 的形式使用 root,这样可以增加一层密码控制。也使获得 root 权限更加困难。
修改 /etc/ssh/sshd_config 如下图所示:
- 将 PermitRootLogin 前的 # 去掉,并且 yes 改为 no。
保存退出后执行 service sshd restart。
4)启动 tcp_wrapper 或者 iptables
- 在前端有防火墙的情况下,使用 wrapper;没有防火墙使用 iptables。都要使用不被允许的就是禁止的规则,都要严格限制远程登录,尽量每台机器放开一个对外的服务端口(比如 80)。
- 如果前端防火墙设置比较宽松(比如没有禁止 ping),建议使用 iptables。
5)删除系统多余的账号和组
系统中有可能存在一些用于服务的用户和组,大部分是不需要的,删除掉。真有需要可以添加。
- 用户:adm,lp,sync,shutdown,halt,news,uucp,operator,games,gopher,ftp
- 组:adm,lp,news,uucp,games,pppusers,dip,slipusers
6)控制应用安全
不同的应用有不同的安全策略,比如 apache 需要关闭目录访问、关闭 keepalive 等。所以要谨慎对待任何开放了端口的应用。
7)定期检查各种日志
包括:last\/var/log/secure,/var/log/message 以及应用的日志。
另外,iptables 是可以开启日志系统的,比如可以针对 drop 的日志记录。
3. 系统优化
3.1 系统瘦身
任何进程都会占系统的资源,包括启动时间、cpu、mem、文件句柄等。在系统安装最初,采取了尽量精简的安装已经让系统“瘦身”初步成功,但是还不够,系统默认启动的许多进程和服务仍然是不必要的。
一、系统默认启动级别
系统默认启动级别有 6 种,但是实际上可以正常使用的是有两种。/etc/inittab 文件中有详细介绍:
- 0:挂起,相当于关机,如果将 initdefault 设置为 0,机器将无法启动,除非使用启动盘;
- 1:单用户模式,用于维护系统。一般在丢失 root、磁盘损坏等情况下进入,不需要在这里设置进入单用户,有专门的进入单用户方法;
- 2:和 3 一样,只是少了网络,一般不会使用;
- 3:字符模式,不启动图形界面,其它进程均启动(如果定义的话);
- 4:保留,未使用;
- 5:图形界面模式;
- 6:重新启动,如果 initdefault 定义为 6,机器将不停重启。
常用的模式有三种,单用户、字符模式和图形界面模式。但是单用户模式不在这里设置,只剩下两种模式。如果安装时安装有图形系统,这里将会是 5;如果没有安装图形系统,这里将会是 3。
字符模式开机后将进入一个终端,和 crt 连接 linux 类似(crt 无法启动桌面系统)。如下图:
图形模式开机后将进入一个桌面系统。
建议使用 3 的模式,即使安装了图形系统,在机器启动时也是不需要加载的。使用字符模式启动,可以节省大量的启动时间和减少所有图形相关的进程。
二、关闭或者打开系统默认启动项
- chkconfig --level 135 servicename off:关闭某项系统服务的自动启动
- chkconfig --level 135 servicename on:打开某项系统服务的自动启动
其中 135 代表的是在单用户模式下、字符模式下和图形模式下。这三种模式为常用模式,这三种模式的服务保持一致不会出现混淆。
关掉不必要的系统服务:
将以下行写入脚本文件中(比如 close.sh),直接执行 sh close.sh。
chkconfig --level 2345 acpid off chkconfig --level 2345 anacron off chkconfig --level 2345 atd off chkconfig --level 2345 auditd off chkconfig --level 2345 autofs off chkconfig --level 2345 avahi-daemon off chkconfig --level 2345 bluetooth off chkconfig --level 2345 cpuspeed off chkconfig --level 2345 cups off chkconfig --level 2345 firstboot off chkconfig --level 2345 gpm off chkconfig --level 2345 haldaemon off chkconfig --level 2345 hidd off chkconfig --level 2345 ip6tables off chkconfig --level 2345 iptables off chkconfig --level 2345 irqbalance off chkconfig --level 2345 isdn off chkconfig --level 2345 kudzu off chkconfig --level 2345 lm_sensors off chkconfig --level 2345 lvm2-monitor off chkconfig --level 2345 mcstrans off chkconfig --level 2345 mdmonitor off chkconfig --level 2345 messagebus off chkconfig --level 2345 microcode_ctl off chkconfig --level 2345 netfs off chkconfig --level 2345 nfslock off chkconfig --level 2345 pcscd off chkconfig --level 2345 portmap off chkconfig --level 2345 rawdevices off chkconfig --level 2345 readahead_early off chkconfig --level 2345 restorecond off chkconfig --level 2345 rpcgssd off chkconfig --level 2345 rpcidmapd off chkconfig --level 2345 sendmail off chkconfig --level 2345 setroubleshoot off chkconfig --level 2345 smartd off chkconfig --level 2345 snmpd off chkconfig --level 2345 xfs off chkconfig --level 2345 xinetd off chkconfig --level 2345 yum-updatesd off
重启机器后,上述服务将不再自动启动。
查看当前启系统服务自动启动情况:chkconfig --list。
3.2 修改系统的 limit
Linux 系统对用户有各种各样的限制,这些限制保证了机器的稳定。举个例子,系统默认对用户打开的文件数限制为 1024 个,为了避免用户过多打开文件导致内存不够使用或者系统文件数不够使用等问题。但是如果服务器也被限制到打开 1024 文件,apache 进程就只能有不到 1024 个连接进来,如果使用 root 用户启动 apache,甚至只有几百个连接可以访问进来。
所以,对于服务器来说,要打开一些限制,使服务能够最大程度的使用系统资源。
查看 ulimit 方法:
上图中,需要放开限制的常用的有两个值,open files 和 max user processes。一般加到 65535 这个值。
所以需要以 root 身份执行一下两条命令:
可以看到,两个目标值都已经修改为 65535。但是这个修改在重启机器后将失效,所以将这两个命令放在 root 的 profile 文件中。
echo "ulimit –n 65535" >> /root/.bash_profile echo "ulimit –u 65535" >> /root/.bash_profile
注意:ulimit 命令只有 root 可以使用,所以放在 root 的环境变量中可以生效。如果放置在全局变量中,该命令不会生效,普通用户登录时还会报错:
-bash: ulimit: max user processes: cannot modify limit: Operation not permitted
放在 root 的环境变量中,只有 root 用户登录后,这两条命令才会生效,这之后启动的用户才能用到 65535 的文件数和进程数,等 root 退出后,之后的用户和进程再次受到严格的限制。所以,如果使用 ulimit 命令修改了限制,一般会使用 root 启动服务进程。
上述方法使用有一定的局限性,可以更简单的使这个值生效,而不需要 root 用户登录,方法:
在 /etc/ security/limits.conf 文件中加入以下四行:
* soft nproc 65535 * hard nproc 65535 * soft nofile 65535 * hard nofile 65535
注意,这种方法虽然方便,但是等于将机器完全打开了限制。有可能造成比较严重的后果,因为大家习惯性在使用 root 的时候很谨慎,在使用普通用户的时候相对随便。使用这个方法后,如果某个用户再写一个测试脚本,里面有死循环,无论是生成子进程的死循环还是打开文件的死循环,都会导致机器资源用尽。
3.3 修改系统运行参数
系统的运行参数可以直接优化,也可以通过修改 /etc/sysctl.conf 生效。因为系统运行参数很重要、很敏感,如果不确定某参数的实际意义,请不要随意修改。