복붙노트

[REDIS] 스크립트 전역 변수를 작성하려고

REDIS

스크립트 전역 변수를 작성하려고

나는 실행 미래 스크립트에 따라 달라집니다 기능을 보냅니다 레디 스에 하나의 스크립트를로드하지만, 전역 함수가 실패 같은 전역 변수에 간다 정의하려고 시도하고 싶습니다 :

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'

어떻게 전역 함수 및 변수를 정의 할 수 있습니까?

해결법

  1. ==============================

    1.파일 scripting.c의 소스 코드를 보면

    파일 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);
    }
    

    scriptingEnableGlobalsProtection의 문서-string은 의도 (로컬 사용하지 않는) 일반적인 실수의 스크립트 저자를 통지 할 것을 나타냅니다.

    이 보안 기능이없는 것 같습니다, 그래서 우리는 두 가지 솔루션이 있습니다

    하나는이 보호를 제거 할 수 있습니다 :

    local mt = setmetatable(_G, nil)
    -- define global functions / variables
    function alex() return 3.1415 end
    -- return globals protection mechanizm
    setmetatable(_G, mt)
    

    또는 사용 rawset :

    local function alex() return 3.1415 end
    rawset(_G, "alex", alex)
    
  2. from https://stackoverflow.com/questions/19997647/script-attempted-to-create-global-variable by cc-by-sa and MIT license