php类备忘录

public(公开):外部、内部、子类全通车
protected(受保护):家族内可用
private(私有):仅当前类可用
 
基础类class
abstract 抽象类,做基础架构、只能继承不能修改,extends后才能new实例化,做model之类的定义
final 最终完美类, 不能extends,可以new实例化
trait 代码复用,不能new初始化,只能class use引入
interface 接口类,不能被 new实例化,使用 implements 来实现接口, 一个类只能继承(extends)一个父类,但可以同时实现(implements)多个接口。

int 整数类型
string 字符串
float 浮点型 带小数点的
bool 布尔型 true或false
array 数组
object 对象
callable 可调用 只能是一个函数、闭包或者方法名
void 空
mixed 混合,任何类型(字符串、数字、数组、对象、甚至 null)
(int|string $id) 联合类型

function 函数
return 直接返回

最蠢的营销广告

用女人拍擦边性暗示的视频推广卖男装是我见过最愚蠢的精致营销。

买衣服要穿着合身和舒适, 其次才是好看。

即使我这种好色的老色批看这种营销内容都能感到满满的生理厌恶。

 

PostgreSQL18 主从同步复制部署备忘录

安装postgresql-18

apt install -y postgresql-common
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
install -d /usr/share/postgresql-common/pgdg
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
apt update
apt install postgresql-18

主库配置

USER="replica"
PASSWORD=$(openssl rand -base64 24)
NETWOKR="0.0.0.0/0"   //从库IP段
IP="1.1.1.1" #主库IP 

#主库
cat>>/etc/postgresql/18/main/postgresql.conf<<EOF
listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 1GB
archive_mode = off
#archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
EOF
#archive_mode归档模式很占空间
echo "host replication $USER $NETWOKR md5" >>/etc/postgresql/18/main/pg_hba.conf
# 创建用户(幂等)
sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='$USER'" | grep -q 1 || \
sudo -u postgres psql -c "CREATE ROLE $USER WITH REPLICATION LOGIN PASSWORD '$PASSWORD';"
systemctl restart postgresql
echo "REPL $USER PASSWORD: $PASSWORD"

echo -e "\n\n从库快速导入备份bash shell:"
echo -e "USER=$USER\nPASSWORD=$PASSWORD"
echo "sudo -u postgres pg_basebackup -h $IP  -U  $USER -D /home/postgresql/18/main -P -R -X stream -v"

从库配置

IP="1.1.1.1" #主库IP
#rm -rf /var/lib/postgresql/18/main/*   
cat>>/etc/postgresql/18/main/postgresql.conf<<EOF
listen_addresses = '*'
#recovery_min_apply_delay='24h'   #延迟24小时同步
hot_standby = on
wal_keep_size = 2GB
max_wal_senders = 10
EOF
systemctl stop postgresql
mkdir /home/postgresql
chown -R postgres:postgres /home/postgresql
chmod 700 /home/postgresql
sudo -u postgres pg_basebackup -h $IP -U $USER -D /home/postgresql/18/main -P -R -X stream -v
systemctl start postgresql
建议修改/etc/postgresql/18/main/postgresql.conf的data_directory和max_connections参数
 
data_directory = '/home/postgresql/18/main'
 
#从库的设置小于主库的max_connections会无法启动
 
从库自动连接配置文件 /var/lib/postgresql/18/main/postgresql.auto.conf
 

检查核验配置

tail -n 100 /var/log/postgresql/postgresql-18-main.log
#验证主库
sudo -u postgres psql -c "SELECT client_addr,state FROM pg_stat_replication;"

#验证从库
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"

 

/etc/postgresql/18/main/conf.d/ 目录存放配置文件可以覆盖主配置

dnswatch

https://www.dnswatch.info/dns/dnslookup?la=en&host=164.210.103.in-addr.arpa&type=NS&submit=Resolve

一个在线验证rpki网站

https://bgprpki.com/

youtube的Shorts就是shift.........

两三年前刷过,老是重复出现看过的视频, 现在还是一点都没变。。。。。。

 

真是shi。。。。。。。。 shift

workerman和swoole单文件静态php

worker和swoole直接常驻内存运行抛弃fpm直接高效运行, 官方提供了现成的静态编译php文件,拿来直接可以运行,不用再自己吭哧吭哧再去编译,直接带上nginx就可以跑,如果将php打包成二进制文件会更简单。

 

几个相关项目发布地址

