ubuntu 使用apt-get install 安装php5.6–php7

使用ppa增加源:

$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install -y php7.0 php7.0-mysql php7.0-curl php7.0-json php7.0-cgi

然后可以查看php版本:

php -v

关于php5.4–php5.6版本

$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get -y install php5.6 php5.6-mcrypt php5.6-mbstring php5.6-curl php5.6-cli php5.6-mysql php5.6-gd php5.6-intl php5.6-xsl php5.6-zip

查看php7的扩展

sudo apt-cache search php7-* 

或者可以源码安装

1、下载php7的源码包
2、tar -zxvf 解压
3、安装一些依赖

sudo apt-get install php5-mcrypt libmcrypt-dev
sudo apt-get install libxslt-dev libxml2-dev

4、

/configure --prefix=/zhou.data/php/php7 --enable-maintainer-zts -with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-mhash --with-openssl --with-zlib --with-bz2 --with-curl --with-zlib --enable-mbstring --with-mcrypt --enable-sockets --with-xsl --enable-zip --with-pear --enable-session --enable-xml --enable-shared --enable-bcmath --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-mbregex --enable-pcntl --with-xmlrpc

5、

make && make install

6、如果报错,缺少哪些依赖,就一次安装即可

记Apache httpd 2.4.6 升级部署 https

一个2014年初上线的项目,要升级https,记录一下。

一共有三台WEB服务器,进入 apache/modules 查看是否有 mod_ssl.so。

两台服务器正常,一台缺失,于是需要动态编译。

官网下载httpd2.4.6(这里需要./httpd -v 查看一下当前版本号),解压缩,进入源码 /modules/ssl/ 目录

cd /usr/local/src/httpd-2.4.6/modules/ssl/

然后执行下面的动态编译命令

当前apahce的路径/bin/apxs -i -c -a -D HAVE_OPENSSL=1 -I /usr/include/openssl -lcrypto -lssl -ldl *.c

此处遇到了第一个坑:报错 /usr/bin/ld: cannot find -lcrypto

搜素一番后,是 /usr/lib64/libssl.so/usr/lib64/libcrypto.so 没有建立软连接。但是搜索出来的解决方案的路径不对,于是参考另外两台服务器

ln -s /lib64/libssl.so.0.9.8e /usr/lib64/libssl.so
ln -s /lib64/libcrypto.so.0.9.8e /usr/lib64/libcrypto.so

使用上面方式建立软链接。

然后再次编译,提示成功了。

但是在httpd restart的时候碰到了第二个坑。

再次报错:mod_ssl.so: undefined symbol: SSL_get_srp_userinfo

搜索一番了解到是 openssl 版本太高。

这才想起来,之前我更新过一次openssl,现在的版本不是 0.9.8e了。

于是 找到现在的openssl对应lib目录 /usr/local/ssl/lib/libcrypto.so.1.0.0

删除现有的链接,重新链接为新的。

rm -rf /usr/lib64/libssl.so
rm -rf usr/lib64/libcrypto.so
ln -s /usr/local/ssl/lib/libssl.so.1.0.0 /usr/lib64/libssl.so
ln -s /usr/local/ssl/lib/libcrypto.so.1.0.0 /usr/lib64/libcrypto.so

于是重新编译apahce,再次重启能够成功了。

在配置https配置文件的过程中,记得要监听443端口并且设置好防火墙规则。

Listen 0.0.0.0:443
Listen [::]:443

其他的配置文件就按照网上的参考就行了。

apache服务器出现No input file specified.解决方案

APACHE服务器出现No input file specified.解决方案 thinkcmf程序默认的.htaccess里面的规则:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

“No input file specified.”,是没有得到有效的文件路径造成的。

修改伪静态规则,如下:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>

就是正则结果“/$1”前面多加了一个“?”号。。

Apache禁止访问目录

本文将详细介绍如何操作禁止显示apache网站根目录

进入apache的配置文件 httpd.conf 找到:

vim /etc/httpd/conf/httpd.conf

Options Indexes FollowSymLinks

修改为:

Options FollowSymLinks

其实就是将Indexes去掉,Indexes表示若当前目录没有index.html就会显示目录结构。

重启Apache服务器

nginx和apache添加brotli算法压缩网站

什么是brotli?

brotli是Google开发的最新压缩算法,有效减少网站传输数据
具体内容请查看WIKI
https://en.wikipedia.org/wiki/Brotli

