Composer使用经验总结

切换国内镜像 composer 加速扩展包—— hirak/prestissimo 中文文档

–ignore-platform-reqs:  忽略 phphhvmlib-* 和 ext-* 要求并强制安装,就算本地环境不完全要求。平台配置选项可见 platform 文档

举例说明,windows平台的php不支持pcntl扩展,安装laravel-horizon时需要用的该扩展,可以通过指令强制安装

–with-all-dependencies:(-W)

 添加所有白名单中的依赖到白名单,包括那些根依赖,

允许升级、降级和删除目前锁定在特定版本的软件包。

composer require packagename:*

不确定当前项目可以使用扩展的哪个版本的时,可以使用require xxx:* 来计算是否有任何版本可以安装

laravel5.5安装horizon示例

依赖冲突

比如package A 和 B依赖相同的package C,但是版本不同,需要通过github 或packagelist 的composer.json 找到A和B依赖的最低版本C然后卸载C 然后安装适合版本的A和B,这样会自动安装最适合版本C

laravel 如何覆盖composer的 vendor类文件? 适用于需要修改vendor代码的场景

项目和框架运行缓慢

基于composer构建的项目出现过,加载运行缓慢的问题。碰到过旧laravel项目运行php artisan -v 时,命令显示非常慢。运行php artisan server 访问页面响应也很慢。

具体原因未验证,可能是安装依赖时,和运行项目时的php版本不一致,使用低版本安装了依赖,切换了高版本的php。composer安装项目后,会在vendor/bin目录下生成命令文件和缓存之类的,

解决方法,将vendor目录完全删除,然后重新运行composer install ,项目在升级或切换composer版本和php版本之后保险起见需要重新安装依赖

引入本地包

laravel-devstart 本地包的名称,path指定目录 要用基于当前项目路的相对路径,适用于开发扩展包

//设置路径,本质是创建了一个系统软连接
composer config repositories.laravel-devstart path ../../package/laravel-devstart
//引入本地包的master分支
composer require yangliuan/laravel-devstart:dev-master

扩展包开发

安装 Package Builder 包结构创建工具
composer global require overtrue/package-builder 
安装项目需要的依赖

修改composer.json

编写异常

编写单元测试

测试扩展包

发布版本到github

发布第一个版本

自动化测试

使用 GitHub Actions 做自动化测试

使用 StyleCI 自动修复代码格式

参考教程

LX2 PHP 扩展包实战教程 – 从入门到发布

PHP回顾之创建自己的扩展包 概述

扩展包版本对应

Laravel旧版本和扩展包对应版本,方便维护旧项目时参考

Laravel版本扩展包版本
5.5“laravel/horizon”: “2.1”
5.5“barryvdh/laravel-ide-helper”: “2.4.1”
5.5“doctrine/dbal”: “^2.10”
5.5“laravel/passport”: “~4.0”
5.5“laravel/tinker”: “~1.0”
5.5“propaganistas/laravel-phone”: “^4.2”
5.5“barryvdh/laravel-debugbar”: “3.4”,
5.5“filp/whoops”: “~2.0”
5.5“friendsofphp/php-cs-fixer”: “^2.14” 配置文件为.php_cs.dist

PHP 开发工具扩展包 使用笔记

前置知识

PHP代码风格指南

PSR 是 PHP Standard Recommendations (PHP 推荐标准)的简写,由 PHP FIG 组织制定的 PHP 规范,是 PHP 开发的实践标准。中文文档 例如composer 遵循psr4标准

很多php框架和组件都遵循psr规范,因此要编写遵循行业规范的代码

PHP-CS-Fixer

推荐在项目中安装配置,因为不同的项目php版本和规范不同,依赖的php-cs-fixer的版本也不相同

安装

composer require --dev friendsofphp/php-cs-fixer

项目根目录创建 .php-cs-fixer.php 配置文件(旧版本为.php_cs) 并且将它纳入git版本管理,保证该项目的所有开发人员都使用相同的规范

