最進項目中使用到了socketproc通信,但是這樣有一點不是很好,必須單獨啟動一個進程來執行代碼中的shell命令,后面想在nginx+lua的環境下使用openresty中的lua-resty-shell,但是在后續閱讀源碼說明的時候發現依賴關系過於復雜,會導致引入的openresty模塊越來越堵。但是發現歸根結底是對ffi庫的調用,什么是ffi庫?
說白一點:ffi動態庫就是lua語言調用底層C語言的一系列接口,而ffi動態庫日空了非常方便的編碼風格,來使用完成自己的功能。來看一下如何使用ffi庫。
首先下載源碼到自己的環境中進行編譯。需要注意的是這個插件根據環境的不同生成的動態庫不能相互使用的,樓主在過程中就煩了這個錯誤,將ubuntu環境下的動態庫移動到centOS下使用失敗。
首先make 會發現有兩個找不到的,這時候就需要你手動更改Makefile中的PKG_CONFIG_PATH和lua的路徑,改正之后make 成功,就會看到生成了ffi.so
然后將動態庫拷貝到nginx的conf同一級目錄下的lualib路徑下,再將此路徑添加到lua的cpath中,就可以使用了,就像下面一樣:
package.cpath= "/usr/local/nginx-1.16.0/lualib/?.so;;"..package.cpath local ffi = require("ffi") local ffiShell = ffi.load("shellTest") ffi.cdef[[ struct dummy{}; double sqrt(double x); int gethostname(char *name,size_t len); char* Run(const char* cmd); ]] local dat = ffiShell.Run('ls -al /tmp') ngx.print(ffi.string(dat)) local int_t = ffi.typeof("int") local char_arr_t = ffi.typeof("char[?]") local a_int = ffi.new(int_t) local char_arr=char_arr_t(10) local x = ffi.C.sqrt(5) ngx.print(x) ffi.fill(char_arr,10) ffi.C.gethostname(char_arr,10) --ngx.print(char_arr) ngx.print(ffi.string(char_arr)) --ngx.print(char_arr[0]) ngx.say(" call ffi.so!") --ngx.say(ffiShell.Run("ls -al ")) --ffi.C.system("ls -al /usr/local")
shellTest是樓主自己使用C語言中的popen函數寫的一個調用shell命令接口的動態鏈接庫
#include "shellTest.h" char* Run(const char* shellCmd){ /* int ret = system(shellCmd); if(ret < 0){ char errInfo[128]; sprintf(errInfo,"system call shellCmd error,ret:%d",ret); return errInfo; }else if(ret == 0){ return "system fork failed"; }else{ return "shellCmd call successful!"; } */ char buf[1024]; FILE *fp=popen(shellCmd,"r"); fgets(buf,sizeof(buf),fp); //fscanf(fp,"%s",buf); //printf("%s",buf); pclose(fp); return buf; }
頭文件
#ifndef __SHELLCMD_H #define __SHELLCMD_H #include <stdio.h> #include <stdlib.h> char* Run(const char* shellCmd); #endif
可能貼出來的代碼有問題,需要大家在使用的時候進行簡單的修改