PHP效验银行卡卡号

/* 采用 Luhm 校验方法计算:
	1,将未带校验位的 15 位卡号从右依次编号 1 到 15,位于奇数位号上的数字乘以 2
	2,将奇位乘积的个十位全部相加,再加上所有偶数位上的数字
	3,将加法和加上校验位能被 10 整除。
*/
function luhm($s) {
	$n = 0;
	for ($i = strlen($s); $i >= 1; $i--) {
		$index=$i-1;
		//偶数位
		if ($i % 2==0) {
			$n += $s{$index};
		} else {//奇数位
			$t = $s{$index} * 2;
			if ($t > 9) {
				$t = (int)($t/10) + $t%10;
			}
			$n += $t;
		}
	}
	return ($n % 10) == 0;
}

网上盛传一个采用Luhm校验方法对银行卡卡号进行效验的函数,据笔者测试发现,该函数只能效验16位银行卡卡号,无法效验19位的银行卡卡号,能够效验19位银行卡卡号的函数经笔者整理如下:

function luhm($bankNo) {
	// 奇数之和
	$sumOdd = 0;
	// 偶数之和
	$sumEven = 0;
	// 长度
	$length = strlen($bankNo);
	$wei = [];
	for ($i = 0; $i < $length; $i++) {
		$wei[$i] = substr($bankNo, $length - $i - 1, 1);// 从最末一位开始提取,每一位上的数值
	}
	for ($i = 0; $i < $length / 2; $i++) {
		$sumOdd += $wei[2 * $i];
		if(!isset($wei[2 * $i + 1])) continue;// 如果为19位卡号,要防止报Notice: Undefined offset错误
		if (($wei[2 * $i + 1] * 2) > 9)
			$wei[2 * $i + 1] = $wei[2 * $i + 1] * 2 - 9;
		else
			$wei[2 * $i + 1] *= 2;
		$sumEven += $wei[2 * $i + 1];
	}
	if (($sumOdd + $sumEven) % 10 == 0) {
		return true;
	} else {
		return false;
	}
}

有关FTP客户端传输模式的问题

一般我们在使用FTP客户端传送文件时有两种模式,一种是ASCII,一种是二进制,据笔者的使用经验来看,如果服务器操作系统为Linux或者MAC,而你本地的开发环境为Windows,则应选择二进制模式。当然,很多情况下FTP客户端会自动为你选择二进制模式,但有时也会自动选择ASCII模式,那么在传送文本文件时,它就会处理文本文件里面的换行符,所以有时你会发现从服务器端传下来的文件怎么行间距变的那么大,而从本地上传到服务器上的文件居然会执行出错,把传输模式设置成固定的二进制模式就正常了,这里面也是一个坑!

关于FTP主动(PORT)模式和被动(PASV)模式的简要说明

1、PORT中文称为主动模式,工作原理是: FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,客户端随机开放一个端口(1024以上),发送PORT命令到FTP服务器,告诉服务器客户端采用主动模式并开放端口,FTP服务器收到PORT主动模式命令和端口号后,通过服务器的20端口和客户端开放的端口连接,发送数据。所以在此种模式下,FTP服务器只需用到21、20两个端口,而客户端则需用到一些不确定的随机端口。

2、PASV中文称为被动模式,工作原理是:FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,发送PASV命令到FTP服务器,服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端, 客户端再连接到服务器开放的随机端口上进行数据传输。所以在此种模式下,FTP服务器需用到21端口以及一些不确定的随机端口,而客户端则无需考虑端口问题。

综合来看,使用被动(PASV)模式比较实用,因为这种模式只需考虑服务器端口问题,服务器端口对于运维人员来讲是很容易配置的,而客户端(即用户那边)则无需操心任何问题了。