将缓存文件.php-cs-fixer.cache 添加到.gitignore文件中 (旧版本为.php_cs.cache)

规则和配置文件

可用内置规则地址 Laravel框架规则集地址

配置文件生成工具

点击问号,查看配置工具使用说明

通过规则风格筛选 比如php版本,psr12等

选中需要的规则

点击导出按钮生成规则配置文件

如何使用

手动使用方式 文档

#指定规则运行
$ php php-cs-fixer.phar fix /path/to/project --rules=@PSR12

#框架项目中指定配置文件手动修复,以laravel为例,在项目根目录下执行
$ vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php
#执行结果如下
Loaded config default from ".php-cs-fixer.php".
   1) app/Http/Controllers/Admin/CategoryController.php
   2) app/Http/Controllers/Admin/HotKeywordsController.php
  ... 此处省略中间部分输出信息
 205) routes/api.php
 206) tests/Feature/CommonApiTest.php
Fixed all files in 2.135 seconds, 20.000 MB memory used

php-cs-fixer vscode插件 github

扩展>>安装 ,个人配置项

{
   "php-cs-fixer.executablePath": "${extensionPath}/php-cs-fixer.phar",
   "php-cs-fixer.onsave": true,
   "[php]": {
        "editor.defaultFormatter": "junstyle.php-cs-fixer"
   },
}

PHPStan

付费替代品vscode 插件 PHP Intelephense 支持代码自动提示,跳转追踪和语法检测 99RMB永久授权

laravel版本 Larastan github 也是基于phpstan开发的

Laravel-ide-helper

安装

composer require --dev barryvdh/laravel-ide-helper

如果需要为模型生成字段,需要安装如下扩展包,参考文章是laravel5.5版本 跟laravel-ide-helper版本有关

laravel-ide-helper”: “^2.10″版本测试会自动安装doctrine/dbal 扩展包

composer require doctrine/dbal

生成配置文件 config目录下会生成ide-helper.php

php artisan vendor:publish --provider="Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider" --tag=config

为Facades生成文档提示,会在项目根目录下生成_ide_helper.php,可以根据团队需要决定是否将该文件加入.gitignore

php artisan ide-helper:generate

为模型生成注释,要在创建完成模型文件和数据迁移文件运行之后,若数据库字段有注释,则模型字段也会有注释

#不加命令参数给所有模型生成注释
php artisan ide-helper:models
#包含指定模型
php artisan ide-helper:models "App\Models\ExcelDemo"
#忽略指定模型
php artisan ide-helper:models --ignore="App\Models\BaseModel"
#会提示是否覆盖原模型,不覆盖会在根目录下生成_ide_helper_models.php文件,推荐no选项
 Do you want to overwrite the existing model files? Choose no to write to _ide_helper_models.php instead (yes/no) [no]:
 > 

使用 Travis-CI 做自动化测试

使用 StyleCI 自动修复代码格式

编辑器相关插件如下

Linux文件系统 FAQ

rm cannot remove xxx Read-only file system 无法删除文件

df dir 查看无法删除的目录所在的文件系统

df /snap/remmina/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/nvme0n1p2 479152840 195515620 259227828 43% /

fsck -y /   #执行修复文件系统 的挂载根目录 或者 有问题的文件所在的挂载目录;

shutdown -r now

再删除ubuntu系统中的snap应用文件时上述方法没有解决

使用df -h 查看 发现remmina中的 /snap/remmina/4978 的挂载点是/dev/loop12

sudo umount /dev/loop12 去掉挂载后,再删除就可以了 ,原因是磁盘的挂载目录无法直接被删除

PHP面试题2021-12-10

前言

  • 定位是后端开发工程师,大部分公司都需要转 go,并且这方面的知识如果不熟悉也可以明说,不会考查。如果面试官以前是做 php 的话,可能会问一些 php 的相关知识
  • 经典八股文一定要牢牢掌握,如果你不会的话就直说不会,千万不要强答(会减分),并不需要 100% 全答出来
  • 算法题做不出来通过的可能性很低,平时一定要多刷。不过除了字节,其他公司的算法题会相对简单一点,但总体上还是以 leetcode medium 难度为主(运气好的话 easy)

