2013-11-15 5 views
5

मैं 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' 

मैं वैश्विक कार्यों और चर को कैसे परिभाषित कर सकता हूं? फ़ाइल scripting.c में स्रोत कोड को

+0

lua स्क्रिप्ट जोड़ने जब तक कि आप उत्तर नहीं चाहते हैं: वैश्विक चर परिभाषित न करें: पी –

+0

@ टॉमसो को भ्रम के लिए खेद है, लेकिन सवाल वैश्विक चर के बारे में है। – Alex

उत्तर

8

खोज रहे हैं

/* 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 के डॉक-स्ट्रिंग इंगित करता है कि इरादे (local का उपयोग नहीं) आम गलती की पटकथा लेखकों को सूचित करने के लिए है।

यह इस तरह दिखता है सुरक्षा सुविधा नहीं है, इसलिए हम दो समाधान है:

एक यह सुरक्षा हटा सकते हैं:

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) 
+0

मुझे प्यार है कि आपको ऐसा करने का कोई तरीका मिला है। जीत के लिए हैकर भावना! मैं यह सुझाव देने जा रहा हूं कि लोग इस विधि का उपयोग नहीं करते हैं, हालांकि। यह रेडिस डॉक्स से स्पष्ट लगता है कि स्क्रिप्ट को सर्वर पर नहीं रहने के लिए सर्वर प्रबंधन को सरल बनाना है (यह एसएचए आधारित कैशिंग के साथ कुशलता से किया जाता है)। वैश्विक दायरे में कार्य को इंजेक्ट करने से इस इरादे को कम किया जाता है। हालांकि, अद्भुत हैकिंग, एलेक्स। –

+0

एक सामान्य कोड स्टोर करने के लिए वैश्विक दायरे का उपयोग करेगा। वैकल्पिक है कि स्क्रिप्ट को भेजी गई एक स्क्रिप्ट पर सभी स्क्रिप्ट को संकलित करने के लिए टेम्पलेटिंग इंजन का उपयोग करना है। मैं पूर्व पसंद करता हूं - रेडिस-क्लाइंट से कनेक्ट करना और अपनी सभी उपयोगिताओं का उपयोग करना आसान है। ध्यान दें कि अभ्यास में रेडिस ऑपरेशन कभी भी सरल या स्पष्ट नहीं होते हैं। – Alex

+1

'ईवाल' पर रेडिस डॉक्स से: "यदि उपयोगकर्ता लुआ ग्लोबल स्टेटस के साथ गड़बड़ करता है, तो एओएफ और प्रतिकृति की स्थिरता की गारंटी नहीं है: ऐसा न करें।" –

संबंधित मुद्दे