安装依赖文件[仅限centos]

yum groupinstall 'Development Tools' -y
yum install cmake -y

编译安装brotli库

wget https://github.com/google/brotli/archive/v1.0.3.tar.gz
tar -zxvf v1.0.3.tar.gz
cd brotli-1.0.3
./configure-cmake
make 
make test 
make install

apache/nginx添加编译参数

 "--enable-brotli"  
"--with-brotli=/usr/local/lib"    #apache官方模块,依赖brotli库 

--add-module=../ngx_brotli-master   #添加ngx_brotli模块编译

ngx_brotli模块下载地址
https://github.com/google/ngx_brotli
https://github.com/eustas/ngx_brotli

apache/nginx修改配置文件

http://httpd.apache.org/docs/2.4/mod/mod_brotli.html
apache修改文件 /etc/httpd/conf/extra/httpd-deflate.conf

<IfModule brotli_module> 
 SetOutputFilter BROTLI_COMPRESS;DEFLATE
 SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip no-brotli dont-vary
 BrotliCompressionQuality  6
 BrotliCompressionWindow 18
 AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/xml
 AddOutputFilterByType BROTLI_COMPRESS application/x-javascript application/javascript
 AddOutputFilterByType BROTLI_COMPRESS application/rss+xml
 AddOutputFilterByType BROTLI_COMPRESS application/xml
 AddOutputFilterByType BROTLI_COMPRESS application/json
</IfModule>
#nginx配置文件  
    brotli on;
    brotli_types text/html text/plain text/javascript text/css text/xml text/x-component application/javascript application/x-javascript application/xml application/json application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;
    brotli_static off;
    brotli_comp_level 6;
    brotli_buffers 8 16k;
    brotli_window 512k;
    brotli_min_length 512;

出错解决办法

nginx: error while loading shared libraries: libbrotlienc.so.1: cannot open shared object file: No such file or directory
可行的解决方案之一,是把对应的库文件做软链接:

# 64 位系统  
 ln -s /usr/local/lib/libbrotlienc.so.1 /lib64 
 ln -s /usr/local/lib/libbrotlicommon.so.1  /lib64

# 32 位系统  
ln -s /usr/local/lib/libbrotlienc.so.1 /lib 
ln -s /usr/local/lib/libbrotlicommon.so.1  /lib

重载nginx,若无报错,即问题解决
nginx -s reload

Vagrant搭建虚拟化开发环境

1、安装 VirtualBox

下载地址:https://www.virtualbox.org/wiki/Downloads

2、安装 Vagrant

下载地址:http://downloads.vagrantup.com

3、添加Box

到 vagrantcloud 上找一个 box.

下载地址:http://www.vagrantbox.es

方式一:使用http远程添加

vagrant box add boxName http://BoxUrl

方式二:使用本地box文件

vagrant box add boxName D:/centos-7.0-x86_64.box

个人推荐先使用迅雷将Box下载到本地,再使用方式二安装,因为墙的原因,线上安装会很慢

4、初始化开发环境

vagrant init boxName

接下来执行开机命令,就会进入安装

vagrant up

等个几分钟左右,就安装成功了。成功之后可以输入一下命令可以连接进虚拟机:

vagrant ssh

链接成功之后,就可以对该系统进行操做了

5、常用命令

vagrant init  # 初始化
vagrant up  # 启动虚拟机
vagrant halt  # 关闭虚拟机
vagrant reload  # 重启虚拟机
vagrant ssh  # SSH 至虚拟机
vagrant status  # 查看虚拟机运行状态
vagrant destroy  # 销毁当前虚拟机

错误处理:

在运行 vagrant up时系统没有响应,卡在那不动,系统是win7。

两种解决方式:

  1. 网上有人说是因为VirtualBox和Vagrant版本不对,下载互相匹配的版本即可,我网上找了一些说是可以的匹配版本试了还是不行,放弃了。

  2. 将windows7自带的是powershell 2.0 可以自己升级 到 powershell 5.1。可行

powershell下载地址:https://github.com/PowerShell/PowerShell/releases
下载对应的版本安装即可

参考资料:

Vagrant官方文档 www.vagrantup.com/docs/

Vagrant搭建虚拟化开发环境 www.jianshu.com/p/3c3f35436c05

使用 Vagrant 打造跨平台开发环境 segmentfault.com/a/1190000000264347

