野草博客 - 技术分享
type: channel
link: https://www.cnweed.com/category/qtfx/
items: MariaDB简单主从同步
items: Linux MegaCli 根据盘符获取 RAID 位置与 盘位
items: Python结合MegaCLI对RAID列阵定时检测异常自动短信/电话通知
items: 解决bootstrap弹出框内容向左偏移
items: php in_array多维数组查询
items: php foreach跳出本次/当前循环与终止循环方法
items: Centos7 Error Python.h No such file or directory
items: PHP对象Object与数组Array互转
items: Laravel查询构造器自定义分页实现方法offset()和limit()
items: PHP之Trait详解

MariaDB简单主从同步
type: item
date: 2025-11-01T23:34:00+00:00
description: 我的一些业务数据库比较大，虽然服务器配置完全满足业务运行，但当用mysqldump备份单个30GB左右的数据库时还是会IO延迟暴增，导致备份期间WEB短暂卡顿或中断。另外就算本地做RAID，再做异地备份，一旦真的RAID扑街你恢复异地备份也会失去备份间隔的数据。鉴于此做数据库主从同步，从库仅作备份用就是最靠谱的备份方案了，从库的数据是实时的，异地备份也在从库进行，这样就完全不影响主库业务运行又拥有实时的数据备份，主库挂了还能短时间立即切换到从库恢复业务。MariaDB主库配置my.cnf:[mysqld] log-bin=mysql-bin # 启用二进制日志，mysql-bin是日志文件名前缀 binlog_format=ROW # 保证数据复制和恢复的最高安全性和可靠性 server-id=1 # 唯一的服务器ID，每台服务器必须不同 gtid-domain-id=1 # 设置主服务器的GTID域ID bind-address=0.0.0.0 # 允许远程连接，或者指定主服务器的IP地址 创建复制用户并赋予PRIVILEGES权限CREATE USER 'repl_user'@'%' IDENTIFIED BY 'Password'; GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%'; FLUSH PRIVILEGES; MariaDB从库配置my.cnf[mysqld] server-id=2 gtid-domain-id=1 # 从服务器通常与主服务器使用相同的GTID域ID #log-bin=mysql-bin # 可选: 如果从服务器将来可能成为主服务器，建议开启 如果主库存在数据，需要先备份导入从库。首先登入root用户在数据库全局锁表FLUSH TABLES WITH READ LOCK; 如果你的MariaDB中所有数据库和所有表都使用InnoDB存储引擎，那么你可以用下面的mysqldump命令不锁表备份。InnoDB是事务型存储引擎。--single-transaction 选项会利用InnoDB的事务特性，在备份开始时启动一个事务，从而在事务的隔离级别下创建一个数据快照。这个快照在整个备份过程中保持一致性，即使在备份进行时，数据库有新的写入操作，也不会影响备份的数据一致性。备份完成后，该事务自动提交。因此，如果全部是InnoDB表，使用 --single-transaction可以实现完全在线的无锁备份，主服务器的写入业务在备份期间可以持续进行，几乎没有停机时间。记录当前日志位置MariaDB [cndba]> SHOW MASTER STATUS; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000008 | 401 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) MariaDB [cndba]> SELECT BINLOG_GTID_POS(‘mysql-bin.000008', 401); +------------------------------------------+ | binlog_gtid_pos('mysql-bin.000008', 401) | +------------------------------------------+ | 0-2-6 | +------------------------------------------+ 1 row in set (0.00 sec) 退出后使用 mysqldump 进行备份（如果已经锁表，mysqldump执行完后会自动执行解锁）mysqldump -u root -p --flush-logs --master-data=2 --single-transaction --routines --triggers --events --all-databases | gzip > full_backup.sql.gz 在从服务器恢复备份gunzip < full_backup.sql.gz | mysql -u root -p 如果未锁表备份，则先解压full_backup.sql.gz…

