月度归档:2021年02月

Laravel连接数据库失败的诡异问题

晚上被运营叫起来了,发现一些本该上架的信息没有上架,观察发现是计划任务出现了问题,报数据连接超时:SQLSTATE[HY000] [2002] Connection time out。

找了一半天没有发现问题,config(“database”)看配置也是对的。

最后在框架的Connection类里打出pdo调试信息,发现数据库地址居然是测试环境的,全局搜索测试环境地址:

find ./ -name "*.php" | xargs grep  "1.1.1.1"

发现在一个Console/Command的Test测试文件的全局部分出现了,如下图:

由于Laravel在命令行运行的时候,会全局的加载所有的Command文件,分析出命令字等信息,所以造成了这段代码被执行,所以才引起了这个错误。

Redash笔记

安装

参考:https://github.com/getredash/setup
Mac上由于运行setup.sh有问题,需要手动的执行,包括以下几步
一、参考setup.sh建议env文件

PYTHONUNBUFFERED=0
REDASH_LOG_LEVEL=INFO
REDASH_REDIS_URL=redis://redis:6379/0
POSTGRES_PASSWORD=upGYF9nPSdUMErOynCeKP6VCkMPzwnCh
REDASH_COOKIE_SECRET=NiTTuwP6XcvWxjO1RQc3lKfQFAG9C0dL
REDASH_SECRET_KEY=0cYKX4YAcY2ERYBJTt4gK8nS1op5yB8K
REDASH_DATABASE_URL=postgresql://postgres:upGYF9nPSdUMErOynCeKP6VCkMPzwnCh@postgres/postgres

二、把docker-compose.xml下载下来,并修改env对应的目录。
三、初始化
“`
docker-compose run –rm server create_db
“`

四、运行
“`
docker-compose up -d
“`

文档地址:https://redash.io/help/

把一个查询当成一个数据源,需要建立一个Query DataSource,再按下面一个查询写:
“`
select * from query_1;
// 上面的以query_开始后面的数据,是查询的id
“`

在Redash里更新数据,需要手动的commit

select @max_order_id:=`value` from redash_var where `var_name`='max_order_id';
select @max_order_id_new:=max(id) from `order`;

replace into redash_var (`var_name`, `value`) values ('max_order_id', @max_order_id_new);
commit;
select * from `order` where id>@max_order_id;

用Api获取结果
http://111.111.111.111:88/api/queries/3/results?api_key=xxx
post传json

{
"parameters": {
"BeginDate": "2021-01-01",
"EndDate": "2021-01-05"
},
"max_age": 1800
}

 

 

Mac操作系统PHP、MySQL等开发环境相关笔记

Mac使用

brew使用命令
https://www.cnblogs.com/miker-lcy/archive/2004/01/13/13622391.html

加入–verbose可以显示详情
brew update –verbose

安装和使用

brew install [email protected]
启动php-fpm
brew services start [email protected]

安装扩展

到指定的版本目录下,如7.4,则到:/usr/local/opt/[email protected]/bin 目录下
./pecl install redis
如果是php5.6,则要指定版本:
./pecl install https://pecl.php.net/get/redis-4.3.0.tgz
配置文件路径:
/usr/local/etc/php/8.0

如果要自己编译安装如memcache,可以从pecl上下载下来,
tar zxvf xxx.tgz后,
/usr/local/opt/[email protected]/bin/phpize
要注意下面的命令,是指定了php-config版本的
./configure –with-zlib-dir=/usr/local/Cellar/zlib/1.2.11 –with-php-config=/usr/local/opt/[email protected]/bin/php-config
make
make install
vi /usr/local/etc/php/5.6/php.ini ,加入:
extension=”memcache.so”

VSCode安装断点调试

安装xdebug扩展,在配置文件里加入:

[XDebug]
zend_extension="xdebug.so"
xdebug.mode=debug
xdebug.log_level=0
xdebug.start_with_request=yes
xdebug.client_host="127.0.0.1"
xdebug.client_port="9180"

