2013-11-15 23 views
5

küresel değişken oluşturmak için çalıştı, aynı küresel değişkenler için de geçerli:Senaryo Gelecek komut bağlıdır yürütülen işlevleri ihraç edecek REDIS içine bir komut dosyası yüklemek, ancak başarısız küresel işlevini tanımlamak girişimi istiyoruz

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' 

Genel işlevleri ve değişkenleri nasıl tanımlarım?

+0

lua komut dosyasını ekleyin gibi cevaplar istemiyorsanız: global değişkenleri tanımlama: P –

+0

@ Tommaso karışıklık için özür dilerim, ama soru global değişkenlerle ilgilidir. – Alex

cevap

8

dosya scripting.c kaynak kodu baktığımızda

/* 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 ait doc-string niyet (local kullanarak değil) ortak hata senaryo yazarları bilgilendirmek için olduğunu gösterir. Bu şuna benzer

güvenlik özelliği değildir, bu yüzden iki çözüm vardır:

biri bu korumayı kaldırabilirsiniz:

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

Veya kullanmak rawset:

local function alex() return 3.1415 end 
rawset(_G, "alex", alex) 
+0

Bunu yapmanın bir yolunu bulduğunuzu seviyorum. Kazanmak için hacker ruhu! Yine de, insanların bu yöntemi kullanmamalarını önereceğim. Redis belgelerinden, sunucuda yer almayan komut dosyalarını zorlayarak sunucu yönetimini basitleştirmek olduğu açık görünüyor (bu, SHA tabanlı önbellekleme ile etkin bir şekilde yapılır). İşlevleri global kapsam içine enjekte etmek bu amacı altüst eder. Harika hack olsa, Alex. –

+0

Ortak kod depolamak için genel kapsam kullanılır. Alternatif, tüm komut dosyalarını Redis'e gönderilen bir betiğe derlemek için şablon oluşturan motoru kullanmaktır. Ben eski tercih ederim - redis-client ile bağlanmak ve tüm yardımcı programlarını kullanmak daha kolaydır. Uygulamadaki Redis işlemlerinin asla basit veya açık olmadığını unutmayın. – Alex

+1

"EVAL" üzerindeki Redis belgelerinden: "Kullanıcı Lua genel durumuyla uğraşırsa, AOF ve çoğaltmanın tutarlılığı garanti edilmez: bunu yapma." –

İlgili konular