八股文

mysql

  • 有哪些事务隔离级别,Mysql 的事务隔离级别是怎么实现的?(每家都问)
  • 索引原理(每家都问)
  • 分库分表的策略,如果要按照分表字段以外的字段作为查询条件怎么办(每家都问)
  • MVCC 和间隙锁原理(滴滴 字节 百度)
  • explain 的 type 字段有哪些(知乎)
  • update 语句的执行流程,binlog 的作用和几种格式(滴滴)
  • 主从同步的原理和问题(字节 滴滴 陌陌)
  • 发生死锁的原因以及如何解决(滴滴 顺丰)
  • 如何优化大 offset(陌陌)

redis

  • 缓存如何保证一致性(每家都问)
  • 用过 redis 哪些数据结构,使用场景是什么(每家都问)
  • redis 的 connect 和 pconnect 的区别,pconnect 有什么问题(滴滴 陌陌)
  • redis 如何实现分布式锁,有什么问题(陌陌)
  • redis 为什么用跳表实现有序集合?原理,用有序集合的场景(字节 滴滴)
  • 主从同步的原理,哨兵和集群的区别(滴滴)
  • redis cluster 用的什么协议同步数据,哨兵的选举呢(陌陌)
  • rdb 和 aof 的原理(滴滴 高德)
  • 数据过期和淘汰策略(滴滴 高德 字节)
  • 缓存雪崩 击穿 穿透(滴滴 陌陌)

php

  • php-fpm 的生命周期,创建进程方式,各自的优缺点(腾讯 百度 滴滴 陌陌)
  • php 数组遍历为什么能保证有序(滴滴)
  • php 怎么实现的弱类型,怎么实现一个扩展(腾讯)
  • 常见魔术方法和函数(腾讯 滴滴)

es

  • 深度分页会有什么问题(滴滴 百度 陌陌)
  • 倒排索引的原理(字节 高德)
  • lsm 树原理(字节)

kafka

  • kafka 的架构,大致储存结构(高德 字节 滴滴)
  • 如果消费者数超过分区数会怎么样?(顺丰 滴滴)
  • 怎么保证数据的可靠投递?(陌陌 字节)
  • 消费者的 offset 存在哪里?(字节 腾讯 陌陌)
  • 如何通过 offset 定位消息?(字节)
  • 时间轮的原理(陌陌 顺丰)
  • kafka 写入高性能的原因,sendfile 和 mmap 原理,为什么不用 splice(滴滴)

网络

  • https 原理,tls 握手需要几个 rtt?(滴滴 百度)
  • 浏览器访问某个网址的详细过程,四次挥手(腾讯 滴滴)
  • http2 和 quic 原理(字节)

分布式系统

  • 分布式事务怎么处理(高德 陌陌)
  • 简述 raft 原理(陌陌)
  • 分布式 id 的几种实现和优缺点(滴滴)
  • 降级 限流 熔断实现原理(高德 陌陌)

其他

  • 布隆过滤器的实现原理和使用场景(滴滴)
  • 进程间通信有哪几种方式(腾讯)
  • 进程线程协程区别(滴滴 知乎)
  • lvs 原理,如何保证高可用(滴滴)
  • 502 504 什么原因,如何处理(滴滴 百度 腾讯 顺丰)
  • 给你两个一模一样的玻璃球,求出 100 层楼哪一层开始玻璃球会被摔碎(腾讯)
  • 一致性 hash 原理,怎么解决节点少数据倾斜的问题(滴滴 陌陌)

系统设计

  • 设计秒杀系统,需要支持 100W 以上 QPS(滴滴)
  • 设计微博首页,需要拉取所有关注用户的最近 20 条微博(百度)
  • 抢红包算法设计(百度 滴滴)
  • 设计一个短链系统(百度)