https://github.com/swoole/swoole-cli/releases
https://github.com/dixyes/phpmicro
https://github.com/crazywhalecc/static-php-cli

https://www.swoole.com/download
https://www.workerman.net/download

swoole-cli静态php

wget -O - https://github.com/swoole/swoole-cli/releases/download/v6.1.4.0/swoole-cli-v6.1.4-linux-x64.tar.xz | tar -xJ 
install swoole-cli /usr/bin/swoole

workerman官方静态php

wget https://www.workerman.net/download/php/php-8.4-linux-x86_64.tar.gz|  tar -xz

phpmicro可以打包php为二进制文件

 

swoole启动fpm

swoole-cli -P -h
# 运行 FPM
swoole-cli -P --fpm-config /opt/php-8.1/etc/php-fpm.conf -p /opt/php-8.1/var
# 关闭守护进程
swoole-cli -P --fpm-config /opt/php-8.1/etc/php-fpm.conf -p /opt/php-8.1/var -F
# 使用 root 账户启动
swoole-cli -P --fpm-config /opt/php-8.1/etc/php-fpm.conf -p /opt/php-8.1/var -F -R

发现两个新的邮局方案mox和stalwart

https://github.com/stalwartlabs/stalwart/releases

https://github.com/mjl-/mox/releases

PostgreSQL查找慢查询

统计CPU

ps -u postgres -o %cpu | awk '{s+=$1} END {print "Postgres Total CPU: " s "%"}'

查看活跃查询

SELECT pid, now() - query_start AS duration, query, state FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC;
SELECT pid, now() - query_start AS duration, query, state FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC LIMIT 5;

查看连接IP和查询语句

SELECT pid, now() - query_start AS 执行时间, usename AS 用户名, 
client_addr AS 连接IP, state AS 状态, query AS 查询语句         
FROM pg_stat_activity WHERE
 pid <> pg_backend_pid() ORDER BY 执行时间 DESC;

查看扫表

SELECT 
    relname AS 表名,
    seq_scan AS 全表扫描次数,
    seq_tup_read AS 全表扫描读取行数,
    idx_scan AS 索引扫描次数,
    idx_tup_fetch AS 索引提取行数
FROM pg_stat_user_tables
WHERE seq_scan > 0
ORDER BY seq_tup_read DESC
LIMIT 10;

启用插件

CREATE EXTENSION IF NOT EXISTS pg_stat_statements; 

 重置自动增续ID

SELECT setval('tag_id_seq', (SELECT MAX(id) FROM tag));

nginx隐藏真实文件路径

给浏览器浏览器返回头

$file=decode($url);
header("X-Accel-Redirect: /privatefiles/$file");

nginx配置

    location /privatefiles {
        internal;  #内部访问
        alias /var/www/html/xaccel/restrictedfiles;
    }   

 

将文件名url加密, 然后接收解密,通过X-Accel-Redirect再转给nginx返回数据。

为什么要这么做?  一些文件路径在某些原因下不想暴露真实路径,又不通过程序再去读一遍问题直接转交个nginx响应。

转载自:https://dev.to/gbhorwood/nginx-serving-private-files-with-x-accel-redirect-57dl

Thinkphp使用postgresql新库报错解决

DROP FUNCTION IF EXISTS public.table_msg(varchar) CASCADE;
DROP FUNCTION IF EXISTS public.table_msg(varchar, varchar) CASCADE;
DROP FUNCTION IF EXISTS public.pgsql_type(varchar) CASCADE;
DROP TYPE IF EXISTS public.tablestruct CASCADE;

CREATE OR REPLACE FUNCTION public.pgsql_type(a_type character varying) RETURNS character varying AS
$BODY$
DECLARE
     v_type character varying;
BEGIN
     CASE a_type
         WHEN 'int8' THEN
              v_type := 'bigint';
         WHEN 'int4' THEN
              v_type := 'integer';
         WHEN 'int2' THEN
              v_type := 'smallint';
         WHEN 'bpchar' THEN
              v_type := 'char';
         ELSE
              v_type := a_type;
     END CASE;
     RETURN v_type;
END;
$BODY$
LANGUAGE plpgsql;

-- 2. tablestruct 类型
CREATE TYPE public.tablestruct AS (
  fields_key_name varchar(100),
  fields_name varchar(200),
  fields_type varchar(20),
  fields_length bigint,
  fields_not_null varchar(10),
  fields_default varchar(500),
  fields_comment varchar(1000)
);

