1. 启用HTTPS后提示ERR_SSL_PROTOCOL_ERROR

  1. 首先用openssl检查证书是否合法openssl s_client -connect ss.fly2x.com:443 -servername ss.fly2x.com
    系统返回
CONNECTED(00000003)
140495365109576:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 268 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
  1. 查看nginx log。
  • 要找到log,首先查看nginx配置文件
  • nginx配置文件用命令nginx -t显示
2017/01/26 22:45:15 [error] 2952#2952: *117 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: 123.123.123.123, server: 0.0.0.0:443
  1. 这个网页给出了解决方法:
    在虚拟服务器配置文件的listen指令后添加default_server
 listen 443 default_server ssl;

2. 重定向过多

设置config/.config.php中打开debug,查看错误原因

3. "AUTH" failed: ERR Client sent AUTH, but no password is set

给redis设置密码。这个网页告诉我们可以设置在配置文件中永久有效,或者使用redis命令行工具一次有效。
找到配置文件例子,redis.conf,在其中找到reqiurepass,确保它前面没有#号,在后面加上空格,输入密码。
启动redis时,要指定配置文件,否则还是没有密码。./redis-server redis.conf

4. 添加统计代码:

在 resources/views/{主题名} 下创建一个 analytics.tpl,把统计代码贴进去
然后在config/.config.php文件里面把以下设置为true。
$System_Config['enable_analytics_code']='true';

5. 即使开启debug也是500错误:

在public/index.php里面添加
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);

6. php出错提示缺少文件/vendor/autoload.php

运行php composer.phar install安装依赖文件

7. Failed to download xxx/yyy from source: The Process class relies on proc_open, which is not available on your PHP installation.Now trying to download from dist

php禁用了proc_open,于是程序使用了另一种方式下载。
如果没有安装成功就启用proc_open函数。
编辑php.ini,把disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait...里面的proc_open删掉。

8. 后台用户列表,在线列表打不开

下载纯真IP文件到storage目录
运行在网站根目录运行php xcat initQQWry

9. php composer.phar install出错

Cannot create cache directory
/root/.composer/cache/repo/https---packagist.org/, or directory is not writable. Proceeding without cache Cannot create cache directory
/root/.composer/cache/files/, or directory is not writable. Proceeding without cache
[ErrorException]
is_dir(): open_basedir restriction in effect. File(/root/.composer) is not within the allowed path(s):
(/home/wwwroot/default:/tmp/:/proc/:/home/wwwroot)

编辑/etc/php.ini或者/usr/local/php/etc/php.ini,找到open_basedir = /home/wwwroot/default,更改为open_basedir = /home/wwwroot/default:/root/.composer/,用冒号隔开。open_basedir的参数不一定完全一致,在后面加冒号和/root/.composer/即可。
也可以在nginx/conf/fastcgi.conf里面或者站点的conf文件里面添加以下语句
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/:/root/.composer/";
修改完成后重启php和nginx。

service php-fpm restart
service nginx restart

