使用Vagrant配置并创建属于自己的CentOS box

在使用Vagrant创建虚拟机时,我们要使用CentOS的box来创建虚拟机,而官方提供的box是原版的box,创建完成后还需要自己手动配置环境。我们可以创建一个已经装载好自己需要的常用软件依赖的box,然后将这个box重复使用。

先讲一下相关知识:

  • CentOS7自带的Python版本为2.7。
    python2.7,也就是2版,依然是一种长期支持的稳定版,是传统python;同时系统的yum也只能在python2环境下使用。
    而python3.x版本是一个研究型的开发版,为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下兼容。

  • Linux很多应用都安装在/usr/local下面(usr指的是Unix System Resource,不是指user),而/usr/bin下面的都是系统预装的可执行程序(python2就在这里面),会随着系统升级而改变;如果两个目录下有相同的可执行程序,谁优先执行受到PATH环境变量的影响,比如我的一台服务器的PATH变量为
    echo $PATH
    /usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/dean/bin
    这里/usr/local/bin优先于/usr/bin。

安装centos7原版虚拟机方法请参考实验一第四条:安装Vagrant,并使用Vagrant安装CentOS

安装完成后使用XShell以root用户身份登录
然后update一下:yum -y update
完成后重启一下:reboot,重启完成后重新连进去

一、在CentOS虚拟机中安装Python3

由于可以使用PyCharm位每个项目都创建一个唯一的CentOS虚拟机,所以我们在这里直接装原版Python3:
安装方法可参考之前的实验(直接装在/usr/bin目录下,并将python软链直接指向python3,然后修复yum命令)
或者参考该博文(装在/usr/local/bin目录下,把用户自定义的配置放入/etc/profile.d/目录中):
CentOS7安装Python3环境(无需修复yum命令) – 小武的兴趣部落 – CSDN博客

注意:
“3.7.0”要换成“3.6.6”

安装常用软件:

yum -y install git zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel epel-release openssl-devel kernel-devel gcc

安装pip:

yum -y install python-pip

更新pip:

pip install --upgrade pip

安装flask和Jinja2:

pip install flask jinja2

至此,我们就已经制作了一个带有Python3环境的CentOS虚拟机了。

二、打包BOX

先关闭刚刚创建的虚拟机
然后以管理员身份打开cmd,进入刚刚创建的虚拟机的Vagrantfile所在的文件夹
执行以下语句:

vagrant package

完成后便会在该目录下生成一个“package.box”,这个box即为打包好当前环境的box

现在将该box加载到vagrant的box list中:

vagrant box add --name 'my-virtualbox' package.box

看是否添加成功:

vagrant box list

新建一个文件夹,用来存放init该box后产生的Vagrantfile文件:

cd ..
mkdir myCentOS
cd myCentOS
123

Init该box:

vagrant init my-virtualbox

完成后便可在myCentOS文件夹中就可以看到自己创建的box的Vagrantfile文件。

Vagrant使用方法

1.虚拟机操作

1.1 查看vagrant中有多少个虚拟机

E:>vagrant box list
centos7 (virtualbox, 0)

这个命令的返回结果表示我的vagrant 中有一个虚拟机,虚拟机的名字是centos7

1.2 新增一个vagrant虚拟机

E:>md centos7test

E:>cd centos7test

E:centos7test>vagrant box add centos7test E:vagrantvagrant-centos-7.2.box
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'centos7test' (v0) for provider:
    box: Unpacking necessary files from: file:///E:/vagrant/vagrant-centos-7.2.box
    box: Progress: 100% (Rate: 117M/s, Estimated time remaining: --:--:--)
==> box: Successfully added box 'centos7test' (v0) for 'virtualbox'!

E:centos7test>vagrant box list
centos7     (virtualbox, 0)
centos7test (virtualbox, 0)

参数解析:

  • add 表示新增虚拟机
  • centos7test 这个是虚拟增虚拟机的名字
  • E:vagrantvagrant-centos-7.2.box 这个是镜像文件所在位置

1.3 创建一个vagrant配置文件

E:centos7test>vagrant init centos7test
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

1.4 打开虚拟机

先cd 到虚拟机所在目录。然后使用vagrant up命令启动虚拟机

E:centos7test>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos7test'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: centos7test_default_1538399987116_82773
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection reset. Retrying...
    default: Warning: Connection aborted. Retrying...
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 4.3.30
    default: VirtualBox Version: 5.2
==> default: Mounting shared folders...
    default: /vagrant => E:/centos7test

1.5 关闭虚拟机

使用vagrant halt 命令关闭虚拟机

E:centos7test>vagrant halt
==> default: Attempting graceful shutdown of VM...

1.6 重载虚拟机配置文件

使用vagrant reload 命令重载虚拟机配置文件

E:centos7test>vagrant reload

2.虚拟机配置

虚拟机配置都放在虚拟机所在目录下,文件名是Vagrantfile,没有扩展名。

2.1 修改端口映射

先打开Vagrantfile, 发现都是# ,井号代表注释。在 Vagrant.configure(“2”) do |config| 下面新增一行()

config.vm.network "forwarded_port", guest: 80, host: 8080

这句话代表 把虚拟机的80端口映射成宿主机的8080端口

2.2 修改虚拟机内存

配置文件里有写好的配置方法,直接修改这个就行了,但是要注意把注释打开。

  config.vm.provider "virtualbox" do |vb|  
    # Customize the amount of memory on the VM:
    vb.memory = "1024"
  end

2.3 修改网卡设置

先打开Vagrantfile。在 Vagrant.configure(“2”) do |config| 下面新增一行()

  config.vm.network "private_network", ip: "192.168.56.10"

Lua的集成开发环境ZeroBrane Studio

目前在使用Lua进行脚本的开发,可是官方并没有提供很好的集成开发环境。
体验了很多,发现ZeroBrane Studio这个开源软件还是非常好用的,并且已经能正常支持Linux,Windows,MacOS这三个主流平台。

建议去官方网站下载最新的版本,但是鉴于国内网络访问不是非常稳定,可以从本站下载一份目前最新的版本。

下面的版本根据自身操作系统来选择其中一个进行下载

https://www.mobibrw.com/wp-content/uploads/2018/09/ZeroBraneStudioEduPack-1.70-linux.sh_.zip

https://www.mobibrw.com/wp-content/uploads/2018/09/ZeroBraneStudioEduPack-1.70-macos.dmg_.zip

https://www.mobibrw.com/wp-content/uploads/2018/09/ZeroBraneStudioEduPack-1.70-win32.exe_.zip

树莓派下的编译(目前编译出的暂时无法使用):

$ git clone https://github.com/pkulchenko/ZeroBraneStudio.git

#如果代码下载存在问题,可以本站下载一份拷贝
# wget https://www.mobibrw.com/wp-content/uploads/2018/09/ZeroBraneStudio.tar.xz
# tar xvf ZeroBraneStudio.tar.xz

$ cd ZeroBraneStudio

$ cd build

$ bash build-linux-prep-deb.sh

# gthread
$ sudo apt-get install libglib2.0-dev

# gtk+
$ sudo apt-get install libgtk2.0-dev

$ sudo apt-get install libgtk-3-dev

#opengl
$ sudo apt-get install freeglut3-dev

# ssl for luasec
$ sudo apt-get install libssl-dev

$ sudo ln -s /usr/lib/arm-linux-gnueabihf/libssl.so /usr/lib/libssl.so

# lua
$ sudo apt-get install lua5.1 liblua5.1-dev

#webview可选
#sudo apt-get install libwebkitgtk-dev

# luasec最新版本,早期版本编译不通过
$ sed -i "s/^LUASEC_BASENAME="luasec-0.6"/LUASEC_BASENAME="luasec-0.7"/g" build-linux.sh