接下来再讲下FTP服务器端口配置问题, 一般的服务器都有设置防火墙,必须把FTP用到的那些端口列入防火墙白名单中才行,没有防火墙的服务器可无视此问题,不过即便你的服务器没有防火墙,也难保你的服务器的上级网络没有设置防火墙,比如阿里云服务器,它里面有个安全组规则,这个规则就是你服务器的上级防火墙,所以要在这个上级防火墙里面设置好端口才行。另外,在设置之前我们先要确定哪些端口被FTP使用,21端口是确定的,而随机端口只好在FTP服务的配置文件中设定一个范围,比如以pureftp为例,随机端口取值范围为20000-20500的配置方法如下:

# 在pure-ftpd.conf文件中
PassivePortRange            20000 20500
在pure-ftpd.conf文件中

确定好端口后,就可以配置防火墙了,以Centos本地防火墙为例,在/etc/sysconfig/iptables中的配置规则示例如下:

-A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 20000:20500 -m state --state NEW -j ACCEPT
在/etc/sysconfig/iptables文件中

在阿里云安全组规则中的配置示例如下:

里面的20端口其实是可以不用的

关于php捕获500错误的说明

网上关于这个问题的解决方法有很多,这里就针对那些常用的方法做进一步的说明。

方法一:

error_reporting(E_ALL);

这种方法并不能捕获500错误,只能显示出“PHP Notice”、“PHP Warning”、“PHP Deprecated”之类的并不影响代码运行级别的错误,并且必须配合
ini_set(“display_errors”,”On”); 来使用,完整的用法应该是:

ini_set("display_errors","On");
error_reporting(E_ALL);

方法二:

ini_set("display_errors","On");

这种方法能捕获一部分500错误,比如“PHP Fatal error”之类的错误,这种错误可以称之为“严重错误”,一般由于程序中调用了一个没有定义的函数或是访问的文件路径不存在等等,会导致代码中断执行并出现500错误,用此方法即可显示出详细的错误信息并返回给页面正常的200状态。

方法三:

function cache_shutdown_error() {
	$_error = error_get_last();
	if ($_error &amp;&amp; in_array($_error['type'], array(1, 4, 16, 64, 256, 4096, E_ALL))) {
		echo '<font color=red>你的代码出错了:</font></br>';
		echo '致命错误:' . $_error['message'] . '</br>';
		echo '文件:' . $_error['file'] . '</br>';
		echo '在第' . $_error['line'] . '行</br>';
	}
}
register_shutdown_function("cache_shutdown_error");

这种方法看上去很“高大上”,但其实它的效果跟方法二是一样的,也只能捕获
“PHP Fatal error”之类的错误,碰到“PHP Parse error”这种最要命的语法错误也是没辙的,但我们在开发过程中难免一时疏忽少写或多写了个分号或是括号之类的,这种500错误是没有办法捕获到的,只能到web日志文件里面去查了!

Nginx日志分割方法

Nginx不像Apache有自己配套的切割工具,那么我们就需要写个shell脚本来处理分割需求了,脚本示例如下:

# 新建脚本文件并编辑文件内容
vi /usr/local/sbin/nginx_logrotate.sh
#! /bin/bash
d=`date -d "-1 day" +%Y%m%d` #生成昨天的日期
logdir="/www/wdlinux/nginx/logs/" #nginx日志文件目录
nginx_pid="/www/wdlinux/nginx/logs/nginx.pid" #pid文件路径
cd $logdir
for log in `ls *.log`  #把ls列举的.log文件,执行以日期格式的重命名
do
    mv $log $log-$d
done
/bin/kill -HUP `cat $nginx_pid` #重载nginx.pid,可以理解为热启动nginx

给脚本文件授予执行权限:

chmod +x /usr/local/sbin/nginx_logrotate.sh

查看shell脚本执行过程:

sh -x /usr/local/sbin/nginx_logrotate.sh

确认无误后,加入计划任务列表:

# 编辑定时任务
crontab -e
# 加入如下内容
0 0 * * * /usr/local/sbin/nginx_logrotate.sh