算法

  • 常见的排序算法有哪些,哪些是稳定的,如果需要稳定排序算法的话,选哪种(百度)
  • 反转链表(滴滴)easy
  • topk(百度 字节) medium
  • lru(滴滴) medium
  • leetcode104. 二叉树的最大深度(滴滴) easy
  • leetcode98. 验证二叉搜索树(滴滴) medium
  • leetcode103. 二叉树的锯齿形层序遍历(字节) medium
  • leetcode113. 路径总和 II(字节) medium
  • leetcode695. 岛屿的最大面积(字节) medium
  • leetcode56. 合并区间(字节) medium
  • leetcode23. 合并 K 个升序链表(字节) hard
  • leetcode162. 寻找峰值(字节) medium
  • leetcode64. 最小路径和(滴滴) medium

原文:https://learnku.com/articles/63520

laravel广播使用笔记,基于laravel-websocket扩展包

阅读文档

Laravel 广播系统文档

laravel-websockets文档

安装需要的用的依赖

//websocket服务端
composer require beyondcode/laravel-websockets

//发布数据迁移文件
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"

//发布配置文件
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"

//安装队列管理面板 或者 使用php artisan queue:work也可以
composer require laravel/horizon
php artisan horizon:install

//执行迁移
php artisan migrate

//前端依赖
npm install laravel-echo pusher-js

修改配置

.env 配置

//广播驱动设置为pusher
BROADCAST_DRIVER=pusher

//队列驱动改为redis
QUEUE_CONNECTION=redis

//使用laravel-websockets做后端,pusher配置随便填写
PUSHER_APP_ID=yangliuan
PUSHER_APP_KEY=yangliuan
PUSHER_APP_SECRET=yangliuan
//注意一定要注释这行,否则laravel-websockets不生效
#PUSHER_APP_CLUSTER=mt1

//websocket端口号
LARAVEL_WEBSOCKETS_PORT=6001

config/app.php 配置

取消如下Provider的注释

/*
 * Application Service Providers...
 */
...
// App\Providers\BroadcastServiceProvider::class,

config/broadcasting.php 配置

按如下修改

'connections' => [

        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                 //本地开发关闭安全连接
                'useTLS' => false,
                //本地host配置
                'host' => '127.0.0.1',
                //端口
                'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
                //协议
                'scheme' => 'http',
            ],
        ],

config/websockets.php

'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'path' => env('PUSHER_APP_PATH'),
            'capacity' => null,
            //是否开启客户端发送消息
            'enable_client_messages' => false,
            //是否开启统计
            'enable_statistics' => true,
        ],
    ],

测试案例场景

使用laravel excel 队列导出文件后,自动提示并下载,使用公共频道 demo地址

后端代码

注册频道

route/channels.php 文件,可以自定义频道名称

Broadcast::channel('excel', function () {
    return true;
});

创建ExcelExportCompletedEvent事件

php artisan make:event ExcelExportCompletedEvent

<?php
use Illuminate\Broadcasting\Channel;//公共频道
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel; //存在频道可以加入和离开,需要授权
use Illuminate\Broadcasting\PrivateChannel; //私有频道,需要授权
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

//注意事件一定要实现ShouldBroadcast接口
class ExcelExportCompletedEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    //public属性会自动转换为广播数据
    //自定义广播数据  文档 https://learnku.com/docs/laravel/9.x/broadcasting/12223#b2f5d1
   
    public $excel_path;

    public $disk;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(string $excel_path, string $disk)
    {    
        //文件路径
        $this->excel_path = $excel_path;
        //磁盘
        $this->disk = $disk;
    }

    /**
     * 监听频道
    *  监听自己的定义频道名称
     * 
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('excel');
    }
}

创建导出文件 ExcelDemoPictureQueryExport 细节略过详情看 laravel excel文档

创建通知队列,用于触发时间

php artisan make:job ExcelNotifyJob

class ExcelNotifyJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $attach;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(array $attach)
    {
        $this->attach = $attach;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //发送广播通知
        ExcelExportCompletedEvent::dispatch($this->attach['file_name'], $this->attach['disk']);
    }
}

控制器代码

/**
 * 字段导出图片 使用队列 并接受广播通知
 *
 * @param Request $request
 * @return void
 */