Linux MegaCli 根据盘符获取 RAID 位置与 盘位
type: item
date: 2022-03-25T15:09:00+00:00
description: 我的CEPH OSD因为列阵卡不支持直通是基于RAID0的，最近ceph性能不足，排查过程iostat观察发现有一些盘r_await或w_await持续1000多，这就需要换盘了。ceph存储一份数据如果是默认3副本，那么就会3份副本写完才会完成写入，如果有1个osd延迟很高，就会影响整体写入速度。首先可以运行 ceph-volume lvm list 查看osd对应的盘符，如果是bcache，则需要再运行lsblk查看在哪个盘符下。然后查看是哪个盘符，以及盘位，进行更换重建。Python基于MegaCli获取raid卡状态的代码：https://raw.githubusercontent.com/eLvErDe/hwraid/master/wrapper-scripts/megaclisas-status这个大佬的python脚本可以快速帮忙定位，运行完后再执行下：lsscsi 查看盘符在系统中的编号就可以定位到盘了，记得MegaCli得先安装。代码贴上：#!/usr/bin/python # $Id: megaclisas-status,v 1.78 2018/10/01 03:52:57 root Exp root $ # # Written by Adam Cecile <gandalf@NOSPAM.le-vert.net> # Modified by Vincent S. Cojot <vincent@NOSPAM.cojot.name> # import os import re import sys import pdb import inspect import argparse os.system('lsscsi') if sys.platform == "win32": import ctypes def_megaclipath = "/opt/MegaRAID/MegaCli/MegaCli64" # Non-Nagios Mode defaults nagiosmode = False nagiosoutput = "" nagiosgoodarray = 0 nagiosbadarray = 0 nagiosgooddisk = 0 nagiosbaddisk = 0 # Sane defaults printarray = True printcontroller = True debugmode = False notempmode = False totaldrivenumber = 0 totalconfdrivenumber = 0 totalunconfdrivenumber = 0 # Hardcode a max of 16 HBA and 128 LDs for now. LDTable must be initialized to accept populating list of LD's into each ctlr's list. MaxNumHBA = 16 MaxNumLD = 128 LDTable = [[] * MaxNumHBA for i in range(MaxNumLD)] NestedLDTable = [[False for i in range(MaxNumLD)] for j in range(MaxNumHBA)] # Outputs is a 'dict' of all MegaCLI outputs so we can re-use them during loops.. Outputs = {} ConfDisks = {} NagiosBadDisks = {} NagiosGoodDisks = {} # We need root access to query if __name__ == "__main__": # deal with command line options parser = argparse.ArgumentParser() parser.add_argument("--nagios", help="enable nagios support", action="store_true") parser.add_argument("--debug", help="enable debugging output", action="store_true") parser.add_argument("--notemp", help="disable temperature reporting", action="store_true") args = parser.parse_args() nagiosmode = a…

Python结合MegaCLI对RAID列阵定时检测异常自动短信/电话通知
type: item
date: 2020-06-10T08:27:00+00:00
description: 公司有台10个盘组的RAID10的服务器列阵挂了，坏了3个盘，超过了RAID10的容错，已经无法通过列阵恢复数据了。同时挂3个是很小几率的，所以也有一定可能刚开始挂了1-2个不知道，直到第3个挂了down机了才发现。因为机器很多，人工每天检查一次会比较耗时，每周检查也许又会太长。所以写了个py小脚本，可以定时1小时检查次，出现故障可以立即通知到技术立即去进一步检查、换盘，避免悲剧发生。1、安装MegaCLI# wget https://raw.githubusercontent.com/crazy-zhangcong/tools/master/MegaCli8.07.10.tar.gz && tar -zxf MegaCli8.07.10.tar.gz && cd MegaCli8.07.10/Linux/ && rpm -ivh Lib_Utils-1.00-09.noarch.rpm MegaCli-8.02.21-1.noarch.rpm && ln -s /opt/MegaRAID/MegaCli/MegaCli64 /usr/local/bin/MegaCli && MegaCli -v 出现如下信息即正常完成安装MegaCLI SAS RAID Management Tool Ver 8.02.21 Oct 21, 2011(c)Copyright 2011, LSI Corporation, All Rights Reserved. Exit Code:0x002、Python脚本# -*- coding: utf-8 -*- #!/usr/bin/python import os import requests node = '宽带型VPS宿主服务器1' #填写节点名称 error = 0 def get_status(value): status = value.split(": ") return status[1] def send_warning(): global node # 语音通知 基于 https://www.mysubmail.com 语音通知接口 voice_url = 'https://api.mysubmail.com/voice/send.json' voice_params = { 'appid': '', 'to': '13200000000', 'content': '紧急事态：'+node+'硬盘状态异常，请立即检查', 'signature': '' #填写应用密匙 } voice_res = requests.post(voice_url, data=voice_params) # print voice_res.text # 短信通知 基于 https://www.mysubmail.com 短信接口 message_url = 'https://api.mysubmail.com/message/send.json' message_params = { 'appid': '', 'to': '13200000000', 'content': '【xx科技】紧急事态：'+node+'硬盘状态异常，请立即检查', 'signature': '' #填写应用密匙 } message_res = requests.post(message_url, data=message_params) # print message_res.text # 检查RAID状态 # raidinfos = open('raid.log','r') # for raidinfo in raidinfos.readlines(): raidinfos = os.popen('/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -Lall -aALL -NoLOG').readlines() for raidinfo in raidinfos: raidinfo = raidinfo.strip('\n') if "State" in raidinfo: status = get_status(raidinfo) if status != 'Optimal': error = 1 print(raidinfo+'\n') # 检查所有磁盘状态 # pdlist = open('raid_pdlist.log','r') # for line in pdlist.readlines(): pdlist = os.popen('/opt/MegaRAID/MegaCli/MegaCli64 -PDList -aALL -NoLOG').readlines() for lin…

解决bootstrap弹出框内容向左偏移
type: item
date: 2020-04-16T11:05:04+00:00
description: body { padding-right: 0px !important; } *.modal-open { overflow-y: scroll; padding-right: 0 !important; } https://blog.csdn.net/baiyan_er/article/details/82588826

