PHP 服务器CPU飙升排查工具

1.使用top查询出占用资源最高的程序和pid

[root@VM-12-9-centos ~]# top
top - 10:34:51 up 151 days, 14:46,  4 users,  load average: 7.88, 8.00, 8.13
Tasks: 198 total,   8 running, 190 sleeping,   0 stopped,   0 zombie
%Cpu(s): 20.0 us, 79.8 sy,  0.0 ni,  0.1 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem :  8008644 total,   211792 free,  3804488 used,  3992364 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  3859032 avail Mem 
PID to signal/kill [default pid = 8817] ill -9 
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                             
 8817 root      20   0  250904  33572   2688 R   3.0  0.4   6287:50 php                                                                                                                 
 9552 root      20   0  248128  34480   6296 S   2.7  0.4   5596:32 php                                                                                                                 
 9562 root      20   0  248128  34480   6296 S   2.7  0.4   5451:31 php                                                                                                                 
 9554 root      20   0  248128  34480   6296 S   2.3  0.4   5505:47 php                                                                                                                 
 9564 root      20   0  248128  34484   6296 S   2.3  0.4   5345:03 php                                                                                                                 
 3297 root      20   0  993820  77192  18748 S   1.3  1.0 140:27.37 YDService                                                                                                           
12284 root      20   0  156856   5616   4272 R   1.0  0.1   0:00.13 sshd                                                                                                                
15865 root      20   0  126348   1220   1008 R   1.0  0.0   0:00.14 strace                                                                                                              
17619 root      20   0  842824  19204   3068 S   1.0  0.2   2237:00 barad_agent                                                                                                         
27958 root      20   0  787048  86856  15340 S   0.7  1.1   0:40.60 BT-Panel                                                                                                            
 4473 root      20   0 1070600  13988   6592 S   0.3  0.2   1:49.62 YDLive                                                                                                              
28200 root      20   0 1384064  20300   6200 S   0.3  0.3   1:38.29 BT-Task                                                                                                             
    1 root      20   0   51916   4000   2456 S   0.0  0.0  43:41.89 systemd                                                                                                             
    2 root      20   0       0      0      0 S   0.0  0.0   0:07.34 kthreadd                                                                                                            
    4 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                                                                                        
    6 root      20   0       0      0      0 S   0.0  0.0  60:43.14 ksoftirqd/0                                                                                                         
    7 root      rt   0       0      0      0 S   0.0  0.0   0:34.60 migration/0                                                                                                         
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.04 rcu_bh                                                                                                              
    9 root      20   0       0      0      0 S   0.0  0.0 381:47.98 rcu_sched                                                                                                           
   10 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 lru-add-drain                                                                                                       
   11 root      rt   0       0      0      0 S   0.0  0.0   3:03.63 watchdog/0                                                                                                          
   12 root      rt   0       0      0      0 S   0.0  0.0   3:04.37 watchdog/1                                                                                                          
   13 root      rt   0       0      0      0 S   0.0  0.0   0:35.39 migration/1                                                                                                         
   14 root      20   0       0      0      0 R   0.0  0.0  57:27.61 ksoftirqd/1                                                                                                         
   16 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0H                                                                                                        
   17 root      rt   0       0      0      0 S   0.0  0.0   3:02.59 watchdog/2                                                                                                          
   18 root      rt   0       0      0      0 S   0.0  0.0   0:35.17 migration/2                                                                                                         
   19 root      20   0       0      0      0 S   0.0  0.0  57:48.05 ksoftirqd/2                                                                                                         
   21 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/2:0H                                                                                                        
   22 root      rt   0       0      0      0 S   0.0  0.0   3:10.39 watchdog/3                                                                                                          
   23 root      rt   0       0      0      0 S   0.0  0.0   0:34.69 migration/3                                                                                                         
   24 root      20   0       0      0      0 S   0.0  0.0  59:06.12 ksoftirqd/3                                                                                                         
   26 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/3:0H                                                                                                        
   28 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kdevtmpfs                                                                                                           
   29 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 netns                                                                                                               
   30 root      20   0       0      0      0 S   0.0  0.0   0:07.67 khungtaskd        