public function queueImages(Request $request)
{
  $file_name = 'excel-demo-'.date('YmdHis').\mt_rand(100000, 999999).'.xlsx';
  $disk = 'public';
  Excel::queue(new ExcelDemoPictureQueryExport(), $file_name, $disk)
  //导出成功后,使用任务链调用excel通知job
  //DOC:https://learnku.com/docs/laravel/8.5/queues/10395#dispatching-jobs
  //DOC:https://docs.laravel-excel.com/3.1/exports/queued.html#appending-jobs
  ->chain([
      new ExcelNotifyJob(compact('file_name', 'disk'))
  ]);

  return response()->json();
}

//下载文件方法
public function store(Request $request)
{
    $request->validate([
       'storage_path' => 'bail|required|string',
       'disk' => 'bail|nullable|string',
    ]);
    $realPath = Storage::disk($request->input('disk') ?? 'public')
       ->path($request->input('storage_path'));

    return response()->download($realPath)->deleteFileAfterSend();
}

前端代码

使用 Laravel Jetstream Inertia.js  构建

封装laravel-echo.js

import Echo from 'laravel-echo';

window.pusher = require('pusher-js');

const echo = new Echo({
    broadcaster: 'pusher',
    key: 'yangliuan',
    wsHost: window.location.hostname,
    wsPort: 6001,
    forceTLS: false,
    enabledTransports: ['ws', 'wss'],
})

export { echo }

Excel.vue

<template>
 <app-layout title="Dashboard">
  ...
  <a href="#" @click="queueImagesClick">
  <div class="mt-3 flex items-center text-sm font-semibold text-indigo-700">
  <div>队列导出图片并用广播接受通知</div>
  <div class="ml-1 text-indigo-500">
  <svg viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
 </div>
 </div>
 </a>
 </app-layout>
</template>

<script>
 ...
 //导入laravel echo 
 import { echo } from '@/laravel-echo'

 export default defineComponent({
    components: {
       AppLayout,
       JetApplicationLogo,
       Link
    },
    created() {
      //监听公共频道excel,响应下载excel文件
       echo.channel('excel')
           .listen('ExcelExportCompletedEvent', (e) => {
               alert('ExcelExportCompletedEvent')
               this.downloadExcel(e.excel_path,e.disk)
               console.log(e);
           })
    },
    methods: {
       //下载方法
       downloadExcel(excel_path,disk) {
          const download_url =  '/api/files/download?storage_path=' + excel_path + '&disk=' + disk
          window.open(download_url)
       },
      //点击时间调用队列导航图片接口
       queueImagesClick() {
          axios.post('/api/excel/export/queue-images').then( response => {
             console.log(response)
          })
       }
  }
})
</script>
//开启websocket服务
php artisan websockets:serve

//开启horizon队列
php artisan horizon

演示

授权频道案例

nginx代理websocket

laravel websocket文档

websocket单独使用一个域名不和http接口共享域名,配置如下