Vagrant简介和安装配置 rmingwang.com/vagrant-commands-and-config.html

在windows 7中vagrant up 无反应,没任何信息输出 blog.csdn.net/cow66/article/details/77993908

Vagrant的安装与使用

未分类

什么是 Vagrant?简而言之,这是一个与虚拟机一起工作的工具,可以让你自动创建和删除虚拟机。
— Christopher Shaw

Vagrant 对于虚拟机来说是一个强大的工具,在这里我们将研究如何在 Ubuntu 上设置和使用 Virtualbox 和 Vagrant 来提供可复制的虚拟机。

虚拟机,并不复杂

多年来,开发人员一直使用虚拟机作为其工作流程的一部分,允许他们交换和更改运行软件的环境,这通常是为了防止项目之间的冲突,例如需要 php 5.3 的项目 A 和需要 php 5.4 的项目 B。
并且使用虚拟机意味着你只需要你正在使用的计算机就行,而不需要专用硬件来镜像你的生产环境。
当多个开发人员在一个项目上工作时,它也很方便,他们都可以运行一个包含所有需求的环境,但是维护多台机器并确保所有的需求都具有相同的版本是非常困难的,这时 Vagrant 就能派上用场了。

使用虚拟机的好处

  • 你的虚拟机与主机环境是分开的
  • 你可以根据你代码的要求裁剪一个定制虚拟机
  • 不会影响其他虚拟机
  • 可以运行在你的主机上无法运行的程序,例如在 Ubuntu 中运行一些只能在 Windows 运行的软件

什么是 Vagrant

简而言之,这是一个与虚拟机一起工作的工具,可以让你自动创建和删除虚拟机。
它围绕一个名为 VagrantFile 的配置文件而工作,这个配置文件告诉 Vagrant 你想要安装的操作系统,以及一些其他选项,如 IP 和目录同步。 你还可以在虚拟机上添加一个命令的配置脚本。
通过共享这个 VagrantFile,项目的所有开发人员全可以使用完全相同的虚拟机。

安装要求

安装 VirtualBox

VirtualBox 是运行虚拟机的程序,它可以从 Ubuntu 仓库中安装。

sudo apt-get install virtualbox

安装 Vagrant

对于 Vagrant 本身,你要前往 https://www.vagrantup.com/downloads.html 查看适用于你的操作系统的安装软件包。

安装增强功能

如果你打算与虚拟机共享任何文件夹,则需要安装以下插件。

vagrant plugin install vagrant-vbguest

配置 Vagrant

首先我们需要为 Vagrant 创建一个文件夹。

mkdir ~/Vagrant/test-vm
cd ~/Vagrant/test-vm

创建 VagrantFile:

vagrant init

开启虚拟机:

vagrant up

登录机器:

vagrant-ssh

此时,你将拥有一个基本的 vagrant 机器,以及一个名为 VagrantFile 的文件。

定制

在上面的步骤中创建的 VagrantFile 看起来类似于以下内容
VagrantFile:

    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    # All Vagrant configuration is done below. The "2" in Vagrant.configure
    # configures the configuration version (we support older styles for
    # backwards compatibility). Please don't change it unless you know what
    # you're doing.
    Vagrant.configure("2") do |config|
        # The most common configuration options are documented and commented below.
        # For a complete reference, please see the online documentation at
        # https://docs.vagrantup.com.

        # Every Vagrant development environment requires a box. You can search for
        # boxes at https://vagrantcloud.com/search.
        config.vm.box = "base"

        # Disable automatic box update checking. If you disable this, then
        # boxes will only be checked for updates when the user runs
        # `vagrant box outdated`. This is not recommended.
        # config.vm.box_check_update = false
        # Create a forwarded port mapping which allows access to a specific port
        # within the machine from a port on the host machine. In the example below,
        # accessing "localhost:8080" will access port 80 on the guest machine.
        # NOTE: This will enable public access to the opened port
        # config.vm.network "forwarded_port", guest: 80, host: 8080

        # Create a forwarded port mapping which allows access to a specific port
        # within the machine from a port on the host machine and only allow access
        # via 127.0.0.1 to disable public access
        # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

        # Create a private network, which allows host-only access to the machine
        # using a specific IP.
        # config.vm.network "private_network", ip: "192.168.33.10"
        # Create a public network, which generally matched to bridged network.
        # Bridged networks make the machine appear as another physical device on
        # your network.
        # config.vm.network "public_network"

        # Share an additional folder to the guest VM. The first argument is
        # the path on the host to the actual folder. The second argument is
        # the path on the guest to mount the folder. And the optional third
        # argument is a set of non-required options.
        # config.vm.synced_folder "../data", "/vagrant_data"

        # Provider-specific configuration so you can fine-tune various
        # backing providers for Vagrant. These expose provider-specific options.
        # Example for VirtualBox:
        #
        # config.vm.provider "virtualbox" do |vb|
        #   # Display the VirtualBox GUI when booting the machine
        #   vb.gui = true
        #
        #   # Customize the amount of memory on the VM:
        #   vb.memory = "1024"
        # end
        #
        # View the documentation for the provider you are using for more
        # information on available options.

        # Enable provisioning with a shell script. Additional provisioners such as
        # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
        # documentation for more information about their specific syntax and use.
        # config.vm.provision "shell", inline: <<-SHELL
        #   apt-get update
        #   apt-get install -y apache2
        # SHELL
    end