-- 3. table_msg 函数(带 schema 参数)
CREATE OR REPLACE FUNCTION public.table_msg(a_schema_name varchar, a_table_name varchar)
RETURNS SETOF public.tablestruct AS
$body$
DECLARE
     v_ret tablestruct;
     v_oid oid;
     v_sql varchar;
     v_rec record;
     v_key varchar;
BEGIN
     -- 获取表 oid
     SELECT c.oid INTO v_oid
     FROM pg_class c
     INNER JOIN pg_namespace n ON c.relnamespace = n.oid AND lower(n.nspname) = lower(a_schema_name)
     WHERE c.relname = a_table_name;

     IF NOT FOUND THEN
         RETURN;
     END IF;

     -- 构造动态查询
     v_sql := '
     SELECT
           a.attname AS fields_name,
           a.attnum AS fields_index,
           pgsql_type(t.typname::varchar) AS fields_type,
           a.atttypmod - 4 AS fields_length,
           CASE WHEN a.attnotnull THEN ''not null'' ELSE '''' END AS fields_not_null,
           pg_get_expr(ad.adbin, ad.adrelid) AS fields_default,
           d.description AS fields_comment
     FROM pg_attribute a
     INNER JOIN pg_class c ON a.attrelid = c.oid
     INNER JOIN pg_type t ON a.atttypid = t.oid
     LEFT JOIN pg_attrdef ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum
     LEFT JOIN pg_description d ON d.objoid = c.oid AND d.objsubid = a.attnum
     WHERE a.attnum > 0 AND a.attisdropped = false AND c.oid = ' || v_oid || '
     ORDER BY a.attnum;
     ';

     -- 遍历字段
     FOR v_rec IN EXECUTE v_sql LOOP
         v_ret.fields_name := v_rec.fields_name;
         v_ret.fields_type := v_rec.fields_type;
         IF v_rec.fields_length > 0 THEN
             v_ret.fields_length := v_rec.fields_length;
         ELSE
             v_ret.fields_length := NULL;
         END IF;
         v_ret.fields_not_null := v_rec.fields_not_null;
         v_ret.fields_default := v_rec.fields_default;
         v_ret.fields_comment := v_rec.fields_comment;

         SELECT constraint_name INTO v_key
         FROM information_schema.key_column_usage
         WHERE table_schema = a_schema_name
           AND table_name = a_table_name
           AND column_name = v_rec.fields_name;

         IF FOUND THEN
             v_ret.fields_key_name := v_key;
         ELSE
             v_ret.fields_key_name := '';
         END IF;

         RETURN NEXT v_ret;
     END LOOP;

     RETURN;
END;
$body$
LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

COMMENT ON FUNCTION public.table_msg(a_schema_name varchar, a_table_name varchar) IS '获得表信息';

-- 4. table_msg 函数(简化版,只传 table_name)
CREATE OR REPLACE FUNCTION public.table_msg(a_table_name varchar)
RETURNS SETOF public.tablestruct AS
$body$
DECLARE
    v_ret tablestruct;
BEGIN
    FOR v_ret IN SELECT * FROM public.table_msg('public', a_table_name) LOOP
        RETURN NEXT v_ret;
    END LOOP;
    RETURN;
END;
$body$
LANGUAGE plpgsql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

COMMENT ON FUNCTION public.table_msg(a_table_name varchar) IS '获得表信息';

rhel系更新启动内核

dracut --force #强制更新initramfs
#dracut --force /boot/initramfs-$(uname -r).img $(uname -r)
#grubby --set-default /boot/vmlinuz-5.19.0-ml.x86_64   #设置指定内核
grubby --set-default 0         #设置启动第一个内核
grubby --default-kernel       #查看启动内核

初学golang之用beego快速创建项目

现安装golang https://go.dev/dl/

go install github.com/beego/bee/v2@latest
export PATH=$PATH:$(go env GOPATH)/bin
bee new app
cd app
go mod tidy
bee run

苹果giftcard礼品卡链接备忘录

https://www.apple.com/shop/buy-giftcard/giftcard

关闭windows账户锁定策略

在 Windows 系统中,账户锁定策略(Account Lockout Policy) 用于在多次登录失败后锁定账户,以防止暴力破解。但在远程桌面(RDP)、自动化运维或测试环境中,这一机制可能导致正常账号被频繁锁定。

net accounts /lockoutthreshold:0

 

验证方式

net accounts

输出中显示:Lockout threshold: Never