问题描述
我想将一个脚本加载到redis中,该脚本将导出未来脚本执行所依赖的函数,但尝试定义全局函数失败,全局变量也一样:
redis 127.0.0.1:6379> EVAL函数alex()返回3.1415结束0
(error)ERR运行脚本错误(调用f_f24a5a054d91ccc74c2629e113f8f639bbedbfa2):user_script:1:脚本尝试创建全局变量'alex'
$ c $如何定义全局函数和变量?解决方案
我想将一个脚本加载到redis中,该脚本将导出未来脚本执行所依赖的函数,但尝试定义全局函数失败,全局变量也一样:
redis 127.0.0.1:6379> EVAL函数alex()返回3.1415结束0
(error)ERR运行脚本错误(调用f_f24a5a054d91ccc74c2629e113f8f639bbedbfa2):user_script:1:脚本尝试创建全局变量'alex'
$ c $如何定义全局函数和变量?解决方案
>
/ *此函数在全局表_G中安装metamethods,防止
*意外创建全局变量。
*
*它应该是在脚本引擎初始化
*序列中调用的最后一个,因为它可能与创建全局变量相互作用。 * /
void scriptingEnableGlobalsProtection(lua_State * lua){
char * s [32];
sds code = sdsempty();
int j = 0;
/ * strict.lua来自:http://metalua.luaforge.net/src/lib/strict.lua.html。
*修改为适应Redis。 * /
s [j ++] =local mt = {} \\\
;
s [j ++] =setmetatable(_G,mt)\\\
;
s [j ++] =mt .__ newindex = function(t,n,v)\\\
;
s [j ++] =if debug.getinfo(2)then \\\
;
s [j ++] =local w = debug.getinfo(2,\S\)。what'\
;
s [j ++] =if w〜= \main \and w〜= \C \then \\\
;
s [j ++] =error(\脚本试图创建全局变量'\.. tostring(n).. \'\,2)\\\
;
s [j ++] =end \ n;
s [j ++] =end \ n;
s [j ++] =rawset(t,n,v)\\\
;
s [j ++] =end \ n;
s [j ++] =mt .__ index = function(t,n)\\\
;
s [j ++] =if debug.getinfo(2)and debug.getinfo(2,\S\)。
s [j ++] =error(\脚本试图访问未知的全局变量'\.. tostring(n).. \'\,2)\\\
;
s [j ++] =end \ n;
s [j ++] =return rawget(t,n)\\\
;
s [j ++] =end \ n;
s [j ++] = NULL; (j = 0; s [j]!= NULL; j ++)code = sdscatlen(code,s [j],strlen(s [j]));
luaL_loadbuffer(lua,code,sdslen(code),@ enable_strict_lua);
lua_pcall(lua,0,0,0);
sdsfree(code);
scriptingEnableGlobalsProtection的doc-string
表示意图是通知脚本作者常见的错误(不使用 local
)。
看起来这不是安全功能,所以我们有两个解决方案:
:
local mt = setmetatable(_G,nil)
- 定义全局函数/变量
函数alex()返回3.1415结束
- 返回全局保护mechanizm
setmetatable(_G,mt)
或使用 rawset
:
local function alex( )return 3.1415 end
rawset(_G,alex,alex)
I would like to load one script into redis that will export functions that future scripts executed will depend on, but attempt to define global function fails, same goes for global variables:
redis 127.0.0.1:6379> EVAL "function alex() return 3.1415 end" 0
(error) ERR Error running script (call to f_f24a5a054d91ccc74c2629e113f8f639bbedbfa2): user_script:1: Script attempted to create global variable 'alex'
How can I define global functions and variables ?
Looking at the source code in file scripting.c
/* This function installs metamethods in the global table _G that prevent
* the creation of globals accidentally.
*
* It should be the last to be called in the scripting engine initialization
* sequence, because it may interact with creation of globals. */
void scriptingEnableGlobalsProtection(lua_State *lua) {
char *s[32];
sds code = sdsempty();
int j = 0;
/* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.
* Modified to be adapted to Redis. */
s[j++]="local mt = {}\n";
s[j++]="setmetatable(_G, mt)\n";
s[j++]="mt.__newindex = function (t, n, v)\n";
s[j++]=" if debug.getinfo(2) then\n";
s[j++]=" local w = debug.getinfo(2, \"S\").what\n";
s[j++]=" if w ~= \"main\" and w ~= \"C\" then\n";
s[j++]=" error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n";
s[j++]=" end\n";
s[j++]=" end\n";
s[j++]=" rawset(t, n, v)\n";
s[j++]="end\n";
s[j++]="mt.__index = function (t, n)\n";
s[j++]=" if debug.getinfo(2) and debug.getinfo(2, \"S\").what ~= \"C\" then\n";
s[j++]=" error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n";
s[j++]=" end\n";
s[j++]=" return rawget(t, n)\n";
s[j++]="end\n";
s[j++]=NULL;
for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));
luaL_loadbuffer(lua,code,sdslen(code),"@enable_strict_lua");
lua_pcall(lua,0,0,0);
sdsfree(code);
}
The doc-string of scriptingEnableGlobalsProtection
indicates that intent is to notify script authors of common mistake (not using local
).
It looks like this is not security feature, so we have two solutions:
One can remove this protection:
local mt = setmetatable(_G, nil)
-- define global functions / variables
function alex() return 3.1415 end
-- return globals protection mechanizm
setmetatable(_G, mt)
Or use rawset
:
local function alex() return 3.1415 end
rawset(_G, "alex", alex)
这篇关于脚本试图创建全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!