现在这个 VagrantFile 将创建基本的虚拟机。但 Vagrant 背后的理念是让虚拟机为我们的特定任务而配置,所以我们删除注释和调整配置。
VagrantFile:

    # -*- mode: ruby -*-
    # vi: set ft=ruby :

    Vagrant.configure("2") do |config|
      # Set the Linux Version to Debian Jessie
      config.vm.box = "debian/jessie64"
      # Set the IP of the Box
      config.vm.network "private_network", ip: "192.168.33.10"
      # Sync Our Projects Directory with the WWW directory 
      config.vm.synced_folder "~/Projects", "/var/www/"
      # Run the following to Provision
      config.vm.provision "shell", path: "install.sh"
    end

现在我们有一个简单的 VagrantFile,它将 Linux 版本设置为 debian jessie,设置一个 IP 给我们使用,同步我们感兴趣的文件夹,并最后运行 install.sh,这是我们可以运行 shell 命令的地方。
install.sh:

    #! /usr/bin/env bash
    # Variables
    DBHOST=localhost
    DBNAME=dbname
    DBUSER=dbuser
    DBPASSWD=test123

    echo "[ Provisioning machine ]"
    echo "1) Update APT..."
    apt-get -qq update

    echo "1) Install Utilities..."
    apt-get install -y tidy pdftk curl xpdf imagemagick openssl vim git

    echo "2) Installing Apache..."
    apt-get install -y apache2

    echo "3) Installing PHP and packages..."
    apt-get install -y php5 libapache2-mod-php5 libssh2-php php-pear php5-cli php5-common php5-curl php5-dev php5-gd php5-imagick php5-imap php5-intl php5-mcrypt php5-memcached php5-mysql php5-pspell php5-xdebug php5-xmlrpc
    #php5-suhosin-extension, php5-mysqlnd

    echo "4) Installing MySQL..."
    debconf-set-selections <<< "mysql-server mysql-server/root_password password secret"
    debconf-set-selections <<< "mysql-server mysql-server/root_password_again password secret"
    apt-get install -y mysql-server
    mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME"
    mysql -uroot -p$DBPASSWD -e "grant all privileges on $DBNAME.* to '$DBUSER'@'localhost' identified by '$DBPASSWD'"

    echo "5) Generating self signed certificate..."
    mkdir -p /etc/ssl/localcerts
    openssl req -new -x509 -days 365 -nodes -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -out /etc/ssl/localcerts/apache.pem -keyout /etc/ssl/localcerts/apache.key
    chmod 600 /etc/ssl/localcerts/apache*

    echo "6) Setup Apache..."
    a2enmod rewrite
    > /etc/apache2/sites-enabled/000-default.conf
    echo "
    <VirtualHost *:80>
            ServerAdmin webmaster@localhost
            DocumentRoot /var/www/
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>

    " >> /etc/apache2/sites-enabled/000-default.conf
    service apache2 restart 

    echo "7) Composer Install..."
    curl --silent https://getcomposer.org/installer | php 
    mv composer.phar /usr/local/bin/composer

    echo "8) Install NodeJS..."
    curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - 
    apt-get -qq update
    apt-get -y install nodejs 

    echo "9) Install NPM Packages..."
    npm install -g gulp gulp-cli

    echo "Provisioning Completed"