10. 后端无法连接,提示{"ret":0,"data":"token or source is invalid}

  1. 首先面板配置文件中的muKey是可以设置多个,用逗号隔开。检查key是否正确。
  2. 然后,连接API的IP只能是127.0.0.1或者设置的节点IP。
  3. 检查是否开启了cdn,导致面板获得的IP不是节点IP而是cdn的IP。
    可以在节点服务器用curl https://你的站点地址/mod_mu/func/ping?key=设置的muKey,如果响应为{"ret":1,"data":"pong"}那么就成功了。

如果提示(53) SSL Connect Error,更新curl。
如果使用CloudFlare的cdn,可以在nginx该站点配置文件中的server{}里面添加以下代码,将属于CloudFlare的IP段替换为真实IP。

set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;#  以上代码表示从这些ip发送的请求不是用户真实ip
real_ip_header    X-Forwarded-For; # 将请求头的用户ip替换为代理转发的ip
real_ip_recursive on; # nginx会查找转发链,返回第一个不在以上列表中的ip作为用户真实ip

要是nginx提示没有readip模块,需要重新编译安装。加上参数--with-http_realip_module
军哥的lnmp可以很方便地重新编译安装,在lnmp/lnmp.conf里面修改Nginx_Modules_Options='--with-http_realip_module',然后./upgrade.sh nginx即可。
此方法来自https://www.cmsky.com/lnmp-nginx-realip/

  1. 节点有多个ip(ipv4或ipv6)。打开sspanel服务器的访问日志,看看是用的哪个ip访问的服务器。

11. 原版ss怎么设置

服务器端

  • 加密方式,前面带[SS 可连接]的都可以,推荐以下几种
    [SS 可连接] aes-128-gcm

[SS 可连接] aes-192-gcm
[SS 可连接] aes-256-gcm
[SS 可连接] chacha20-ietf-poly1305
[SS 可连接] xchacha20-ietf-poly1305

  • 协议:origin
  • 混淆:
    [SS 可连接] simple_obfs_http

[SS 可连接] simple_obfs_tls

PC

  1. 下载原版安装文件
  2. 下载obfs插件,放到同一文件夹
  3. 添加服务器界面设置插件,参数中的obfs可选参数为http和tls,与服务器端的混淆一致。
    插件:plugin: obfs-local

插件参数:obfs=http;obfs-host=www.baidu.com

  1. 直接扫二维码添加,会自动添加插件配置。

安卓

  1. 在play市场下载原版并安装
  2. 在play市场下载Simple Obfuscation
  3. 在服务器详情界面添加插件并进行配置

12.php xcat setTelegram提示‘bad request’错误

  1. 确认网站已开启https
  2. config/.config.php文件里面的站点地址也必须是https开头

13. 启用Telegram签到,查询等功能

https://www.hengmt.com/408.html

14. 软件下载链接404

首先编辑/usr/local/php/etc/php.ini,将disable_functions里面的system删掉。
在网站根目录运行php xcat initdownload

教程:于江水的Grunt 新手一日入门

Grunt是基于Nodejs的工具,有大量插件来帮助前端工程师做一些重复性的工作,比如:使用jshint检查代码,合并多个js、css文件,压缩js、css文件,编译sass文件,预览项目。

安装必要组件

  1. 下载并安装NodeJS
  2. 安装Grunt,打开Windows命令提示符cmd,使用命令npm install -g grunt-cli-g参数意思是安装到全局,而不是当前目录。
  3. Windows平台安装Ruby,需要使用rubyinstaller
  4. 安装Ruby的包管理工具Gem,需要手动下载这个页面的ZIP文件。解压到任意目录,比如D:\rubygems-2.6.8。在Windows命令提示符中进入该目录,运行命令ruby setup.rb
  5. 安装sass,gem install sass

开始

创建一个项目

创建一个目录,比如说d:\myproj,进入目录运行npm init来创建一个NodeJs项目,并生成该项目的配置文件。
也可以直接创建一个package.json文件。把以下内容贴进去:

{
  "name": "my-project-name",//项目名
  "version": "0.1.0",//项目版本
  "devDependencies": {//开发过程中需要的模块
    "grunt": "~0.4.5",//表示需要版本号为0.4.5的grunt,以及版本号到0.9.9的新版本。
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-nodeunit": "~0.4.1",
    "grunt-contrib-uglify": "~0.5.0"
  }
}

再创建几个目录,来存放不同的文件,可以根据自己需求更改:

  • src:原始的js文件
  • scss: sass文件
  • js: jsHint检查、合并、压缩后的js文件
  • css: 编译,压缩后的css文件

安装Grunt插件

此处需要以下五个插件:

  • 合并文件:grunt-contrib-concat
  • js检查:grunt-contrib-jshint
  • Sass编译: grunt-contrib-sass
  • 压缩文件: grunt-contrib-uglify
  • 监视文件更改:grunt-contrib-watch
  • 建立本地服务器:grunt-contrib-connect

这些插件都是npm包,使用npm命令即可安装npm -g --save-dev grunt-contrib-concat grunt-contrib-jshint grunt-contrib-sass grunt-contrib-uglify grunt-contrib-watch grunt-contrib-connect

--save-dev参数是说将这些包的信息保存到package.json的devDepandencies开发依赖包中。Grunt只在开发过程中使用,开发完成后就不需要了,所以放在devDepandencies。
--save,如果是jQuery、Bootstrap、AngularJS这类前端框架,开发完成后也要使用,就要用这个参数。

配置Grunt

新建一个Gruntfile.js文件,先填上

module.exports = function(grunt) {

  // 项目相关配置
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    //一. 任务配置
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        js: 'build/<%= pkg.name %>.min.js'
      }
    }
  });

  // 二. 载入uglify插件
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // 三. 默认任务
  grunt.registerTask('default', ['uglify']);

};