上面的:zend_extension=”xdebug.so” 可能在安装扩展的时候已经被加上了,这里我是放在一起方便管理。
xdebug.log_level=0,如果不加这一行的话,在命令行下cli运行时,会报下面的错误:
Xdebug: [Step Debug] Could not connect to debugging client. Tried: 127.0.0.1:9180 (through xdebug.client_host/xdebug.client_port) 🙁

安装多个版本

如果要同时安装多个版本,可以先安装旧版本,再设置:
export HOMEBREW_NO_INSTALL_CLEANUP=TRUE
后,安装新版本(用install xxx.rb),这样旧版本就不会被移除掉,我们就可以用switch来切换了。

查看版本
“`
brew list –version icu4c
“`

### 退回旧版本
https://stackoverflow.com/questions/55826221/install-icu4c-version-63-with-homebrew
锁住某个包不更新
“`
brew pin 包名
“`

### 多个php版本
https://www.cnblogs.com/jingxiaoniu/p/11132807.html

### 多个版本间的切换
“`
brew switch icu4c 64.2
“`
安装PHP多版本和使用

 

开放已经放弃的包
执行以下命令,不然找不到php5
brew tap exolnet/homebrew-deprecated
上面的功能已经失效,可以删除改用下面的 2022年
brew untap exolnet/homebrew-deprecated
brew tap shivammathur/php
brew reinstall [email protected]

/usr/local/Cellar/php/7.4.12/bin/php

brew –prefix php

ln -s /usr/local/opt/[email protected]/lib/libcrypto.1.0.0.dylib /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib
ln -s /usr/local/opt/[email protected]/lib/libssl.1.0.0.dylib /usr/local/opt/openssl/lib/libssl.1.0.0.dylib

 

手动安装brew各版本
https://stackoverflow.com/questions/55826221/install-icu4c-version-63-with-homebrew/55828190#55828190

在/usr/local/opt下面有一堆的软连接,指向到/usr/local/Cellar不同的版本

If you need to have [email protected] first in your PATH run:
echo ‘export PATH=”/usr/local/opt/[email protected]/bin:$PATH”‘ >> ~/.zshrc
echo ‘export PATH=”/usr/local/opt/[email protected]/sbin:$PATH”‘ >> ~/.zshrc

For compilers to find [email protected] you may need to set:
export LDFLAGS=”-L/usr/local/opt/[email protected]/lib”
export CPPFLAGS=”-I/usr/local/opt/[email protected]/include”

安装openssl1.0
php5.6需要openssl1.0,但现在已经升级了,参照下面来安装。
https://stackoverflow.com/questions/59337838/openssl-1-0-2m-on-macos