通过上面的步骤,在你的目录中会有 VagrantFile 和 install.sh,运行 vagrant 会做下面的事情:

  • 采用 Debian Jessie 来创建虚拟机
  • 将机器的 IP 设置为 192.168.33.10
  • 同步 ~/Projects 和 /var/www/ 目录
  • 安装并设置 Apache、Mysql、PHP、Git、Vim
  • 安装并运行 Composer
  • 安装 Nodejs 和 gulp
  • 创建一个 MySQL 数据库
  • 创建自签名证书

通过与其他人共享 VagrantFile 和 install.sh,你可以在两台不同的机器上使用完全相同的环境。

基于Nginx+lua的蓝绿发布系统

一、什么是蓝绿发布

蓝绿部署是不停老版本,部署新版本然后进行测试,确认OK,将流量切到新版本,然后老版本同时也升级到新版本。

1、特点

蓝绿部署无需停机,并且风险较小。

2、蓝绿发布的注意事项

当你切换到蓝色环境时,需要妥当处理未完成的业务和新的业务。如果你的数据库后端无法处理,会是一个比较麻烦的问题;

可能会出现需要同时处理“微服务架构应用”和“传统架构应用”的情况,如果在蓝绿部署中协调不好这两者,还是有可能会导致服务停止。
需要提前考虑数据库与应用部署同步迁移 /回滚的问题。
蓝绿部署需要有基础设施支持。
在非隔离基础架构( VM 、 Docker 等)上执行蓝绿部署,蓝色环境和绿色环境有被摧毁的风险。

二、为什么需要蓝绿发布系统

1、新项目和新需求非常多

2、新需求的上线过程是,先上线一台服务器然后观察会不会出问题,如果没有问题则全部上线。

3、分流是关键,但是动态分流是痛点。

三、老分流方案

未分类

方案存在的问题点:

1、nginx.conf配置文件里各种if、set和rewrite,并且容易配置出错。
2、修改完配置文件后,重启或者reload后才能生效。
3、不能实现太复杂的逻辑。
4、不能实现一些特殊分流方式。

四、新分流方案

未分类

功能说明:

  • 采用Redis存放分流策略
  • 分流策略包括按时间来分流,比如每分钟分流多少笔订单,还有按权重分流,比如新老系统之间的比例是1:9
  • 采用OpenResty+lua,整体性能优秀。

单台压测结果:

未分类

配置Lua转发Nginx请求复制

通过配置Nginx来将请求进行复制,转发到其他应用,以下是自己实际搭建的步骤以及自己的理解,方便以后使用

1、环境搭建

实际搭建环境如下:Linux CenterOS 6.5 ,Nginx1.9.0,headers-more-nginx-module-0.31,LuaJIT-2.1.0-beta2,lua-nginx-module-0.10.2,ngx_devel_kit-0.2.19。

以上是搭建成功的各个对应版本,如果版本不对应可能会导致nginx编译失败,github下载后的插件尽量重命名一下,方便使用。

按照参考链接进行编译Nginx。

2、Nginx+Lua文件配置

a、编写一个 copy request 的 lua 脚本copy_req.lua

local res1, res2, action
action = ngx.var.request_method
if action == "POST" then
        arry = {method = ngx.HTTP_POST, body = ngx.req.read_body()}
else
        arry = {method = ngx.HTTP_GET}
end

if ngx.var.svr == "on" then
        res1, res2 = ngx.location.capture_multi {
                { "/product" .. ngx.var.request_uri , arry},
                { "/test" .. ngx.var.request_uri , arry},
        }
else
        res1, res2 = ngx.location.capture_multi {
                { "/product" .. ngx.var.request_uri , arry},
        }
end

if res1.status == ngx.HTTP_OK then
        local header_list = {"Content-Length", "Content-Type", "Content-Encoding", "Accept-Ranges"}
        for _, i in ipairs(header_list) do
                if res1.header[i] then
                        ngx.header[i] = res1.header[i]
                end
        end
        ngx.say(res1.body)  #此处代表只返回生产环境的返回结果
else
        ngx.status = ngx.HTTP_NOT_FOUND
end