这个配置文件做了这些事:

  1. 从package.json读取项目配置;
  2. 使用了uglify插件。给插件配置了一个生成顶部信息的参数,并让插件从src目录查找js文件,压缩后放到js目录;
  3. 载入了uglify插件;
  4. 注册一个任务,任务名叫default,任务内容是使用上面定义的uglify插件。在命令行中直接运行grunt,就相当于运行grunt default

接下来还有三步:

配置任务

本文用于解决Excel中,把很多条数据分别填充到一个模板的问题。

需要了解的信息

Excel 函数:

  1. address。接受5个参数,返回由这五个参数生成的对单元格的引用。 用法:address(第几行,第几列(数字),相对引用还是绝对引用,此处用不到不填,另一个工作表的名字)

    比如,`ADDRESS(1,3,1,,"Sheet2")`,返回`Sheet2!$C$1`。这样一来,只要修改它的参数即可更改引用的单元格。但是结果是文本字符串,要得到这个字符串所引用的单元格的值就要用indirect。
  2. indirect。接受2个参数,返回第一个参数指定的单元格的值,第二个参数此处用不到,省略。用法:indirect("上面公式生成的字符串")

    例如,`indirect("Sheet2!$C$1")`,将返回Sheet2工作表,C列,第1行的值。等同于公式`=Sheet2!$C$1`
    

开始

  • 假如打印模板和数据是这样的,模板在Sheet1,数据在Sheet2。打印区域已设置好。
    sheet.png

data.png

姓名单元格的公式就是`=INDIRECT(ADDRESS(2,1,1,,"Sheet2"))`,提取Sheet2表,第二行,第一列的数据。生日的公式就是`=INDIRECT(ADDRESS(2,2,1,,"Sheet2"))`,获取Sheet2表,第二行,第二列的数据。其他单元格以此类推。
  • 这样就做好了基本的样子,接下来让这个模板能填充其他数据

    在一个单元格中填入序号,比如G1。那么第一位同学的数据行号是2,第二位是3,依次递增。那么只需要更改公式中的行号,改成1加上序号,就能让模板内容随着序号改变而更新。那么姓名的公式就该改成`=INDIRECT(ADDRESS(1+G1,1,1,,"Sheet2"))`。请注意ADDRESS函数的第一个参数。这样,改动序号就能填充其他同学的数据了。
    
  • 加个按钮来更改序号吧

    首先在选项-自定义功能区-开发工具前面打勾,确定。点击菜单栏的开发工具,插入ActiveX控件“数值调节钮”。在表上画出一组上下按钮。在按钮上右键-属性,修改Min为1,Max为Sheet2中数据总行数,LinkedCell为G1。
    点击“设计模式”。再点击按钮,序号和模板中的数据应该就可以变化了。
    
  • 加个按钮一键打印

    在开发工具中添加ActiveX控件,按钮。右键按钮选属性,其中Caption就是按钮上显示的文字,改成“打印”或者随便什么文字。
    双击按钮进入代码编辑。在光标位置输入代码`ActiveSheet.PrintOut`。
    退出设计模式,再点击按钮就会以当前默认的打印机、纸张、边距、打印区域等设置打印出当前表了。
    
  • 打印后自动增加序号

    在打印按钮的代码中,`ActiveSheet.PrintOut`下面,添加一句`Range("G1").Value = Range("G1").Value + 1`