但在安装的时候,可能会出现:
NoMethodError: undefined method `prefer_64_bit?’ for OS::Mac:Module

做法比较粗野,把openssl.rb文件里那一行删除掉就行了,直接用64的那一行。

openssl1.0和1.0安装的时候,/usr/local/opt下的符号会指向相同的目录,需要修改。

根据前缀删除redis key
redis-cli -h 1.1.1.1 -n 5 keys “ss1:en-US:cp*” | xargs redis-cli -h db-gocashback-redis.gocashback.com -n 5 del

Linux操作记录

Linux隧道端口映射和转发

1.本地ssh可以登录远程服务器,(密码或者秘钥)
2.远程数据库需要赋权限给隧道端的ip
命令:

ssh -NCPfg [email protected] -L 3388:192.168.1.1:3306

参数:
-C 使用压缩功能,是可选的,加快速度。
-P 用一个非特权端口进行出去的连接。
-f 一旦SSH完成认证并建立port forwarding,则转入后台运行。
-N 不执行远程命令。该参数在只打开转发端口时很有用(V2版本SSH支持)
-g 表示远程机器可以连接到这个端口
这里的[email protected]是连接远程服务器的用户名和IP
-L 3388:192.168.1.1:3306 这里表示建立的隧道,3388是本机端口,通过3388和远程服务器建立隧道,192.168.1.1是内网ip,可以用127.0.0.1,当然也可以用外网ip,这里要注意数据库要给这个ip赋权,因为隧道连接实际上就是数据库连接的这个ip ,后面的是远程数据库的端口
这个命令在本地运行
运行这个命令会在本地机器上开启3388端口
ss和nestat 和lsof可以看到,开启了127.0.0.1:3388
连接:
本地装好mysql客户端
mysql -u用户名 -P 3388 -h127.0.0.1 -p密码
恭喜你登陆了

ssh -NCPfg -itmp [email protected] -L 3388:127.0.0.1:3306

防火墙
https://blog.csdn.net/s_p_j/article/details/80979450

CentOS Rinetd安装

这东西在大负载使用的时候,会存在问题,最好是用nginx来做代理
下载rpm包
https://centos.pkgs.org/7/nux-misc-x86_64/rinetd-0.62-9.el7.nux.x86_64.rpm.html

rpm -ivh rinetd-0.62-9.el7.nux.x86_64.rpm

0.0.0.0 6379 db-gocashback-redis.gocashback.com 6379

systemctl start rinetd

防火墙操作

https://blog.csdn.net/s_p_j/article/details/80979450

服务操作

查看服务列表:systemctl list-unit-files
设置开机启动:systemctl enable postfix.service
取消开机启动:systemctl disable postfix.service
systemctl status/start/stop/restart postfix.service

 

安装SQUID代理

yum install squid

vim /etc/squid/squid.conf

设置指定的ip可用
acl localnet src x.x.x.x/32

设置ip隐藏
forwarded_for delete
via off
follow_x_forwarded_for deny all
request_header_access X-Forwarded-For deny all

systemctl enable squid.service
systemctl start squid.service

SSH通过跳板机登录/执行命令

ssh 
root@目标主机IP 
-i 登录目标主机的Key 
-o ProxyCommand='ssh -A ops@跳板机IP -i 登录跳板机Key -W %h:%p -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' 
-o UserKnownHostsFile=/dev/null 
-o StrictHostKeyChecking=no 
"需要在目标主机上执行的命令"

UserKnownHostsFile 忽略ssh目录下的known_hosts文件
StrictHostKeyChecking 不要询问是否接受key的提示
ProxyCommand 通过该参数里的命令建立通道
上面2处的-i指定的private key都是当前主机目录下的key

PS命令

查看进程树
pstree -ap 进程id

查看进程的运行时间
ps -eo pid,lstart,etime,cmd | grep nginx

 

看phpfpm在干什么

strace -p `curl -s http://127.0.0.1/fpm_status?full | grep -C 2 "Finishing" | grep "pid" | awk '{print $2}' | awk 'END {print}'`

 

PHP 抓取记录

Selenium抓取

下载Chrome WebDriver
https://chromedriver.chromium.org/
下载Selenium Server,用的是版本4,3不再维护了
https://www.selenium.dev/downloads/
把2个文件放一个目录后,再运行:
java -jar .\selenium-server-4.0.0-beta-1.jar standalone
访问:http://IP:4444/ 有控制台

安装php-webdriver
php composer.phar require php-webdriver/webdriver

php-webdriver相关参考
https://github.com/php-webdriver/php-webdriver

有的网站判断了是否通过navigator.webdriver来判断是否是通过模拟抓取的,这种情况下需要用到中间人的方式去把返回的javascript替换掉,让他判断不成功。

目前用到的是mitmdump,可以写一个python文件,把返回的数据进行替换:

# coding:utf-8
# modify_response.py

import re
from mitmproxy import ctx

def response(flow):

    """修改应答数据"""
    if 'web-login/canvas' in flow.request.url:
        # 屏蔽selenium检测
        for webdriver_key in ['navigator.webdriver']:
            ctx.log.info('Remove"{}"from{}.'.format(webdriver_key,flow.request.url))
            flow.response.text=flow.response.text.replace(webdriver_key,'navigator.webdriverabc')

运行:mitmdump.ext -s 脚本.py,Python的版本要是3

如果用这样的话,chrome会出现非法的https,需要在webdriver里加入”ignore-certificate-errors”

还有一个问题是当这样用了之后,就没有办法给浏览器指定代理了,如果要指定的话,只能在mitmdump里指定二级代理,思路见:https://www.jianshu.com/p/dfd1e2753d71

没试过,脚本感觉有问题要修改才行。

