Linux Top命令详细记录

最近服务器经常出问题,所以用命令 top 分析其性能,在这里对其做个记录,便于以后查看。top 是常用的性能分析命令,基本和 windows 的任务管理器类似,下面详细介绍使用方法。

> top
top - 10:36:26 up 72 days, 22:21,  1 user,  load average: 0.00, 0.01, 0.05
Tasks:  81 total,   1 running,  80 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.3 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1883844 total,    99960 free,   375164 used,  1408720 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1306676 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
    1 root      20   0   43276   2556   1348 S  0.0  0.1   4:19.02 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.02 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   1:20.24 ksoftirqd/0
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    7 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
    9 root      20   0       0      0      0 S  0.0  0.0   9:45.47 rcu_sched
   10 root      rt   0       0      0      0 S  0.0  0.0   0:18.19 watchdog/0
下面将其参数做下详细的说明:

top - 10:36:26 up 72 days, 22:21,  1 user,  load average: 0.00, 0.01, 0.05
10:36:26:当前系统时间
up 72 days, 22:21:表示系统开机到现在的运行时间
1 user:当前登录系统的用户个数
load average:分别是1分钟、5分钟、15分钟的系统负载情况,
load average 数据是每隔5秒钟检查一次活跃的进程数,然后按特定算法计算出的数值。如果这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了。

 Tasks:  81 total,   1 running,  80 sleeping,   0 stopped,   0 zombie
可以根据其字面意思得到:系统现在共有 80 个进程,其中处于运行中的有 1 个,80 个在休眠(sleep),stoped 状态的有 0 个,zombie 状态(僵尸)的有 0 个。

%Cpu(s):  0.3 us,  0.3 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
CPU 的运转情况,后面值依次意思为:
用户空间占用CPU的百分比 ,内核空间占用CPU的百分比,改变过优先级的进程占用CPU的百分比,空闲CPU百分比,IO等待占用CPU的百分比,#,#

KiB Mem :  1883844 total,    99960 free,   375164 used,  1408720 buff/cache
内存的使用情况:1883844 总内存,99960 可使用内存,375164 已使用,1408720 缓存内存

KiB Swap:        0 total,        0 free,        0 used.  1306676 avail Mem
swap交换分区信息:0 total 总量,0 free 未使用,0 used 已使用

下面就是详细的进程信息:

PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                      
  1 root      20   0   43276   2556   1348 S  0.0  0.1   4:19.02 systemd
PID:进程ID
USER:进程所有者
PR:优先级,数值越大,优先级越高
NI:nice值。负值表示高优先级,正值表示低优先级
VIRT: 进程使用的虚拟内存总量,单位kb。VIRT = SWAP+RES
RES:进程使用的、未被换出的物理内存大小,单位kb。RES = CODE + DATA
SHR:共享内存大小,单位kb
S:进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
%CPU:上次更新到现在的CPU时间占用百分比
%MEM:进程使用的物理内存百分比
TIME+:进程使用的CPU时间总计,单位1/100秒
COMMAND:进程名称(命令名/命令行)

Linux常用命令

grep 文本搜索工具
-i 忽略大小写
-v 不显示匹配行
-c 显示符合条件的行数值

文本搜索支持正则表达式
cat /etc/passwd | grep root // 显示包含root的所有行
cat /etc/passwd | grep -v bash // 显示不包含bansh的所有行
grep 'search' ./ -r //查看当前目录下文件中有 search 的行

tar 解压缩
-x 解压文件
-z 支持giz方式
-j 支持bzip2方式
-v 显示操作过程
-f 制定文件
-C 解压到指定目录
-W 确认压缩文件的正确性
-t 显示压缩文件的内容

tar zxvf file.tar.gz // 解压当前文件
tar zxvf file.tar.gz -C /dir   //  解压文件到指定目录
tar zxvf file.tar.gz file // 将file文件解压出来
tar jxvf file.tar.gz2  // 解压giz2压缩的文件
tar zcvf file.tar.gz source  // 将source 文件压缩,多个文件用空格隔开
tar jcvf file.tar.gz2 source // 将source文件以giz2方式压缩,多个文件用空格隔开

查看压缩文件内容