php in_array多维数组查询
type: item
date: 2020-03-15T20:57:20+00:00
description: in_array 函数只针对一维数组，经过简单的构造，就可以查询多维数组。$arr = array( array('a', 'b'), array('c', 'd') ); in_array('a', $arr); // 此时返回的永远都是 false deep_in_array('a', $arr); // 此时返回 true 值 function deep_in_array($value, $array) { foreach($array as $item) { if(!is_array($item)) { if ($item == $value) { return true; } else { continue; } } if(in_array($value, $item)) { return true; } else if(deep_in_array($value, $item)) { return true; } } return false; } 转自：http://www.phpfensi.com/php/20140710/3731.html

php foreach跳出本次/当前循环与终止循环方法
type: item
date: 2020-03-15T20:55:47+00:00
description: PHP中用foreach()循环中，想要在循环的时候，当满足某个条件时，想要跳出本次循环继续执行下次循环，或者满足某个条件的时候，终止foreach()循环，分别会用到：continue 与 break$arr= array('le','yang','jun','code','life','a','b','c'); $html= ''; foreach($arr as $key => $value){ if($value == 'a'){ $html.= $value; } if($value =='b'){ $html.= $value; continue;// 当 $value为b时，跳出本次循环 } if($value =='c'){ $html.= $value; break;// 当 $value为c时，终止循环 } //$html.= $value; } echo $html; // 输出： abc

Centos7 Error Python.h No such file or directory
type: item
date: 2020-02-15T21:01:35+00:00
description: 系统没有安装python-devel包导致yum install python-devel.x86_64

PHP对象Object与数组Array互转
type: item
date: 2020-02-15T20:58:05+00:00
description: 可以使用json_decode函数$object = json_decode($array); //得到的是 object 数据类型。$array = json_decode($object, ture); //得到的则是数组。

Laravel查询构造器自定义分页实现方法offset()和limit()
type: item
date: 2020-02-15T20:46:00+00:00
description: 情景：Laravel自带有基于 Eloquent ORM + 查询构造器的 paginate 分页方法非常方便。但我正在进行二次开发，程序查询只基于查询构造器，所以只能使用offset()和limit()实现自定义分页功能。实现的代码：$pagenNum=request('page'); $limit=request('limit'); $count=Admin::count(); $page=$pagenNum-1; if ($page != 0) { $page = $limit * $page; $limit=$limit*$pageNum; } $data = Admin::offset($page)->limit($limit)->get()->toArray(); return response([ 'code'=>'0', 'msg'=>'', 'count'=>$count, 'data'=>$data]); 本文参考：https://blog.csdn.net/sqlquan/article/details/81837143

PHP之Trait详解
type: item
date: 2018-10-22T02:59:41+00:00
description: php从以前到现在一直都是单继承的语言，无法同时从两个基类中继承属性和方法，为了解决这个问题，php出了Trait这个特性用法：通过在类中使用use 关键字，声明要组合的Trait名称，具体的Trait的声明使用Trait关键词，Trait不能实例化如下代码实例:<?php trait Dog{ public $name="dog"; public function bark(){ echo "This is dog"; } } class Animal{ public function eat(){ echo "This is animal eat"; } } class Cat extends Animal{ use Dog; public function drive(){ echo "This is cat drive"; } } $cat = new Cat(); $cat->drive(); echo " "; $cat->eat(); echo " "; $cat->bark(); ?> 输出This is cat drive This is animal eat This is dog 再测试Trait、基类和本类对同名属性或方法的处理，如下代码<?php trait Dog{ public $name="dog"; public function drive(){ echo "This is dog drive"; } public function eat(){ echo "This is dog eat"; } } class Animal{ public function drive(){ echo "This is animal drive"; } public function eat(){ echo "This is animal eat"; } } class Cat extends Animal{ use Dog; public function drive(){ echo "This is cat drive"; } } $cat = new Cat(); $cat->drive(); echo " "; $cat->eat(); ?> 输出内容：This is cat drive This is dog eat 所以：Trait中的方法或属性会覆盖 基类中的同名的方法或属性，而本类会覆盖Trait中同名的属性或方法一个类可以组合多个Trait，通过逗号相隔，如下use trait1,trait2当不同的trait中，却有着同名的方法或属性，会产生冲突，可以使用insteadof或 as进行解决，insteadof 是进行替代，而as是给它取别名如下实例：<?php trait trait1{ public function eat(){ echo "This is trait1 eat"; } public function drive(){ echo "This is trait1 drive"; } } trait trait2{ public function eat(){ echo "This is trait2 eat"; } public function drive(){ echo "This is trait2 drive"; } } class cat{ use trait1,trait2{ trait1::eat insteadof trait2; trait1::drive insteadof trait2; } } class dog{ use trait1,trait2{ trait1::eat insteadof trait2; trait1::drive insteadof trait2; trait2::eat as eaten; trait2::drive as driven; } } $cat = new cat(); $cat->eat(); echo " "; $cat->drive(); echo " "; echo " "; echo " "; $dog = new dog(); $dog->eat(); echo " "; $dog->drive(); echo " "; $dog->eaten(); echo " "; $dog->driven(); ?> 输出如下：This is trait1 eat This is trait1 drive This is trait1 eat This is trait1 drive This is trait2 eat This is trait2 drive as 还可以修改方法的访问控制<?php…