def request(flow: http.HTTPFlow) -> None:
    if flow.request.method == "CONNECT":
        # If the decision is done by domain, one could also modify the server address here.
        # We do it after CONNECT here to have the request data available as well.
        return
        client_ip = flow.client_conn.address[0]
        if 'ip.cn' in flow.request.url:
                ctx.log.info(flow.request.url)
                proxy =("localhost", 8888)
        else:
                proxy = ("localhost", 3800)
    # 这里配置二级代理的ip地址和端口
    if flow.live:
        flow.live.change_upstream_proxy_server(proxy)

mitmdump –mode upstream:http://default-upstream-proxy.local:8080/ -s ./change_upstream_proxy.py

https://docs.mitmproxy.org/stable/addons-examples/

还有一个方式是用google的puppeteer,是node写的,没有试过。

更多关于webdriver检测的了解见:https://onefine.blog.csdn.net/article/details/88200217

 

linux shell 常用操作

用awk分析nginx日志

BEGIN {
#FS = "\t"
print("start...\n")
}

/deploy\.php(.*?)302/ {
print $1
}

END {
print("end.\n")
}

awk -f awk access.log 

BEGIN {
   pos = 1
   isupdate = 0
   title = ""
}

/Table_map: `55shantao_prod`\.`product_sku_data`/ {
   title = NR":"$0
}

/UPDATE `55shantao_prod`\.`product_sku_data`/ {
   print NR":"title
   print NR":"$0
   isupdate = 1
}


{
if (isupdate == 1 && pos < 28) {
   print NR":"$0
   pos = pos + 1
} else {
   pos = 1
   isupdate = 0
}
}

输出百度抓取的POST的ID和时间

more www.bianhua8.com.log | grep "Baiduspider" | grep "/post/" | awk 'BEGIN{FS=" "}{match($0, /\[(.+)\].+?post\/([0-9]+)/, m);print NR""m[1]"\t"m[2];}'

把找出执行时间大于多少ms的日志,注意:下面的match只支持在gawk里使用,有的linux默认是gawk,但在mac下面,需要安装gawk才支持,不然会报错。

more access.log-20210630 | awk '{match($0,/urt="([0-9\.]+)"/, m)}m[1]>0.1{print m[1]"\t"$7}' | grep -v "search"

tail -f xxxx.com.access.log | awk '{match($0,/urt="([0-9\.]+)"/, m)}m[1]>0.5{print $4"]\t" m[1]"s\t"$7}'

找出最近访问次数多的ip

tail -n 50000 /data/log/nginx/www.xxx.com.access.log | awk -F' ' '{print $1}' | sort | uniq -c | sort -n

 

grep取上下几行:
-B 前几行
-C 上下几行
-A 后几行

gerp用正则匹配
grep -E ‘xxxx’
但正则好像不能用\d之类的,只能用[0-9]这样

去重
cat xx.txt | sort | uniq

去重并统计行数按倒序排
cat xx.txt | sort | uniq -c | sort -r

curl显示请求时间
curl -o /dev/null -s -w 'dns解析时间:%{time_namelookup}\n连接时间:%{time_connect}\n开始传输时间:%{time_starttransfer}\ntotal:%{time_total}\n速度:%{speed_download}\n' "http://localhost/404.html"

切换用户

su xxx,切换到某用户
sudo -i,切换到管理员
sudo -u nginx php xxx.php,以某个用户运行,像一些无法登录的用户可以以这种方式执行
sudo -su nginx,可以切换到该用户去,并一直在那个用户

查看运行时间久的进程

ps aux | grep " cli.php " | sort -k 10 -n

查看网络连接状态

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

上面的$NF表示是最后一列的内容, NF表示最后一列的索引, END 是各个{}块之间需要的

nginx不能访问中文目录的问题出现404的解决方法

一朋友上传了棋谱到网站上,应该是从mac os里上传的。

用filezilla可以正常浏览显示,但用浏览器访问中文文件或带有中文目录的文件时,,出现404。

原因是上传上来的文件名不是utf-8格式的,是gb2312的。

所以,需要用convmv转换一下。

用法,把当前目录下面包换子目录都转换为utf-8:

convmv -f GB2312 -t UTF-8 -r –notest ./

另外,filezilla里必须把charset改为utf-8,不然浏览的时候会是乱码,