#此处wxWidgets的克隆比较慢,因此可以本站下载一份拷贝,手工修改脚本的下载
# wget https://www.mobibrw.com/wp-content/uploads/2018/09/wxWidgets.tar.xz
# sed -i "s/^[ t]*git clone "$WXWIDGETS_URL".*/  wget https://www.mobibrw.com/wp-content/uploads/2018/09/wxWidgets.tar.xzn  rm -rf wxWidgetsn  tar xvf wxWidgets.tar.xz/g" build-linux.sh
# wget 
# sed -i "s/^[ t]*git clone "$WXLUA_URL" "$WXLUA_BASENAME".*/ wget https://www.mobibrw.com/wp-content/uploads/2018/09/wxlua.tar.xzn rm -rf wxluan tar xvf wxlua.tar.xz/g" build-linux.sh
# sed -i "s/^LEXLPEG_URL="https://foicica.com/scintillua/download/LEXLPEG_URL="https://www.mobibrw.com/wp-content/uploads/2018/09/g" build-linux.sh

# for debug "bash build-linux.sh debug all"
$ bash build-linux.sh all

#编译两次,解决第一次的问题,第一次有些目录创建存在问题
$ bash build-linux.sh all

#还是需要安装一些依赖,上面编译的库并没有完整完成依赖设置
$ sudo apt-get install luarocks

$ sudo luarocks install luasocket

$ cp deps/lib/libwx.so deps/lib/wx.so

#动态链接库应当设置LUA_CPATH而不是LUA_PATH
$ export LUA_CPATH="`pwd`/deps/lib/?.so;`pwd`/deps/lib/lua/51/?.so"

$ export LD_LIBRARY_PATH=`pwd`/deps/lib

#去掉两个检测,这两检测总是会失败,原因不好排查
$ sed -i "s/check_lua_module(wx TRUE)/#check_lua_module(wx TRUE)/g" CMakeLists.txt 

$ sed -i "s/check_lua_module(socket TRUE)/#check_lua_module(socket TRUE)/g" CMakeLists.txt

$ cmake -DCMAKE_SYSROOT=`pwd`/deps/ -DCMAKE_FIND_ROOT_PATH=`pwd`/deps/ .

$ make 

$ sudo make install

使用 Android NDK 编译 Lua

启动 Android Studio ,创建一个 Android 项目,勾选 C++ Support。

未分类

一路 Next 到这里,直接 Finish,不用勾选保持默认即可。

未分类

如果之前没有安装 NDK 和 Cmake 工具,到这里会提示安装 NDK 等工具,直接安装,我这里之前已经安装了,所以略过。

等待工程就绪之后,正常构建一次,看 Hello World 能不能正常构建运行起来。查看编译后的 APK 文件,看看里面是否有下列目录和 .so 文件。

Executing tasks: [:app:assembleDebug]
省略一堆Log
External native generate JSON debug: JSON generation completed without problems
:app:externalNativeBuildDebug
Build native-lib x86_64
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ........buildintermediatescmakedebugobjx86_64libnative-lib.so
Build native-lib x86
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ........buildintermediatescmakedebugobjx86libnative-lib.so
Build native-lib arm64-v8a
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ........buildintermediatescmakedebugobjarm64-v8alibnative-lib.so
Build native-lib armeabi-v7a
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ........buildintermediatescmakedebugobjarmeabi-v7alibnative-lib.so
:app:compileDebugSources
:app:mergeDebugShaders
:app:compileDebugShaders
:app:generateDebugAssets
:app:mergeDebugAssets
:app:transformClassesWithDexBuilderForDebug
:app:transformDexArchiveWithExternalLibsDexMergerForDebug
:app:transformDexArchiveWithDexMergerForDebug
:app:mergeDebugJniLibFolders
:app:transformNativeLibsWithMergeJniLibsForDebug
:app:transformNativeLibsWithStripDebugSymbolForDebug
:app:processDebugJavaRes NO-SOURCE
:app:transformResourcesWithMergeJavaResForDebug
:app:validateSigningDebug
:app:packageDebug
:app:assembleDebug

BUILD SUCCESSFUL in 12s
29 actionable tasks: 16 executed, 13 up-to-date

通过 7-Zip 可以查看 APK 里面的文件组成结构,如下是 lib 目录下的内容,分别对应不同的 CPU 架构。

未分类

如果能到这一步,说明至少 Android Studio 配置基本是 OK 的,NDK 能正常工作。

在 Android Studio 3.1 后,Gradle Console 就不见了,要查看构建过程和步骤,在 Build 窗口点击 Toggle View 就可以查看构建步骤了。

未分类

在 Project 面板中,CPP 目录下的文件就是 C/CPP 的源文件目录,我们从 Lua 官网下载源码后,将 .c 和 .h 文件当道这个目录下面。

未分类

目前我能下载到最新的 Lua 版本是 5.3.5 ,粘贴到 CPP 目录后,文件并不会显示,不知道这是不是 Android Studio 的 bug,接下来修改 CMakeLists.txt 里面的内容,将源代码增加到构建列表。

add_library( # Sets the name of the library.
             luajit

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/lapi.c
             src/main/cpp/lauxlib.c
             src/main/cpp/lbaselib.c
             src/main/cpp/lbitlib.c
             src/main/cpp/lcode.c
             src/main/cpp/lcorolib.c
             src/main/cpp/lctype.c
             src/main/cpp/ldblib.c
             src/main/cpp/ldebug.c
             src/main/cpp/ldo.c
             src/main/cpp/ldump.c
             src/main/cpp/lfunc.c
             src/main/cpp/lgc.c
             src/main/cpp/linit.c
             src/main/cpp/liolib.c
             src/main/cpp/llex.c
             src/main/cpp/lmathlib.c
             src/main/cpp/lmem.c
             src/main/cpp/loadlib.c
             src/main/cpp/lobject.c
             src/main/cpp/lopcodes.c
             src/main/cpp/loslib.c
             src/main/cpp/lparser.c
             src/main/cpp/lstate.c
             src/main/cpp/lstate.h
             src/main/cpp/lstring.c
             src/main/cpp/lstrlib.c
             src/main/cpp/ltable.c
             src/main/cpp/ltablib.c
             src/main/cpp/ltm.c
             src/main/cpp/lua.c
             src/main/cpp/lua.hpp
             src/main/cpp/lundump.c
             src/main/cpp/lutf8lib.c
             src/main/cpp/lvm.c
             src/main/cpp/lzio.c)

执行编译,这个时候 Build 窗口可能会出现一片红 …

未分类