tar -ztvf [filename] 压缩文件
tar -zcvf xx.tar.gz [filename/dir] //多目录文件用空格隔开解压文件
tar -zxvf file.tar.gz  // 解压到当前目录
tar -zxvf file.tar.gz -C [dir]  //解压到指定的目录下面

find 查找文件
格式: find [path] -name searchfile , 文件名支持正则表达式

find / -name 'root'  // 在根目录下面查找root的文件
find / -perm 777  // 查找权限为777的文件
find /home -user user  // 在home下查找属于user用户的文件
find /home -nouser   // 查找没有属主用户的文件
find /home -group group  // 查找属组为group的文件
find /home -nogroup  // 查找没有属组的文件
find /home -type d  // 查找类型为目录的文件

scp 文件安全传输

// local->remote 格式
scp srcfile remote_user@remote_ip:dest_dir
scp -r srcdir remote_user@remote_ip:dest_dir

// remote->local 格式
scp remote_user@remote_ip:dest_dir /localdir
scp -r remote_user@remote_ip:dest_dir /localdir

tail 查看文件最后10行信息

tail -n num file  // 查看制定行数num
tail -f file  // 时时查看写入文件的内容
tailf file // 和上面效果一样

head 查看文件头10行信息

head -n num file  // 查看制定行数num

cat查看文件全部内容

cat file  // 将文件全部内容打印到终端
cat -A file // 查看文件的存储结构,主要是空格和换行符
cat -b file  // 显示行号
cat /etc/passwd > file // 创建文件
cat file1 file2 > file //合并文件

ps查看进程命令
a 显示所有进程
c 显示进程的真实名
-A/-e 显示所有进程
-au 显示详细进程信息
-aux 显示所有包含使用者的进程
f 显示进程间的关系
-ef 显示全部进程间的关系
// 常用命令

ps -aux
ps -ef

netstat查看端口命令
-a 显示全部连接的socket
-A 列出网络类型
-n 直接显示ip地址,不用网络地址
-p 显示socket的识别码和程序名称
-t 显示tcp传输协议列表
-u 显示udp传输协议列表
// 常用命令

netstat -a
netstat -atnp
netstat -aunp

# 还可以配合 grep 使用sort 排序
cat /etc/passwd | sort // 一般都是针对某个结果进行排序

du 查看使用空间
-s 显示总计
-h 以K,M,G单位显示信息
-m 以MB单位输出
-k 以KB单位输出

du -sh file //查看文件目录总大小
du -c file1 file2 //显示多个文件大小,并显示总和
du -csh dir1 dir2 //显示多个目录总大小,和总和

pwd 查看路径命令

pwd  // 显示用户所在当前目录的路径
pwd -P  // 显示真实路径,物理路径

PHP trait 学习笔记

介绍
自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。
众所周知,PHP 中是单继承的,trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。
trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。
实例
首先我们举个例子来介绍 trait,和类定义相似,但使用关键字 trait 定义。在类中使用 use 组合。

trait T
{
    public function m1()
    {
        return 'm1';
    }

    public function m2()
    {
        return 'm2';
    }
}

class Demo
{
    use T;
    public function test()
    {
        return 'test';
    }
}

$demo = new Demo;
echo $demo->m1(), PHP_EOL;
echo $demo->test(), PHP_EOL;

使用多个 trait

trait T
{
    public function m1()
    {
        return 'm1';
    }

    public function m2()
    {
        return 'm2';
    }
}

trait T2
{
    public function m3()
    {
        return 'm3';
    }
}

class Demo
{
    use T, T2;
    public function test()
    {
        return 'test';
    }
}

$demo = new Demo;
echo $demo->m1(), PHP_EOL;
echo $demo->m3(), PHP_EOL;
echo $demo->test(), PHP_EOL;

多个 trait 冲突解决

如果使用多个 trait,但是出现了方法名相同,这是就出现了冲突,就要手动指定使用哪个 trait 的方法,使用 insteadof 关键字实现。

trait T
{
    public function m1()
    {
        return 'm1';
    }

    public function m2()
    {
        return 'm2';
    }
}

trait T2
{
    public function m1()
    {
        return 'm3';
    }
}

class Demo
{
    use T, T2{
        // 使用 T 的 m1 方法
        T::m1 insteadof T2;
    }
    public function test()
    {
        return 'test';
    }
}