可以看到我前面的基本都是PHP程序

2.通过srrace -p PID 跟踪指定pid的系统调用及其接收的信号

root@VM-12-9-centos ~]# strace -p 8817
strace: Process 8817 attached
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 255}], WSTOPPED, NULL) = 15863
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=15863, si_uid=0, si_status=255, si_utime=0, si_stime=1} ---
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman/workerman/../workerman.log", 0x7ffc3c6f0af0) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman/workerman", 0x7ffc3c6f0820) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman", 0x7ffc3c6f06a0) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor", 0x7ffc3c6f0520) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service", 0x7ffc3c6f03b0) = -1 ENOENT (No such file or directory)
open("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman/workerman.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = -1 ENOENT (No such file or directory)
fstat(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
ioctl(1, TCGETS, 0x7ffc3c6f3690)        = -1 ENOTTY (Inappropriate ioctl for device)
write(1, "file_put_contents(/www/wwwroot/j"..., 248) = 248
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f779ac30a10) = 15874
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 255}], WSTOPPED, NULL) = 15874
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=15874, si_uid=0, si_status=255, si_utime=0, si_stime=1} ---
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman/workerman/../workerman.log", 0x7ffc3c6f0af0) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman/workerman", 0x7ffc3c6f0820) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman", 0x7ffc3c6f06a0) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service/vendor", 0x7ffc3c6f0520) = -1 ENOENT (No such file or directory)
lstat("/www/wwwroot/jys.bolinshe.com/service", 0x7ffc3c6f03b0) = -1 ENOENT (No such file or directory)
open("/www/wwwroot/jys.bolinshe.com/service/vendor/workerman/workerman.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = -1 ENOENT (No such file or directory)
fstat(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
ioctl(1, TCGETS, 0x7ffc3c6f3690)        = -1 ENOTTY (Inappropriate ioctl for device)
write(1, "file_put_contents(/www/wwwroot/j"..., 248) = 248

发现是这个站点的workerman导致的
3.先kill掉进程,恢复服务器性能,在到站点排查具体的问题

另外:如果是Java程序有大厂开发的 arthas 工具,可以找到Java程序具体第几行出现问题

记一次MySQL数据恢复处理

前因:

今天星期六,上午正在逛市场,突然老板打电话来说服务器掉线了,刚开始以为只是普通问题,让自己联系机房就好了,先把服务器跑起来,让用户可以访问,一些自动化处理程序等我回去了再启动。

结果机房说服务器系统坏了,跑不起来,只能重新搭建服务
于是赶紧回家,让机房把硬盘挂到别的机器上,想办法把数据给弄出来
把旧硬盘挂到新机器后,开始了数据操作,一开始想的是把旧硬盘的MySQL跑起来,在用工具导出来就好了,结果MySQL跑不起来了。

由于新机器没有按照任何环境,无法直接使用systemctl start mysql,新机器也没有MySQL的配置文件,于是另辟蹊径

1.找个新的配置文件(my.cnf) 放到 /etc/my.conf(刚好旧硬盘里有之前的my.cnf文件)
2.进入MySQL的安装目录直接操作 ./mysql --defaults-file=/etc/my.cnf (--defaults-file=/etc/my.cnf 指定启动的配置文件)
3.启动

报错

[root@xslmbllajezxnqw bin]# ./mysqld --defaults-file=/etc/my.cnf
2024-11-23T15:00:17.085523Z 0 [Warning] [MY-000081] [Server] option 'max_allowed_packet': unsigned value 107374182400 adjusted to 1073741824.
2024-11-23T15:00:17.085604Z 0 [Warning] [MY-010915] [Server] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release.
2024-11-23T15:00:17.085714Z 0 [System] [MY-010116] [Server] /data/www/server/mysql/bin/mysqld (mysqld 8.0.24) starting as process 31595
2024-11-23T15:00:17.099843Z 0 [ERROR] [MY-010123] [Server] Fatal error: Please read "Security" section of the manual to find out how to run mysqld as root!
2024-11-23T15:00:17.100066Z 0 [ERROR] [MY-010119] [Server] Aborting
2024-11-23T15:00:17.118879Z 0 [System] [MY-010910] [Server] /data/www/server/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.24)  Source distribution

注意报错信息同有个 Please read "Security" section of the manual to find out how to run mysqld as root! 提示,要求不能使用root用户启动

于是再创建一个账户useradd www
将MySQL的数据目录所有权更改为www用户

再次启动./mysqld --defaults-file=/etc/my.cnf --user=www

[root@xslmbllajezxnqw bin]# ./mysqld --defaults-file=/etc/my.cnf --user=www
2024-11-23T07:48:47.965407Z 0 [Warning] [MY-000081] [Server] option 'max_allowed_packet': unsigned value 107374182400 adjusted to 1073741824.
2024-11-23T07:48:47.965490Z 0 [Warning] [MY-010915] [Server] 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and 'ERROR_FOR_DIVISION_BY_ZERO' sql modes should be used with strict mode. They will be merged with strict mode in a future release.
2024-11-23T07:48:47.965601Z 0 [System] [MY-010116] [Server] /data/www/server/mysql/bin/mysqld (mysqld 8.0.24) starting as process 26261
2024-11-23T07:48:48.008578Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-11-23T07:48:54.506873Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-11-23T07:48:54.745099Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /tmp/mysqlx.sock
2024-11-23T07:48:55.075232Z 0 [Warning] [MY-013595] [Server] Failed to initialize TLS for channel: mysql_main. See below for the description of exact issue.
2024-11-23T07:48:55.075566Z 0 [Warning] [MY-010069] [Server] Failed to set up SSL because of the following SSL library error: <%.*s|%.*s
2024-11-23T07:48:55.138937Z 0 [Warning] [MY-011302] [Server] Plugin mysqlx reported: 'Failed at SSL configuration: "SSL context is not usable without certificate and private key"'
2024-11-23T07:48:55.139080Z 0 [System] [MY-010931] [Server] /data/www/server/mysql/bin/mysqld: ready for connections. Version: '8.0.24'  socket: '/tmp/mysql.sock'  port: 3306  Source distribution.

成功

只要MySQL跑起来,后面安装普遍流程来操作就可以了

  • navcat
  • mysqldump

用上面的任一都行

写这篇文章用时30分钟不到,按照我一开始的想法是对的,但实际解决这个问题搞了大半天,期间老板一直再问好了吗? ,搞得我快要爆炸了

使用shell拉取代码并部署

#!/bin/bash

# @Author: admin
# @Date:   2023-11-22 17:20:22
# @Last Modified by:   admin
# @Last Modified time: 2023-11-22 20:58:01

# 添加部署脚本
# 首先给脚本执行权限 chmod +x ./deploy.sh
# 使用: ./gitee.sh
# 或: ./deploy.sh www  // www为最终发布目录的所属用户
# 源码将发布到 destDir设置的目录下

# read -p "请输入gitee账号 :" username

# while true
# do
#         if [ ! -n "$username" ];then
#                 read -p "必须输入请输入gitee账号 或者q退出:" username

#         else
#                 if [ "$username" = "q" ];then
#                         exit 0
#                     else
#                         break
#                 fi

#         fi

# done

# read -p "请输入gitee密码 :" password

# while true
# do
#         if [ ! -n "$password" ];then
#                 read -p "必须输入请输入gitee密码 或者q退出:" password

#         else
#                 if [ "$password" = "q" ];then
#                         exit 0
#                     else
#                         break
#                 fi

#         fi

# done


echo '--初始化目录--'
# 临时目录,多个仓库应该使用不同的临时目录
tmpDir="$(pwd)/.qqmasterTemp"
# 部署目录不能与脚本所有目录相同
newDir="$(pwd)/qqmaster"


if [ ! -e "$tmpDir" ];then

    mkdir "$tmpDir"
fi

if [ ! -e "$newDir" ];then

    mkdir "$newDir"
fi



# 代码仓库目录 deploy:gitlab-ci-token修改为部署令牌和密码,也可以是gitlab用户和密码
repository="https://gitee.com/wangzh/qqmaster.git"


# if [ -d $tmpDir ]
# then
#     rm -rf $tmpDir
# fi

echo '--拉取代码--'
git clone $repository $tmpDir

echo '--拉取完成--'

#切換分支
echo '--切換分支--'
cd $tmpDir && git checkout dev

echo '--刪除不能覆蓋的文件--'
cd $tmpDir && rm -rf ApiAdmin/.env && rm -rf ApiAdmin/config && rm -rf ApiAdmin/.git && rm -rf ApiAdmin/cert


# 拷贝源码到部署目录
echo '--拷贝源码到部署目录--'
cd $tmpDir && cp -rf "./" $newDir

echo '--为项目赋权--'
cd $newDir && sudo -S chown -R www:www ./*  && sudo -S chmod -R 755 ./*

echo '--移除临时目录--'
rm -rf $tmpDir


echo "--发布完成--"

此方法的好处是可以避免一些冲突提示

此方法的缺点是仓库用的是码云的,每次使用https方式拉取都要输入账号密码

Linux硬盘挂载

输入 lsblk-f 查看所有设备的挂载情况
2023-11-13T03:12:04.png
例如我的是 /dev/sdb

将新添加的硬盘分区 输入命令fdisk /dev/sdb
2023-11-13T03:12:11.png
输入p创建主分区
2023-11-13T03:12:29.png
默认1即可
2023-11-13T03:13:00.png

分区创建好了之后 输入 w 保存退出
2023-11-13T03:14:18.png

分区创建好了之后 将分区格式化 格式化命令 mkfs -t ext4 /dev/sdb
2023-11-13T03:14:55.png

所有操作完成后就可以开始挂载了
mount /dev/sdb /指定文件的路径

挂载完后后设置开机自动挂载

先使用 df -TH 查看硬盘列表
2023-11-13T03:17:24.png

查看挂载的磁盘属性
2023-11-13T03:18:44.png

打开配置文件,写入自动配置
2023-11-13T03:19:42.png

参数说明:
第一列为UUID,此处填写查询到的磁盘分区的UUID
第二列为磁盘分区的挂载目录,可以通过df -TH命令查询
第三列为磁盘分区的文件系统格式,可以通过df -TH命令查询
第四列为磁盘分区的挂载选项,此处通常设置为defaults即可
第五列为Linux dump备份选项
(1) 0表示不使用Linux dump备份。现在通常不使用dump备份,此处设置为0即可。
(2) 表示使用Linux dump备份。
第六列为fsck选项,即开机时是否使用fsck检查磁盘。
(1) 0表示不检验。
(2) 挂载点为(/)根目录的分区,此处必须填写1。
(3) 根分区设置为1,其他分区只能从2开始,系统会按照数字从小到大依次检查下去。

最后保存配置即可

sh脚本拉取线上代码部署网站

#!/bin/bash

# 添加部署脚本
# 首先给脚本执行权限 chmod +x ./deploy.sh
# 使用: ./deploy.sh
# 或: ./deploy.sh www  // www为最终发布目录的所属用户
# 源码将发布到 destDir设置的目录下

user=${1:-"none"}
# 当前用户密码,用于sudo提权
sudoPwd=""
# 临时目录,多个仓库应该使用不同的临时目录
tmpDir="$(pwd)/.deploy"
# 部署目录不能与脚本所有目录相同
destDir="$(pwd)/destDir"
# 代码仓库目录 deploy:gitlab-ci-token修改为部署令牌和密码,也可以是gitlab用户和密码
repository="http://deploy:gitlab-ci-token@git仓库地址"

echo '初始化目录'
if [ -d $tmpDir ]
then
    rm -rf $tmpDir
fi

echo '拉取代码'
git clone $repository $tmpDir

rm -rf $tmpDir/.git
echo '发布代码'
# 拷贝源码到部署目录
cp -rf $tmpDir $destDir

if [ "$user" != "none" ]
then
    if [ "$sudoPwd" = "" ]
    then
        echo '缺少用户密码'
        exit 1
    fi
    # 修改目录权限
    echo "$sudoPwd" | sudo -S chown -R $user: $destDir
fi

echo '移除仓库'
rm -rf $tmpDir

echo '发布完成'

搭建ssr

CentOS 6和7/Debian6+/Ubuntu14+ ShadowsocksR/Shadowsocks一键部署管理脚本:

yum -y install wget
wget -N --no-check-certificate https://raw.githubusercontent.com/ToyoDAdoubiBackup/doubi/master/ss-go.sh && chmod +x ss-go.sh && bash ss-go.sh
  • 如果搭建SSR账号,请使用脚本一,目前推荐的SSR参数设置为以下,有利于突破网络封锁,参数如下:
  1. 加密方式:none 协议:origin 混淆:tls1.2_ticket_auth
  2. 加密方式:none 协议:auth_chain_a 混淆:tls1.2_ticket_auth
  3. 如果搭建SS账号,请使用脚本二,加密方式可选aes-256-gcm,或者高阶篇的SS+插件模式(推荐)
  4. 推荐搭建SSR账号。

安装完成后,快捷管理命令:

bash ssr.sh

编写shell脚本快速切换PHP版本

由于我是在windows的wsl搭建的PHP环境,包括7.3、7.4、8.0多个PHP版本,测试的时候,有的程序需要某个版本才能运行,手动创建环境变量太麻烦,于是写了我的第一个shell,于是记录下

#!/bin/bash
#第一次提示
read -p "请输入版本号【7.3】、【7.4】、【8】:" version

#如果未输入,则强制要求输入
while [ ! "$version" ]
        do
        if [ ! -n "$version" ]; then
                read -p "必须输入版本号【7.3】、【7.4】、【8】:" version
        fi
done


#先删除现在的环境
rm -rf /usr/bin/php
rm -rf /usr/bin/phpize
rm -rf /usr/bin/php-fpm

#根据输入的版本号创建新的环境变量
case $version in
        7.3)
                #echo "你输入了${version} (7.3 对吗?)"
                ln -s  /usr/local/php/bin/php /usr/bin/php
                ln -s  /usr/local/php/bin/phpize /usr/bin/phpize
                ln -s  /usr/local/php/sbin/php-fpm /usr/bin/php-fpm
        ;;
        7.4)
                #echo "你输入了${version}(7.4对吗)"
                ln -s  /usr/php/74/bin/php /usr/bin/php
                ln -s  /usr/php/74/bin/phpize /usr/bin/phpize
                ln -s  /usr/php/74/sbin/php-fpm /usr/bin/php-fpm
        ;;
        8)
                #echo "你输入了${version}(8对吗)"
                ln -s  /usr/local/php8/bin/php /usr/bin/php
                ln -s  /usr/local/php8/bin/phpize /usr/bin/phpize
                ln -s  /usr/local/php8/sbin/php-fpm /usr/bin/php-fpm
        ;;
        *)
                echo "当前系统未安装此版本号的PHP,无法切换"
        ;;
esac

#检查下是否成功切换
        echo "你已成功切换到${version}"![微信截图_20211029113209.png][1]
        echo "======================================================"
                php -v
        echo "======================================================"

请输入图片描述

解决TP5在命令行创建文件没有权限写入的方法

例如workerman指定user为www运行
在cli模式下创建的文件是root权限的,无法写入log导致程序无法执行

找到 thinkphp\library\think\log\driver\File.php 文件
write 方法中 最后一行添加以下代码

try {
//判断操作文件不是0777权限 就修改
if (substr(base_convert(fileperms($destination),10,8),-4) != '0777') {
  chmod($destination, 0777);
}
            
} catch (\Exception $e) {

}