具体错误内容如下:

Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
  Error while executing process D:ANDROIDSdkcmake3.6.4111459bincmake.exe with arguments {--build D:ANDROID_PROJECTSHelloLua2app.externalNativeBuildcmakedebugx86_64 --target luajit}
  [1/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
  [2/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
  [3/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
  [4/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
  [5/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
  [6/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
  [7/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
  [8/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
  [9/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
  [10/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
  [11/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
  [12/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
  [13/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
  [14/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
  [15/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
  [16/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
  [17/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
  [18/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
  [19/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
  [20/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
  [21/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
  [22/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
  [23/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
  [24/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
  [25/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
  [26/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
  [27/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
  [28/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/luac.c.o
  [29/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
  [30/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
  [31/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
  [32/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
  [33/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
  [34/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
  [35/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
  D:ANDROID_PROJECTSHelloLua2appsrcmaincpploslib.c:169:3: warning: 'tmpnam' is deprecated: tempnam is unsafe, use mkstemp or tmpfile instead [-Wdeprecated-declarations]
    lua_tmpnam(buff, err);
    ^
  D:ANDROID_PROJECTSHelloLua2appsrcmaincpploslib.c:131:33: note: expanded from macro 'lua_tmpnam'
  #define lua_tmpnam(b,e)         { e = (tmpnam(b) == NULL); }
                                         ^
  D:/ANDROID/Sdk/ndk-bundle/sysroot/usr/includestdio.h:167:5: note: 'tmpnam' has been explicitly marked deprecated here
      __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
      ^
  D:/ANDROID/Sdk/ndk-bundle/sysroot/usr/includesys/cdefs.h:160:40: note: expanded from macro '__warnattr'
  #define __warnattr(msg) __attribute__((deprecated(msg)))
                                         ^
  1 warning generated.
  [36/36] Linking C shared library ........buildintermediatescmakedebugobjx86_64libluajit.so
  FAILED: cmd.exe /C "cd . && D:ANDROIDSdkndk-bundletoolchainsllvmprebuiltwindows-x86_64binclang.exe  --target=x86_64-none-linux-android21 --gcc-toolchain=D:/ANDROID/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64 --sysroot=D:/ANDROID/Sdk/ndk-bundle/sysroot -fPIC -isystem D:/ANDROID/Sdk/ndk-bundle/sysroot/usr/include/x86_64-linux-android -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot D:/ANDROID/Sdk/ndk-bundle/platforms/android-21/arch-x86_64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -LD:/ANDROID/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/x86_64 -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libluajit.so -o ........buildintermediatescmakedebugobjx86_64libluajit.so CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o CMakeFiles/luajit.dir/src/main/cpp/linit.c.o CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o CMakeFiles/luajit.dir/src/main/cpp/llex.c.o CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o CMakeFiles/luajit.dir/src/main/cpp/lua.c.o CMakeFiles/luajit.dir/src/main/cpp/luac.c.o CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o  -llog -latomic -lm && cd ."
  D:/ANDROID/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/binld: error: CMakeFiles/luajit.dir/src/main/cpp/luac.c.o: multiple definition of 'main'
  D:/ANDROID/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/binld: CMakeFiles/luajit.dir/src/main/cpp/lua.c.o: previous definition here
  clang.exe: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 9s
21 actionable tasks: 18 executed, 3 up-to-date

提示中说的也比较清楚,我们使用了已经废弃了的函数:warning: ‘tmpnam’ is deprecated: tempnam is unsafe, use mkstemp or tmpfile instead,但是项目中,使用这个 tmpnam 的比较多,而且需要改 Lua 源代码,本着不对 Lua 改动的原则,我们在 CMakeLists.txt 中增加下面的一行代码,屏蔽废弃函数的错误警告。

add_definitions(-Wno-deprecated)

最终,文件结构如下:

未分类

继续编译,发现依然编译不通过,Build 窗口依然一片红,如下:

Executing tasks: [clean, :app:assembleDebug]
省略一堆Log
* What went wrong:
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
  Error while executing process D:ANDROIDSdkcmake3.6.4111459bincmake.exe with arguments {--build D:ANDROID_PROJECTSHelloLua2app.externalNativeBuildcmakedebugx86_64 --target luajit}
  Recompacting log...
  [1/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
  [2/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
  [3/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
  [4/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
  [5/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
  [6/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
  [7/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
  [8/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
  [9/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
  [10/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
  [11/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
  [12/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
  [13/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
  [14/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
  [15/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
  [16/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
  [17/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
  [18/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
  [19/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
  [20/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
  [21/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
  [22/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
  [23/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
  [24/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
  [25/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
  [26/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
  [27/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
  [28/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
  [29/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
  [30/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
  [31/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
  [32/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
  [33/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
  [34/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/luac.c.o
  [35/36] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
  [36/36] Linking C shared library ........buildintermediatescmakedebugobjx86_64libluajit.so
  FAILED: cmd.exe /C "cd . && D:ANDROIDSdkndk-bundletoolchainsllvmprebuiltwindows-x86_64binclang.exe  --target=x86_64-none-linux-android21 --gcc-toolchain=D:/ANDROID/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64 --sysroot=D:/ANDROID/Sdk/ndk-bundle/sysroot -fPIC -isystem D:/ANDROID/Sdk/ndk-bundle/sysroot/usr/include/x86_64-linux-android -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot D:/ANDROID/Sdk/ndk-bundle/platforms/android-21/arch-x86_64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -LD:/ANDROID/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/x86_64 -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libluajit.so -o ........buildintermediatescmakedebugobjx86_64libluajit.so CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o CMakeFiles/luajit.dir/src/main/cpp/linit.c.o CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o CMakeFiles/luajit.dir/src/main/cpp/llex.c.o CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o CMakeFiles/luajit.dir/src/main/cpp/lua.c.o CMakeFiles/luajit.dir/src/main/cpp/luac.c.o CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o  -llog -latomic -lm && cd ."
  D:/ANDROID/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/binld: error: CMakeFiles/luajit.dir/src/main/cpp/luac.c.o: multiple definition of 'main'
  D:/ANDROID/Sdk/ndk-bundle/toolchains/x86_64-4.9/prebuilt/windows-x86_64/lib/gcc/x86_64-linux-android/4.9.x/../../../../x86_64-linux-android/binld: CMakeFiles/luajit.dir/src/main/cpp/lua.c.o: previous definition here
  clang.exe: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 9s
21 actionable tasks: 19 executed, 2 up-to-date

在这个错误里,有两处非常明显:

error: CMakeFiles/luajit.dir/src/main/cpp/luac.c.o: multiple definition of 'main'
CMakeFiles/luajit.dir/src/main/cpp/lua.c.o: previous definition here

事实上,我们也不需要 Main 函数的定义,因为编译为 SHARE_LIBRARY ,所以屏蔽这个文件即可。

未分类

再次构建,发现还是一片红… 错误如下:

省略一堆Log
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
  Error while executing process D:ANDROIDSdkcmake3.6.4111459bincmake.exe with arguments {--build D:ANDROID_PROJECTSHelloLua2app.externalNativeBuildcmakedebugx86 --target luajit}
  [1/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
  [2/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
  [3/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
  [4/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
  [5/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
  [6/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
  [7/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
  [8/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
  [9/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
  [10/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
  [11/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
  [12/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
  [13/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
  [14/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
  [15/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
  [16/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
  [17/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
  [18/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
  [19/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
  [20/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
  [21/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
  [22/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
  [23/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
  [24/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
  [25/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
  [26/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
  [27/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
  [28/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
  [29/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
  [30/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
  [31/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
  [32/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
  [33/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
  [34/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
  [35/35] Linking C shared library ........buildintermediatescmakedebugobjx86libluajit.so
  FAILED: cmd.exe /C "cd . && D:ANDROIDSdkndk-bundletoolchainsllvmprebuiltwindows-x86_64binclang.exe  --target=i686-none-linux-android19 --gcc-toolchain=D:/ANDROID/Sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/windows-x86_64 --sysroot=D:/ANDROID/Sdk/ndk-bundle/sysroot -fPIC -isystem D:/ANDROID/Sdk/ndk-bundle/sysroot/usr/include/i686-linux-android -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot D:/ANDROID/Sdk/ndk-bundle/platforms/android-19/arch-x86 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -LD:/ANDROID/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/x86 -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libluajit.so -o ........buildintermediatescmakedebugobjx86libluajit.so CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o CMakeFiles/luajit.dir/src/main/cpp/linit.c.o CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o CMakeFiles/luajit.dir/src/main/cpp/llex.c.o CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o CMakeFiles/luajit.dir/src/main/cpp/lua.c.o CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o  -llog -latomic -lm && cd ."
  D:ANDROID_PROJECTSHelloLua2appsrcmaincpp/liolib.c:446: error: undefined reference to 'localeconv'
  D:ANDROID_PROJECTSHelloLua2appsrcmaincpp/lobject.c:287: error: undefined reference to 'localeconv'
  D:ANDROID_PROJECTSHelloLua2appsrcmaincpp/lobject.c:381: error: undefined reference to 'localeconv'
  D:ANDROID_PROJECTSHelloLua2appsrcmaincpp/lstrlib.c:936: error: undefined reference to 'localeconv'
  clang.exe: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 12s
21 actionable tasks: 18 executed, 3 up-to-date

这次的错误都是这一个:undefined reference to ‘localeconv’,解决办法是提高 API Level ,我们把它改为 21 以上就可以解决这个问题。

再次构建,终于不再报错了,结果如下:

Executing tasks: [clean, :app:assembleDebug]
省略一堆Log
:app:externalNativeBuildCleanDebug
Clean luajit armeabi-v7a
Cleaning... 0 files.
Clean luajit arm64-v8a
Cleaning... 0 files.
Clean luajit x86
Cleaning... 0 files.
Clean luajit x86_64
Cleaning... 35 files.
:app:externalNativeBuildCleanRelease
Clean luajit armeabi-v7a
Cleaning... 0 files.
Clean luajit arm64-v8a
Cleaning... 0 files.
Clean luajit x86
Cleaning... 0 files.
Clean luajit x86_64
Cleaning... 0 files.
:app:clean
:app:preBuild UP-TO-DATE
:app:preDebugBuild
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:checkDebugManifest
:app:generateDebugBuildConfig
:app:prepareLintJar UP-TO-DATE
:app:mainApkListPersistenceDebug
:app:generateDebugResValues
:app:generateDebugResources
:app:mergeDebugResources
:app:createDebugCompatibleScreenManifests
:app:processDebugManifest
:app:splitsDiscoveryTaskDebug
:app:processDebugResources
:app:generateDebugSources
:app:javaPreCompileDebug
:app:compileDebugJavaWithJavac
:app:generateJsonModelDebug UP-TO-DATE
:app:externalNativeBuildDebug
Build luajit x86_64
Recompacting log...
[1/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
[2/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
[3/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
[4/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
[5/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
[6/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
[7/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
[8/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
[9/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
[10/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
[11/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
[12/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
[13/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
[14/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
[15/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
[16/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
[17/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
[18/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
[19/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
[20/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
[21/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
[22/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
[23/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
[24/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
[25/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
[26/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
[27/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
[28/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
[29/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
[30/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
[31/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
[32/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
[33/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
[34/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
[35/35] Linking C shared library ........buildintermediatescmakedebugobjx86_64libluajit.so
Build luajit x86
[1/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
[2/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
[3/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
[4/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
[5/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
[6/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
[7/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
[8/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
[9/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
[10/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
[11/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
[12/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
[13/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
[14/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
[15/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
[16/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
[17/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
[18/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
[19/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
[20/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
[21/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
[22/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
[23/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
[24/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
[25/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
[26/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
[27/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
[28/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
[29/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
[30/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
[31/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
[32/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
[33/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
[34/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
[35/35] Linking C shared library ........buildintermediatescmakedebugobjx86libluajit.so
Build luajit arm64-v8a
[1/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
[2/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
[3/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
[4/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
[5/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
[6/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
[7/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
[8/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
[9/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
[10/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
[11/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
[12/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
[13/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
[14/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
[15/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
[16/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
[17/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
[18/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
[19/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
[20/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
[21/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
[22/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
[23/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
[24/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
[25/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
[26/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
[27/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
[28/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
[29/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
[30/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
[31/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
[32/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
[33/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
[34/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
[35/35] Linking C shared library ........buildintermediatescmakedebugobjarm64-v8alibluajit.so
Build luajit armeabi-v7a
[1/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcorolib.c.o
[2/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbitlib.c.o
[3/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lapi.c.o
[4/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lauxlib.c.o
[5/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lbaselib.c.o
[6/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lcode.c.o
[7/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldo.c.o
[8/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/llex.c.o
[9/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldump.c.o
[10/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lobject.c.o
[11/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/liolib.c.o
[12/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmathlib.c.o
[13/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lmem.c.o
[14/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loadlib.c.o
[15/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldebug.c.o
[16/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lfunc.c.o
[17/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ldblib.c.o
[18/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lgc.c.o
[19/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/linit.c.o
[20/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lctype.c.o
[21/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lua.c.o
[22/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lopcodes.c.o
[23/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltm.c.o
[24/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/loslib.c.o
[25/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lundump.c.o
[26/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltable.c.o
[27/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstring.c.o
[28/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lutf8lib.c.o
[29/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lzio.c.o
[30/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstate.c.o
[31/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lvm.c.o
[32/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/ltablib.c.o
[33/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lstrlib.c.o
[34/35] Building C object CMakeFiles/luajit.dir/src/main/cpp/lparser.c.o
[35/35] Linking C shared library ........buildintermediatescmakedebugobjarmeabi-v7alibluajit.so
:app:compileDebugSources
:app:mergeDebugShaders
:app:compileDebugShaders
:app:generateDebugAssets
:app:mergeDebugAssets
:app:transformClassesWithDexBuilderForDebug
:app:transformDexArchiveWithExternalLibsDexMergerForDebug
:app:transformDexArchiveWithDexMergerForDebug
:app:mergeDebugJniLibFolders
:app:transformNativeLibsWithMergeJniLibsForDebug
:app:transformNativeLibsWithStripDebugSymbolForDebug
:app:processDebugJavaRes NO-SOURCE
:app:transformResourcesWithMergeJavaResForDebug
:app:validateSigningDebug
:app:packageDebug
:app:assembleDebug

BUILD SUCCESSFUL in 20s
33 actionable tasks: 30 executed, 3 up-to-date

再生成 APK,使用 7-ZIP 查看 APK,就可以看到我们 Lua 已经稳妥妥的在 APK 安装包中了,达到 340 KB了,对于 so 库来说也不小了。

未分类

至此,Lua 已经编译好了,如果需要使用,还需要写 JNI 方法调用,不过那是后话了。

Github 地址:https://github.com/yahch/Luandroid

Default storage engine (InnoDB) is not available的解决方法

自己用的MYSQL都是用MYISAM数据库,还没涉及到需要INNODB,因此打算直接不加载INNODB引擎。

在my.ini(linux下/etc/my.cnf)加上skip-innodb,就可以了。

我这样设置后,在linux下都没问题,今天在我本机winXP启动MYSQL,提示启动不起来。看下mysql目录的错误日志:

090613 10:15:27 [ERROR] Default storage engine (InnoDB) is not available

090613 10:15:27 [ERROR] Aborting

090613 10:15:27 [Note] C:wwwmysqlbinmysqld-nt: Shutdown complete

估计是上次加了参数后,一直没启动起来。。。已经很久没用本机的mysql了。

查了下,原来my.ini里有一句:default-storage-engine=INNODB,把默认的engine设为INNODB,而我又加了skip-innodb,怪不得启不来了。

将default-storage-engine改为MYISAM,MYSQL启动OK!
在skip-innodb下,data目录下的ibdata1,ib_logfile0,ib_logfile1这三个文件就不需要了,就可以删除。

测试了下,在没加skip-innodb时,删除了这三个文件,启动时会自动创建这三个文件,日志如下:

InnoDB: The first specified data file .ibdata1 did not exist:
InnoDB: a new database to be created!
090613 10:19:37 InnoDB: Setting file .ibdata1 size to 10 MB
InnoDB: Database physically writes the file full: wait...
090613 10:19:37 InnoDB: Log file .ib_logfile0 did not exist: new to be created
InnoDB: Setting log file .ib_logfile0 size to 24 MB
InnoDB: Database physically writes the file full: wait...
090613 10:19:38 InnoDB: Log file .ib_logfile1 did not exist: new to be created
InnoDB: Setting log file .ib_logfile1 size to 24 MB
InnoDB: Database physically writes the file full: wait...
InnoDB: Doublewrite buffer not found: creating new
InnoDB: Doublewrite buffer created
InnoDB: Creating foreign key constraint system tables
InnoDB: Foreign key constraint system tables created
090613 10:19:39 InnoDB: Started; log sequence number 0 0
090613 10:19:39 [Note] C:wwwmysqlbinmysqld-nt: ready for connections.

再删除这三个文件,加了skip-innodb后,启动日志:

090613 10:30:12 [Note] C:wwwmysqlbinmysqld-nt: Normal shutdown

090613 10:30:12 [Note] C:wwwmysqlbinmysqld-nt: Shutdown complete

090613 10:30:17 [Note] C:wwwmysqlbinmysqld-nt: ready for connections.

Version: '5.0.45' socket: '' port: 3306 Source distribution

那三个文件就不会自动产生了。

InnoDB的ib_logfile写入策略

ib_logfile是InnoDB的事务日志文件。本文简要说明其写入时机、写入策略及如何保证数据安全。

一、基本概念

  1. redo是物理日志,记录的是页的物理修改操作,是幂等的。
  2. ib_logfile文件个数由innodb_log_files_in_group配置决定,若为2,则在datadir目录下有两个文件,命令从0开始,分别为ib_logfile0和ib_logfile.
  3. 文件为顺序写入,当达到最后一个文件末尾时,会从第一个文件开始顺序复用。
  4. lsn: Log Sequence Number,是一个递增的整数。 Ib_logfile中的每次写入操作都包含至少1个log,每个log都带有一个lsn。在内存page修复过程中,只有大于page_lsn的log才会被使用。
  5. lsn的保存在全局内存结构log_sys中。递增数值等于每个log的实际内容长度。即如果新增的一个log长度是len,则log_sys->lsn += len.
  6. ib_logfile每次写入以512(OS_FILE_LOG_BLOCK_SIZE)字节为单位。实际写入函数 log_group_write_buf(log/log0log.c)
  7. 每次写盘后是否flush,由参数innodb_flush_log_at_trx_commit控制。

二、log_sys介绍

log_sys是一个全局内存结构。以下说明几个成员的意义。

未分类

三、相关更新

用一个简单的更新语句来说明log_sys以及ib_logfile的更新内容的过程。假设我们的更新只涉及到非索引的固定长度字段。

  1. 在bufferpool中写入undo log。 对于一个单一的语句,需要先创建一个undolog头。
  2. 在bufferpool中写入undo log的实际内容。
  3. 在log_sys->buf中写入buffer page的更新内容。此处保存了更新的完整信息。
  4. 在log_sys->buf中写入启动事务(trx_prepare)的日志。
  5. 将c、d更新的log内容写入ib_logfile中。
  6. 在log_sys->buf中写入事务结束(trx_commit)的日志。
  7. 将f步骤的log内容写入ib_logfile中。

四、说明

完成上述所有操作时,数据文件还没有更新。

  1. 每次写入log_sys->buf时同时更新lsn和buf_free。 每次写ib_logfile时同时更新written_to_all_lsn和buf_next_to_write;
  2. 每次写ib_logfile时以512字节为对齐,如需写入600字节,则实际写入1k。写到最后一个文件末尾则从第一个文件重复使用。
  3. 从上述流程看到,在a~d过程中若出现异常关闭,由于没有写入到磁盘中,因此整个事务放弃;若在e刚完成时出现异常关闭,虽然事务内容已经写盘,但没有提交。在重启恢复的时候,发现这个事务还没有提交,逻辑上整个事务放弃。 (重启日志中会有Found 1 prepared transaction(s) in InnoDB字样)。在g完成后出现异常关闭,则能够在重启恢复中正常提交。
  4. 在e和f之间会写mysql的bin-log,若bin-log写完前异常关闭,事务无效,bin-log写入成功后,则异常重启后能够根据bin-log恢复事务的修改。
  5. 若涉及到索引更新,在步骤c之后会增加索引更新的log。由于索引可能有merge过程,因此在merge过程中会另外增加写入一个log。但事务完全提交仍在步骤g中。索引的更新由于已经写盘,并不会因此丢失。

ubuntu+django+uwsgi+nginx前后端分离部署完整版

1.部署之前确定你已经将你的项目上传到你的服务器当中。在我之前的文章已经提到,本文默认项目已经运行成功,并且django项目中允许所有地址进行访问。下面也有我之前的部署,其实按照下面做到虚拟环境能够运行django就可以继续向下读了。

2. 将uwsgi安装到你的virtualenv中,初步设定项目名字为induapp,项目存放在/home/ubuntu/induapp

pip install uwsgi

基础测试(这也是uwsgi文档直接就有的)

创建一个test.py文件

# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3

运行uwsgi:

uwsgi --http :8000 --wsgi-file test.py

如果云主机能够直接外网访问的话

在浏览器访问 http://公网IP:8000即可,会提供一个“hello world”消息

如果云主机禁止外网访问

curl 127.0.0.1:8000

也能看到效果

这样意味下面的组建已经正常,不需要重复验证

web client <-> uWSGI <-> python

3.uwsgi测试运行django项目

uwsgi --http :8000 --module induapp.wsgi

module induapp.wsgi:加载指定的wsgi模块

跟上面相同的做法来验证是否能够访问到django项目,这样意味下面的组建已经正常,不需要重复验证

web client<->uWSGI<->Django

4.基本的nginx

安装nginx

sudo apt-get install nginx
sudo /etc/init.d/nginx start

同上我们能够在浏览器访问80端口或者curl访问80端口

如果会报错的话,这里建议两个比较快的命令

vim /var/log/nginx/error.log

或者

sudo nginx -t

如果正常运行,意味着

web client<->the web server

其实默认的80端口很容易会被占用,并且你想要在哪里使用nginx,那么你将必须重新配置nginx来提供另一个端口的服务,所以我们选择8080来当作后台的端口,8001来当作前台的端口。

4.为站点配置nginx

首先我们需要uwsgi_params文件,可用在uwsgi发行版本的nginx目录下,或者下面的连接就有,直接复制到induapp项目根目录中,不需要进行修改。

现在就可以在项目induapp根目录下面创建induapp_nginx.conf的文件,然后编写下面文件。

# mysite_nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8000; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      8080;
    # the domain name it will serve for
    server_name 127.0.0.1; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /home/ubuntu/induapp/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /home/ubuntu/induapp/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/ubuntu/induapp/uwsgi_params; # the uwsgi_params file you installed
    }
}

将这个文件链接到/etc/nginx/sites-enabled,这样nginx就可以看到它了:
sudo ln -s ~/induapp/induapp_nginx.conf /etc/nginx/sites-enabled/

5.基本nginx测试

sudo /etc/init.d/nginx restart

让nginx来测试test.py

我们可以查看端口号占用情况并杀掉进程

netstat -apn|grep 8000
kill -9 <pid>
uwsgi --socket :8000 --wsgi-file test.py

显然可以看出,已经配置了nginx在8000端口与uWSGI通信,而对外使用8080端口,访问8080端口来进行检查。

6.使用Unix socket而不是端口

使用Unix socket会比端口更好,开销更少。

编写induapp_nginx.conf,修改它来匹配:

upstream django {
    server unix:///home/ubuntu/induapp/induapp.sock; # for a file socket
    # server 127.0.0.1:8000; # for a web port socket (we'll use this first)
}

然后重启nginx

sudo /etc/init.d/nginx restart

再次运行uwsgi

uwsgi --socket mysite.sock --wsgi-file test.py

这次,socket会告诉uwsgi使用哪个文件

在浏览器或者curl尝试访问8080端口

如果那不行

检查nginx错误日志(/var/log/nginx/error.log)。如果你看到像这样的信息:

connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission denied)

那么可能你需要管理这个socket上的权限,从而允许nginx使用它。

尝试:

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 # (very permissive)

或者:

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)

你可能还必须添加你的用户到nginx的组 (可能是 www-data),反之亦然,这样,nginx可以正确地读取或写入你的socket。

值得保留nginx日志的输出在终端窗口中滚动,这样,在解决问题的时候,你就可以容易的参考它们了。

6.使用uwsgi和nginx运行django应用

运行我们的Django应用

uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664

现在,uWSGI和nginx应该不仅仅可以为一个”Hello World”模块服务,还可以为你的Django项目服务。

在induapp项目中配置induapp_uwsgi.ini文件

[uwsgi]
project = induapp
base = /home/ubuntu
socket = 127.0.0.1:8000

chdir = %(base)/%(project)
home = %(base)/anaconda3/envs/djangoEnv
module = %(project).wsgi

master = true
processes = 10

socket = %(base)/%(project)/%(project).sock
chmod-socket = 666
vacuum = true

pythonpath = /home/ubuntu/anaconda3/envs/djangoEnv/lib/python3.6/site-packages

值得注意的是要是没有最后一行的pythonpath很可能在初始化uwsgi应用的时候出现 no moudle named xxx的错误。

chdir是项目路径,home是虚拟环境路径。

使用这个文件运行

uwsgi --ini induapp_uwsgi.ini # the --ini option is used to specify a file

打印出来的结果能够预测Django站点是否预期工作

7.系统安装uwsgi

停用虚拟环境

source deactivate

然后在系统中安装uWSGI:

sudo pip install uwsgi

再次检查是否能运行

uwsgi --ini induapp_uwsgi.ini

Emperor模式

# 系统启动时运行uWSGI
# 最后一步是让这一切在系统启动的时候自动发生。
# 对于许多系统来说,最简单 (如果不是最好的)的方式是使用 rc.local 文件。
# 编辑 /etc/rc.local 然后在”exit 0”行前添加:
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid ubuntu --gid ubuntu --daemonize /var/log/uwsgi-emperor.log

选项表示:

  • emperor: 查找vassals (配置文件)的地方
  • uid: 进程一旦启动后的用户id
  • gid: 进程一旦启动后的组id

文档中的用户是www-data,

/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi-emperor.log

但常常因为权限不够高,访问时候会出现502的错误,所以我们这里直接使用Ubuntu来提高我们的权限。

7.完成前台的部署

将前台的静态文件打包到一个文件夹上传到服务器中,我们这里是/home/ubuntu/knowGraph

我们在项目根目录创建induapp_web_nginx.conf文件并进行编写。

server {
        listen       8001;
        server_name  127.0.0.1;

        location / {
            root /home/ubuntu/knowledgeGraph;
            index index.html;
        }
        location /neo4j {
            proxy_pass http://127.0.0.1:8080;
            proxy_send_timeout 1800;
            proxy_read_timeout 1800;
            proxy_connect_timeout 1800;
            client_max_body_size 2048m;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header  Host              $http_host;   # required for docker client's sake
            proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
            proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header  X-Forwarded-Proto $scheme;
        }
        location /admin {
            proxy_pass http://127.0.0.1:8080;
            proxy_send_timeout 1800;
            proxy_read_timeout 1800;
            proxy_connect_timeout 1800;
            client_max_body_size 2048m;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header  Host              $http_host;
            proxy_set_header  X-Real-IP         $remote_addr;
            proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header  X-Forwarded-Proto $scheme;

        }
}

下面就是对这个文件的解析

该文件监听的是8001端口,location / 对应的是前端静态文件的初始化界面。/neo4j和/admin对应的是django的url。基本上格式可以不做修改,我们值得注意的是proxy_pass http://127.0.0.1:8080(也就是刚刚我们后台运行在nginx的端口。)注意的是http://127.0.0.1:8080后面不应该带/号,不然访问127.0.0.1:8001/neo4就会变成访问127.0.0.1:8080,跟我们想要的结果不同。

将这个文件链接到/etc/nginx/sites-enabled,这样nginx就可以看到它了: sudo ln -s ~/induapp/induapp_web_nginx.conf /etc/nginx/sites-enabled/

最后的最后,重启服务

sudo /etc/init.d/nginx restart
uwsgi --ini induapp_uwsgi.ini -d /home/induapp/induapp.log

nginx+uwsgi启动Django项目

1.安装项目环境

  • 系统环境:ubuntu16.04
  • python环境:python3.5.2
  • Django版本:django1.11.7
  • nginx环境:nginx_1.10.3
  • 虚拟环境:virtualenv15.1.0
  • uwsgi版本:uwsgi2.0.17.1

安装并进入项目虚拟环境:

sudo apt-get install virtualenv
virtualenv -p python3 env_my_project 
source env_my_project/bin/activate
pip install -r requirements.txt 

2.项目配置及运行测试

修改项目配置文件:
cp my_project/settings_local.py.example my_project/settings_local.py

修改es配置文件:
cp rs_es/es_settings.py.example rs_es/es_settings.py

wsgi.py:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings_local")
application = get_wsgi_application()

项目运行测试:
python manage.py collectstatic  # 收集静态文件
python manage.py makemigrations
python manage.py migrate
python manage.py runserver 0.0.0.0:8001

未分类

3.NGINX和UWSGI相关配置

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/my_project
sudo ln -s /etc/nginx/sites-available/my_project /etc/nginx/sites-enabled/
sudo vim /etc/nginx/sites-enabled/my_project

nginx配置:
upstream my_project{
    server unix:///var/run/my_project.sock;
}

server {
    listen      8001;  //服务的端口号   服务通过nginx与uwsgi通信来启动

    server_name 192.168.xx.xx;  //nginx代理的ip  
    charset     utf-8;

    # max upload size
    client_max_body_size 10M;

    # send all non-media requests to the Django server.
    location / {
        uwsgi_pass  my_project;
        include     /etc/nginx/uwsgi_params;
    }

    location /static/ {
        root /home/ubuntu/my_project;
    }
}

Uwsgi配置:
sudo mkdir /var/log/uwsgi
sudo chmod -R 777 /var/log/uwsgi

uwsgi.ini:
[uwsgi]
chdir=/home/ubuntu/my_project
home=/home/ubuntu/my_project/env_my_project
module=my_project.wsgi:application

socket=/var/run/my_project.sock
chmod-socket = 666

master=True
processes = 5
max-requests=5000

# clear environment on exit
vacuum=True

pidfile=/var/run/my_project.pid
daemonize=/var/log/uwsgi/my_project.log

# git pull 自动重启服务
touch-reload=.git/index

4.配置Emperor mode监听和系统自动启动uwsgi

配置Emperor mode监听
sudo mkdir /etc/uwsgi
sudo mkdir /etc/uwsgi/vassals
sudo ln -s /home/ubuntu/my_project/uwsgi.ini /etc/uwsgi/vassals/

系统自动启动uwsgi
sudo vim /etc/rc.local
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals

5.通过uwsgi启动django服务

启动uwsgi
uwsgi --ini uwsgi.ini

重启nginx
sudo service nginx restart

启动django服务
sudo uwsgi --reload /var/run/my_project.pid

此时在浏览器通过ngnix代理出来的ip和端口即可访问服务

Django+uwsgi+nginx+angular.js项目

这次部署的前后端分离的项目:

前端采用angular.js,后端采用Django(restframework),他俩之间主要以json数据作为交互

Django+uwsgi的配置可以参考我之前的博客:http://www.cnblogs.com/52-qq/p/8873328.html

这篇博客里面都是静态页面,而不是采用restapi的形式,不过都是类似的,配置完之后采用uwsgi启动Django项目

前端:吧前端所有的代码拷贝在Django项目根路径下(也可以不用,当然我这么说是为了方便),

然后直接在nginx中配置,就可以了(不过前端框架也需要启动)

未分类

这段代码的配置才是比较重要的,类似的vue项目的部署也都类似

使用 Jenkins 执行持续集成的几个实用经验分享

众所周知,持续构建与发布是我们日常工作中要面对的的一个重要环节,目前很多公司都采用 Jenkins 来搭建符合需求的 CI/CD 流程,作为一个持续集成的开源工具,它以安装启动方便,配置简单,上手容易的特点,深受广大用户的欢迎,通过笔者这几年在公司使用 Jenkins 集群,来完成公司日常各项目组持续集成和发布流程的经验,给大家分享几个实用的经验。

1、 修改 JVM 的内存配置

Jenkins 启动方式有两种方式,一种是以 Jdk Jar 方式运行,一种是将 War 包放在 Tomcat 容器下运行。不管何种方式运行,都会存在一个问题就是,默认 JVM 内存分配太少,导致启动或者运行一段时间后内存溢出报错 java.lang.OutOfMemoryError: PermGen space。所以,需要在启动前修改 JVM 内存配置。以 Tomcat 容器方式启动 Jenkins 为例配置如下:

# 进入到 Jenkins 运行所在 Tomcat conf 目录
$ vim catalina.sh
# 在 #JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.security.SecurityListener.UMASK=`umask`" 行下增加修改配置 JVM 内存配置大小,例如下边配置:
JAVA_OPTS="$JAVA_OPTS -server -Xms512m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=512m"
12345

注意:这里的几个 JVM 参数含义如下:

  • -Xms: 使用的最小堆内存大小
  • -Xmx: 使用的最大堆内存大小
  • -XX:PermSize: 内存的永久保存区域大小
  • -XX:MaxPermSize: 最大内存的永久保存区域大小

这几个参数也不是配置越大越好,具体要根据所在机器实际内存和使用大小配置。

2、修改 Jenkins 主目录

Linux 下 Jenkins 默认安装目录为 /var/lib/jenkins/,这个目录磁盘空间有限,长时间使用会导致磁盘空间不够,建议修改为其他大磁盘空间目录。这里修改安装目录有两种方式,一种是配置为系统环境变量中,一种是配置到 Tomcat 容器环境变量中。

配置 JENKINS_HOME 到系统环境变量里面

# 注意:如果一台机器只安装一个 Jenkins 时,可以配置如下。
$vim /etc/profile
...
export JENKINS_HOME=/data0/jenkins
export PATH=$PATH:$JENKINS_HOME
# 使配置生效
$ source /etc/profile1234567

配置 JENKINS_HOME 到该 Jenkins 启动的 Tomcat 容器环境变量中

# 注意:如果一台机器上边安装多个 Jenkins 时,不能配置 JENKINS_HOME 到系统环境变量里面,
# 需要配置 JENKINS_HOME 到该 Jenkins 启动的 Tomcat 容器配置里面,这样可以区分不同的 Jenkins 目录。
$ vim /data0/scm/apache-tomcat-7.0.85/conf/context.xml
<Context>
    ...
    # 增加以下配置,优先获取该配置路径。
    <Environment name="JENKINS_HOME" value="/data0/jenkins" type="java.lang.String"/>
</Context>12345678

这里要说明一下,如果一台机器上只安装了一个 Jenkins 服务时,可以配置 JENKINS_HOME 到系统环境变量里面,如果安装了多个 Jenkins 服务时,不能这么配置,因为 Jenkins 会读取系统环境变量中 JENKINS_HOME 作为主目录安装,那样会存在配置覆盖的问题。此时应该采用第二种方式,各自配置 JENKINS_HOME 到自己启动的 Tomcat 容器环境变量中,Jenkins 会优先读取该容器环境变量作为各自的主目录安装。

附 Jenkins 寻找 JENKINS_HOME 环境变量的顺序为:首先读取容器环境变量,如果没有,则读取系统环境变量,如果还没有,则使用默认路径安装。

3、配置优化减少磁盘空间占用

Jenkins 运行 Job 构建比较多时,如果没有配置好清理策略的话,会导致占用磁盘空间比较大,最终由于磁盘空间不够导致构建失败的问题。

3.1 丢弃旧的构建配置

我们可以在 Job 中配置丢弃旧的构建,通过设置 “保持构建的天数” 和 “保持构建的最大个数” 两个参数,控制该 Job 最大保存构建数量。

未分类

未分类

如上图所示,我配置了最大保持 3 天之内的构建,如果超过 3 天的构建,则会在Job 执行前被清理掉。同时配置了最大保持构建数量为 10 个,意思就是如果 3 天内构建次数如果超过 10 次,则最多保留最近执行的 10 个构建。这样配置的好处,除了能够自动清理一些 Build 之外,还能够为我们代码执行远程停止 Job Build 时,缩短停止时间,下边会讲到。

3.2 修改工作空间和构建记录根目录

Jenkins 工作主要分为安装主目录,工作空间目录以及构建记录目录,默认配置路径如下图所示:

未分类

如果我们修改了 Jenkins 安装主目录之后,因为工作空间目录是在安装主目录下的 workspace 目录,构建目录在安装主目录下的 builds 目录,这样运行 Job 执行构建比较多时,还会存在磁盘空间不够的问题,那么此时可以在 “系统管理” —> “系统配置” —> “高级” 分别修改工作空间根目录和构建记录根目录,指向其他磁盘空间即可。

4、设置全局属性

适当设置全局属性,可以避免在 Job 中重复写一些固定值,例如输出日志地址、接口请求地址等等,而且当固定值需要修改时,只需要修改一次即可,不用去每个 Job 里面修改,方便维护。我们可以去 “系统管理” —> “系统配置” —> “全局属性” 下增加 Environment variables 键值对,例如如下图:

未分类

那么,在 Job 构建时执行 “ Execute Shell” 使用时,可以直接应用即可,例如如下代码:

未分类

5、JDK/Maven/Gradle 等软件多版本安装

对于一些常用的软件,比如 Jdk、Maven、Gradle等,可能每个项目对软件依赖版本不一样,有的项目依赖 Jdk7,有的依赖 Jdk8,所以为了更好的适配各个项目,可以指定安装多个版本软件,然后 Job 创建时选择其中一个版本使用。这里以 Jdk 为例,去 “系统管理” —> “Global Tool Configuration” —> “JDK” 分别安装 jdk6、Jdk7、Jdk8。

未分类

然后,在创建 Job 时,选择项目需要的一个版本即可。

未分类

6、设置构建超时时间

有些 Job 在执行构建时,由于某些原因导致构建挂起,耗时比较长,而这些长时间挂起的 Job 会导致 Jenkins 内存占用比较大,性能下降,严重的会直接导致 Jenkins 挂掉。所以,我们需要设置构建超时时间来预防这种事情发生,一旦超过一定的时间,要让 Job 自动停止掉。例如,这里我设置构建超过 30 分钟则将本次 Build 置为失败。

未分类

7、配置视图分类管理 Job

Jenkins 默认视图为 ALL 显示所有 Job 列表,如果 Job 比较多的话,找某个 Job 会不太方便,虽然有 Search 搜索功能,毕竟还是不太方便。这时候,我们可以通过新建视图方式,对 Job 进行分门别类,这样管理和查找起来就方便多啦!例如这里我新建 “List View” 类型视图 “wy”,然后选择该视图所关联的 Job 就可以了。

未分类

这样通过视图切换,查找相关 Job 就方便多了。

未分类

8、配置多节点管理

一般我们会使用 Jenkins Slave 集群管理来完成日常持续集成操作,使用 Jenkins Slave 一主多从方式,可以将 Job 调度到对应的 Slave 机器上执行,能够大大提高系统并发执行效率。我们可以从 “系统管理” —> “管理节点” —> “新建节点”,设置节点类型为 “Permanent Agent” 名称 “wy_slave0” 的一个从节点,当然有多个节点时,可以创建多个。创建完毕之后,此时插件还属于不可用状态,因为还没有执行关联,具体关联方式可以参照 Jenkins 上节点关联说明(如下图,这里忽略操作),关联完毕之后,我们就可以在新建 Job 中配置指定那个 Slave 节点运行了。

未分类

未分类

未分类

这里,有两种方式指定 Job 在那个 Slave 节点运行,一种是对于自由风格类型的 Job,我们可以通过在 “Restrict where this project can be run” 选项下指定 “Label Expression” 标签指定节点标签即可。

未分类

另一种是对于多配置项目类型的 Job,我们可以通过在 “Configuration Matrix” 先配置 “Slave” 选择 Node/Label 勾选指定一个或多个 Slave 执行。

未分类

9、一些实用插件

Jenkins 的基础配置就能够满足我们日常的基本工作,但是为了提高构建效率和方便维护,Jenkins 上提供了很多实用的插件,使用这些插件,我们可以更加轻松、更加简便、更加高效的执行持续集成和发布流程。下边,我就简单介绍几个我使用的插件。

9.1 Managed Script 插件管理脚本文件

该插件是为了在管理文件时创建 Script 脚本文件,然后在 Job 中配置直接使用,方便脚本的统一管理和维护。首先我们需要去 “系统管理” —> “管理插件” —> “可选插件” 中选择 “Managed script” 插件,安装重启即可。

未分类

安装完毕后,可以从 “系统管理” —> “Managed files” —> “Add a new Config” 选择 “Managed script file” 类型,创建一个新的 shell 脚本文件,然后输入我们要执行的脚本代码。这里我创建了两个脚本,分别为 before-build-step-shell 和 after-build-step-shell,意思很明确了,前者在构建前执行的一些操作,后者在构建后执行的一些操作。

未分类

未分类

注意: 这里的脚本可以使用一些 Jenkins 系统的环境变量参数、参数化构建时传递的参数以及系统命令哦。

创建完毕后,我们在 Job 中构建处选择 “Execute managed script” 就可以使用这些脚本了。

未分类

9.2 PostBuildScript 插件根据 Build 状态执行脚本

推荐安装 PostBuildScript 插件,该插件可以在构建后操作中,根据构建结果状态,执行对应的脚本操作,很实用的一个插件。同上安装该插件,重启 Jenkins 完毕插件生效后,Job 中构建后操作处选择 “Execute Scripts” ,然后在 “Add build step” 中选择 “Execute shell” 等选项(当然也可以配合上一个插件,那么这里就选择 “Execute managed script”),下边选择一个 build 状态条件值,如果选择 SUCCESS 状态,那么该脚本只有在 Build 成功时才会执行,其他状态依次类推,状态可以多选哦,多选代表多种状态都能下触发。

未分类

9.3 Jenkins2.0 Pipeline 插件执行持续集成发布流程

Jenkins 2.0 的精髓是 Pipeline as Code,是帮助 Jenkins 实现 CI 到 CD 转变的重要角色。Pipeline是一套运行于 Jenkins 上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程。Pipeline 中任何发布流程都可以表述为一段 Groovy 脚本,并且 Jenkins 支持从代码库直接读取脚本。使用 Pipeline 执行持续集成发布流程好处是显而易见的,它可以把以前需要多个节点上多个 Job 使用一段脚本来替代,而且脚本语言功能强大,可以很好的完成一些复杂的流程操作,推荐大家尝试使用。这里就不多说了,详细可以参考之前文章 初试Jenkins2.0 Pipeline持续集成。

9.4 Kubernetes Plugin 插件动态创建 Jenkins Slave

我们知道传统的 Jenkins Slave 一主多从方式会存在一些痛点,比如 Master 单点故障,Slave 配置环境差异,资源分配不均衡等导致可靠性和可维护性比较差,而使用 Kubernetes Plugin 插件可以动态的创建和删除 Jenkins Slave 节点,使用它可以很好的保证服务高可用,动态伸缩合理使用资源,以及良好的扩展性。使用该插件后,它的工作流程大致为:当 Jenkins Master 接受到 Build 请求时,会根据配置的 Label 动态创建一个运行在 Docker Container 中的 Jenkins Slave 并注册到 Master 上,当运行完 Job 后,这个 Slave 会被注销并且 Docker Container 也会自动删除,恢复到最初状态。这里也不多说了,详细可以参考之前文章 初试 Jenkins 使用 Kubernetes Plugin 完成持续构建与发布。

10、JAVA 代码触发 Jenkins Job 创建、删除、停止等操作。

Jenkins Job 创建、删除、构建等操作,除了在页面手动操作外,我们还可以通过 Jenkins API 接口执行对应操作,详细接口可参考 Jenkins
REST API 文档地址:http:///api。这里我要演示的是使用 Jenkins-client.jar 包,使用 JAVA 代码操作如何创建、删除、停止、触发构建等,使用代码触发 jenkins 相关操作,好处就是自己可控,这样可以配合自己的业务需要,随时启动或者新建 Job 啦。

public class JenkinsUtils {

    private static String jenkins_url = "http://127.0.0.1/jenkins/";
    private static String jenkins_user = "admin";
    private static String jenkins_token = "1b356d175432ed0d34c440d68d00fe49";

    /**
     * 通过模板创建 Job
     * @param jobName
     * @param jobTemplate
     * @return
     */
    public static boolean createJobFromTemplate(String jobName, String jobTemplate) {
        try {
            URI uri = new URI(jenkins_url);            
            JenkinsServer jenkins = new JenkinsServer(uri, jenkins_user, jenkins_token);
            String template = jenkins.getJobXml(jobTemplate);
            Document doc = DocumentHelper.parseText(template);
            String newConfigXml = doc.asXML();
            jenkins.createJob(jobName, newConfigXml, false);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 删除/禁用 Job
     * @param jobName
     * @return
     */
    public static boolean deleteJob(String jobName){
        try {
            URI uri = new URI(jenkins_url);            
            JenkinsServer jenkins = new JenkinsServer(uri, jenkins_user, jenkins_token);
            jenkins.deleteJob(jobName, false);
            jenkins.disableJob(jobName, false);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 启动 Job 构建
     * @param jobName
     * @param params
     * @return
     */
    public static boolean startJob(String jobName, String params){
        try {
            String buildUrl = jenkins_url + jobName + "/buildWithParameters?" + params;
            HttpUtils.HttpGet(buildUrl);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 停止正在构建中的 Job,先清除等待队列中的 build,在停止运行中的 build
     * @param jobName
     * @return
     */
    public static boolean stopJob(String jobName){
        try {
            URI uri = new URI(jenkins_url);
            JenkinsServer jenkins = new JenkinsServer(uri, jenkins_user, jenkins_token);
            // 先 kill 掉 queue 里面的 build
            QueueItem qi = jenkins.getJob(jobName).getQueueItem();
            if(qi != null){
                HttpUtils.HttpPost(jenkinsUrl + "queue/cancelItem?id=" + qi.getId());
            }
            // 在 kill 掉正在运行中的 build
            List<Build> bulidsList = jenkins.getJob(jobName).getAllBuilds();
            for(Build b:bulidsList){
                if(b.details().isBuilding()){
                    try{
                        b.Stop();
                    }catch(Exception ee){
                        ee.printStackTrace();
                        return false;
                    }
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

这里有一个地方要注意,在停止构建中的 Job 时,这里是遍历所有 Build,然后在 Kill 掉运行中的 Build,如果 Build 历史比较多的时候,会耗时比较久,这将会导致立马重新执行该 Job Build 时, Build 会被异常 Abort 掉。。。 也尝试过获取最后一次 Build 执行 Stop 操作,好像也不太好使。所以这里大家可以通过上边 3.1、丢弃旧的构建配置 中的操作,减少构建历史记录,这样就可以很快执行完毕,就不会出现上述问题了。