$demo = new Demo;
echo $demo->m1(), PHP_EOL;
echo $demo->test(), PHP_EOL;

在冲突的时候,也可以使用 use 定义方法别名解决冲突,例子如下:

trait T
{
    public function m1()
    {
        return 'm1';
    }

    public function m2()
    {
        return 'm2';
    }
}

trait T2
{
    public function m1()
    {
        return 'm3';
    }
}

class Demo
{
    use T, T2{
        T::m1 insteadof T2;
        T2::m1 as new_m1;
    }
    public function test()
    {
        return 'test';
    }
}

$demo = new Demo;
echo $demo->m1(), PHP_EOL;
echo $demo->new_m1(), PHP_EOL;
echo $demo->test(), PHP_EOL;

改变访问权限
也可以使用 use 关键字来改变方法的访问权限。

trait T
{
    public function m1()
    {
        return 'm1';
    }

    public function m2()
    {
        return 'm2';
    }
}

class Demo
{
    use T{
        m2 as protected;
    }

    public function test()
    {
        return 'test';
    }
}

$demo = new Demo;
echo $demo->m1(), PHP_EOL;
echo $demo->m2(), PHP_EOL;
echo $demo->test(), PHP_EOL;

上面我只是介绍了一些常用的特性,详细可参考 官方手册。

PHP yield 读取大文件

今天来优化下读取大文件,在 PHP 读取大文件的时候,经常会出现内存不足的情况,如果文件过大的话,没法一次读取完,今天采用 yield 来实现大文件的读取。yield生成器是php5.5之后出现的,yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。yield生成器允许你 在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组。

老式读取方式

function readLocalFile($fileName)
{
  $handle = fopen($fileName, 'r');
  $lins = [];
  while (!feof($handle)) {
      $lines[] = fgets($handle);
  }
  fclose($handle);
  return $lines;
}

yield 读取方式
使用 yield 的特性,来读取大文件

function readYieldFile($fileName)
{
  $handle = fopen($fileName, 'r');
  while (!feof($handle)) {
      yield fgets($handle);
  }
  fclose($handle);
}

辅助函数
为了便于测试,我们写一个读取内存的辅助函数

function formatBytes($bytes)
{
  if ($bytes < 1024) {
      return $bytes . "b";
  } else if ($bytes < 1048576) {
      return round($bytes / 1024, 2) . "kb";
  }
  return round($bytes / 1048576, 2) . 'mb';
}

测试
我这里准备了一个 7M 大小的文本文件来做测试。

# 第一种
readLocalFile('./all.txt');
echo formatBytes(memory_get_peak_usage());  // 结果为 7.59mb

# 第二种
$lines = readYieldFile('./all.txt');
foreach ($lines as $row) {}
echo formatBytes(memory_get_peak_usage());  // 结果为 137.79kb

linux下查看http 并发和 tcp连接数

linux查看httpd进程数

ps -ef | grep httpd | wc -l

查看Apache的并发请求数及其TCP连接状态

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

(这条语句是从新浪互动社区事业部技术总监王老大那儿获得的,非常不错)

返回结果示例:
LAST_ACK 5 SYN_RECV 30 ESTABLISHED 1597 FIN_WAIT1 51 FIN_WAIT2 504 TIME_WAIT 1057
其中的SYN_RECV表示正在等待处理的请求数;ESTABLISHED表示正常数据传输状态;TIME_WAIT表示处理完毕,等待超时结束的请求数。(来源http://blog.s135.com/post/269/

linux并发连接数查看
1、查看Web服务器(Nginx Apache)的并发请求数及其TCP连接状态:

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
netstat -n|grep  ^tcp|awk '{print $NF}'|sort -nr|uniq -c
或者:

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'

返回结果一般如下:
LAST_ACK 5 (正在等待处理的请求数)
SYN_RECV 30
ESTABLISHED 1597 (正常数据传输状态)
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057 (处理完毕,等待超时结束的请求数)
其他参数说明:

CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉

2、查看Nginx运行进程数

ps -ef | grep nginx | wc -l

返回的数字就是nginx的运行进程数,如果是apache则执行

ps -ef | grep httpd | wc -l

3、查看Web服务器进程连接数:

netstat -antp | grep 80 | grep ESTABLISHED -c

4、查看MySQL进程连接数:

ps -axef | grep mysqld -c