此处文件地址引用是可以写觉得地址,相对地址是相对于nginx目录的。
b、配置对应的Nginx配置文件,此处本文地址是conf/vhost/fenliu.conf,在nginx.conf下端加入include vhost/*.conf;

fenliu.conf文件配置如下:

upstream product {
        server  127.0.0.1:80;
}
upstream test {
        server  192.168.1.1:88;
}
server {
        listen      8000;
        #lua_code_cache off;

        location ~* ^/product {
                log_subrequest on;
                rewrite ^/product(.*)$ $1 break;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://product;
                access_log logs/product-upstream.log;
        }

        location ~* ^/test {
                log_subrequest on;
                rewrite ^/test(.*)$ $1 break;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://test;
                access_log logs/test-upstream.log;
        }

        location ~* ^/(.*)$ {
                client_body_buffer_size 2m;
                set $svr    "on";              #开启或关闭copy功能
                content_by_lua_file conf/vhost/copy_req.lua;
        }
}

此文件很重要,这里备注的是本人自己的理解,^/product,^/test主要就是对这两个路径访问的url进行转发,一个转发到生产,一个到测试,多了一个rewrite是为了重写请求地址,下面会讲到,
^/(.*)$才是重点,是将所有非product,test请求进行请求复制转发。

以上面配置为例,实际使用的流程如下:

1、请求地址:http://ip:8000/hello/req.do
2、nginx不匹配product和test会走最后一个,通过Lua配置会变成两个请求/product/hello/req.do和/test/hello/req.do
3、这时会被nginx的product和test拦截到,进行转发到生产和测试环境,此时地址是不对的,所以使用rewrite进行url重写,
rewrite ^/product(.*)$ $1 break; 匹配/product/hello/req.do会变成/product(/hello/req.do),$1代表/hello/req.do,重写后的地址就会变成我们想要的地址,转发后就变成http://product/hello/req.do。

openresty下lua的function定义及调用

本文主要研究下如何在openresty下lua的function定义及调用。

源码示例

/usr/local/openresty/lualib/resty/string.lua

-- Copyright (C) by Yichun Zhang (agentzh)


local ffi = require "ffi"
local ffi_new = ffi.new
local ffi_str = ffi.string
local C = ffi.C
local setmetatable = setmetatable
local error = error
local tonumber = tonumber


local _M = { _VERSION = '0.09' }


ffi.cdef[[
typedef unsigned char u_char;

u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len);

intptr_t ngx_atoi(const unsigned char *line, size_t n);
]]

local str_type = ffi.typeof("uint8_t[?]")


function _M.to_hex(s)
    local len = #s * 2
    local buf = ffi_new(str_type, len)
    C.ngx_hex_dump(buf, s, #s)
    return ffi_str(buf, len)
end


function _M.atoi(s)
    return tonumber(C.ngx_atoi(s, #s))
end


return _M

实例

demo.lua

local _M = { _VERSION = '0.01' }
function _M.hello()
    ngx.say("hello from demo module!")
end
return _M

conf

        location /function {
            content_by_lua '
                local demo = require("demo")
                demo.hello()
            ';
        }

报错

2018/03/26 16:24:15 [error] 5#5: *1 lua entry thread aborted: runtime error: content_by_lua(nginx.conf:69):2: module 'demo' not found:
    no field package.preload['demo']
    no file '/usr/local/openresty/lualib/demo.lua'
    no file '/usr/local/openresty/lualib/demo/init.lua'
    no file './demo.lua'
    no file '/usr/local/openresty/luajit/share/luajit-2.1.0-beta2/demo.lua'
    no file '/usr/local/share/lua/5.1/demo.lua'
    no file '/usr/local/share/lua/5.1/demo/init.lua'
    no file '/usr/local/openresty/luajit/share/lua/5.1/demo.lua'
    no file '/usr/local/openresty/luajit/share/lua/5.1/demo/init.lua'
    no file '/usr/local/openresty/lualib/demo.so'
    no file './demo.so'
    no file '/usr/local/lib/lua/5.1/demo.so'
    no file '/usr/local/openresty/luajit/lib/lua/5.1/demo.so'
    no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
coroutine 0:
    [C]: in function 'require'
    content_by_lua(nginx.conf:69):2: in function <content_by_lua(nginx.conf:69):1>, client: 192.168.99.1, server: , request: "GET /function HTTP/1.1", host: "192.168.99.100:8686"

修复

ADD demo.lua /usr/local/openresty/lualib/demo.lua

小结

从源码可以看出,基本是定义一个_M变量,里头有个_VERSION属性,然后定义_M的function,最后返回_M。另外注意自己定义的类库需要放在openresty查找的路径下面,否则会报错。