server {
    listen 80;
    server_name websocket.exhibition.demo;

    location / {
        proxy_pass             http://127.0.0.1:6001;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

第二种方式websocket和http接口公用一个域名

map $http_upgrade $type {
  default "";
  websocket "ws";
}

server {
    listen 80;
    server_name api2.exhibition.demo;
    root /home/yangliuan/Code/Php/business-logic/laravel-exhibition/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.php;
    charset utf-8;

    location = /favicon.ico {
        access_log off; log_not_found off;
    }

    location = /robots.txt {
        access_log off; log_not_found off;
    }
   
   //http
    location /  {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
   //websocket
    location @ws  {
        proxy_pass             http://127.0.0.1:6001;
        proxy_set_header Host  $host;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    location ~ [^/]\.php(/|$) {
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

参考

websocket实现手机扫码登陆

FAQ: mysqld_safe mysqld from pid file xxx.pid ended

处理一个兼职人员部署的服务器故障

1.php故障

Warning: require_once(ROOTPATHconfig/bluebee.inc.php): failed to open stream: No such file or directory in /web/code/mygym/mygym_pc/include/head.php on line 23

Fatal error: require_once(): Failed opening required 'ROOTPATHconfig/bluebee.inc.php' (include_path='.:/usr/local/php54/lib/php') in /web/code/mygym/mygym_pc/include/head.php on line 23

boss反馈,一个兼职人员开发部署的项目,出现了这个问题,根据经验初步判断,是文件不存在了,或者目录没有权限,登录之后发现,这个phper根本没有linux基础,以及不懂php-fpm运行机制,文件用户和组是 nginx 然后给了777权限

解决方法

service php-fpm status 显示 php-fpm 是www 用户跑的,但是当前服务器没有该用户

执行如下命令,创建www用户并加入www用户组

命令参考

groupadd www
useradd -g www -M -s /sbin/nologin www

更改代码目录权限

//更改用户组
chown -R www.www /web/code
//更改目录权限
chmod -R 755 /web/code
文件权限根据情况可以给644

2.php报错提示mysql连接失败

service mysqld status 显示启动失败,查看/var/log/mysqld.log 日志 报错如下

mysqld_safe mysqld from pid file /var/lib/mysql/mysqld.pid ended

/etc/my.cnf配置如下

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html

[mysqld]
skip-grant-tables
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

发现是使用rpm包使用的社区版安装的。

尝试了各种发,都没有用,最后参考如下问答解决

https://stackoverflow.com/questions/33984848/mysqld-safe-mysqld-from-pid-file-var-run-mysqld-mysqld-pid-prevent-from-server

restorecon -r /var/lib/mysql
service mysqld start

原因分析

可能是 /var/lib/mysql 目录,用户组 不是 mysql,

移动复制或修改文件时导致了 SELinux文件属性 丢失

首先保证 mysql 数据目录/var/lib/mysql 用户组 必须是 mysql

然后使用 restorecon 恢复文件的安全上下文

restorecon指令参考

如何实现给每个注册用户生成固定独立的URL地址

使用二级域名作为独立url, nginx使用通配符配置域名绑定

这种方案浪费域名资源

官方文档 https://nginx.org/en/docs/http/server_names.html

本地测试

host文件增加三个配置

127.0.0.1 abc.pan-domain.stu
127.0.0.1 efg.pan-domain.stu
127.0.0.1 yangliuan.pan-domain.stu

nginx配置

server {
    listen 80;
    #通配符绑定
    server_name *.pan-domain.stu;
    root /home/yangliuan/Code/Study/PHP/pan-domain;
    index index.php;

    location ~ [^/]\.php(/|$) {
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

    location ~ ^/(\.user.ini|\.ht|\.git|\.svn|\.project|LICENSE|README.md) {
        deny all;
    }
}

测试结果

对其中一个域名yangliuan.pan-domain.stu 进行优先级测试,增加单独的站点配置和绑定,

server {
    listen 80;
    server_name yangliuan.pan-domain.stu;
    root /home/yangliuan/Code/Study/PHP/test;
    index index.php;

    location ~ [^/]\.php(/|$) {
        #fastcgi_pass remote_php_ip:9000;
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

    location ~ ^/(\.user.ini|\.ht|\.git|\.svn|\.project|LICENSE|README.md) {
        deny all;
    }
}

结果如下

说明 server_name指令中 指定名称的优先级大于通配符

yangliuan.pan-domain.stu 的优先级大于 *.pan-domain.stu

如果云平台可以调用平台的域名解析接口,添加子域名解析 或者使用*.xxxx.com 泛域名解析

最简单实用的方案,给每个用户生成一个固定的独立子路由

  1. 使用用户昵称 命名
  1. 用户唯一标识 命名