Symfoware

Symfowareについての考察blog

lftp 隠しファイル(ドットから始まるファイル)もmirrorする

lftpでmirrorアップロードするとき、Linuxの隠しファイル(ドットから始まるファイル)が
どうも確認対象から漏れ、毎回アップロードの対象になってしまう模様。

変更がないのにログとして出力されるのがイヤなので、
同期対象に含める方法を調べてみました。

そのものズバリの記事が...

lftpでドットから始まるファイルを対象にする


set ftp:list-options -a



このオプションを指定することで、「.htaccess」や「.gitignore」も同期されるようになりました。

テーマ:サーバ - ジャンル:コンピュータ

  1. 2016/05/17(火) 21:39:12|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

nginx + luaで簡易ファイルストレージ

画像ファイル等を、別サーバーへ受け渡すため一時的に保存するツールが欲しい。
良い案を模索中です。


nginx + luaによる実装



とりあえず、nginxのluaモジュールで簡単なファイルストレージを作ってみました。


nginx.confに、ファイルの保存先とluaプログラムのパスを指定。
合わせて、アップロードサイズの上限「client_max_body_size」を増やしておきます。


    client_max_body_size 4G;
    
    server {

        location /strage {
                set $path '/var/www/data/';
                content_by_lua_file /var/www/strage.lua;
        }





luaプログラム。

・strage.lua


  1. local do_get = function(filepath)
  2.     local file = io.open(filepath, 'rb')
  3.     ngx.print(file:read('*a'))
  4.     file.close()
  5. end
  6. local do_post = function(filepath)
  7.     -- body_dataを取得してみる
  8.     local req_body = ngx.req.get_body_data()
  9.     
  10.     -- 取得できたら、req_body自身が保存すべき内容
  11.     if req_body then
  12.         local f = io.open(filepath, "wb")
  13.         f:write(req_body)
  14.         f:close()
  15.         
  16.         ngx.say('saved')
  17.         return
  18.     end
  19.     
  20.     -- もし取得できていなかったら、データはファイルに行っている
  21.     -- テンポラリのファイル名を取得
  22.     local req_body_file_name = ngx.req.get_body_file()
  23.     os.rename(req_body_file_name, filepath)
  24.     ngx.say('moved')
  25. end
  26. local do_delete = function(filepath)
  27.     os.remove(filepath)
  28. end
  29. local strage_path = ngx.var.path
  30. if strage_path == "" or string.sub(strage_path, -1) ~= "/" then
  31.     strage_path = strage_path .. '/'
  32. end
  33. -- bodyの解析
  34. ngx.req.read_body()
  35. -- ヘッダーから保存するときのファイル名を取得
  36. local filename = ngx.req.get_headers()["filename"]
  37. -- ファイルの保存先
  38. local filepath = strage_path .. filename
  39. local method = ngx.req.get_method()
  40. if method == 'GET' then
  41.     do_get(filepath)
  42.     
  43. elseif method == 'POST' then
  44.     do_post(filepath)
  45.     
  46. elseif method == 'DELETE' then
  47.     do_delete(filepath)
  48.     
  49. end





Pythonのサンプル


  1. # -*- coding:utf-8 -*-
  2. import urllib2
  3. url = "http://192.168.1.103/strage"
  4. # --- ファイルのアップロード ---
  5. with open('cc2.jpg', 'rb') as f:
  6.     image = f.read()
  7. req = urllib2.Request(url, data=image)
  8. # ヘッダーに保存するファイル名を指定する
  9. req.add_header('filename', 'cc2.jpg')
  10. res = urllib2.urlopen(req)
  11. # --- ファイルのダウンロード ---
  12. req = urllib2.Request(url)
  13. req.add_header('filename', 'cc2.jpg')
  14. res = urllib2.urlopen(req)
  15. f = open('test.jpg', 'wb')
  16. f.write(res.read())
  17. f.close()
  18. # --- ファイルのダ削除 ---
  19. req = urllib2.Request(url)
  20. req.add_header('filename', 'cc2.jpg')
  21. req.get_method = lambda: 'DELETE'
  22. res = urllib2.urlopen(req)








MariaDB blobとの比較



同じサーバーにMariaDBをインストール。
longblobフィールドを持つテーブルを作成し、画像テンポラリとして使ってみます。


  1. CREATE TABLE imagetmp (
  2.     name varchar(50) primary key,
  3.     image longblob not null
  4. )




luaとどちらが速いかテスト。
14Mの画像を登録、復元、削除というオペレーションを100回繰り返し、必要な時間を計測してみます。

まず、今回作ったluaのファイルストレージ。


  1. # -*- coding:utf-8 -*-
  2. import urllib2
  3. import time
  4. url = "http://192.168.1.103/strage"
  5. # 登録用のデータを準備
  6. with open('04.jpg', 'rb') as f:
  7.     image = f.read()
  8. start = time.time()
  9. for i in xrange(100):
  10.     # --- ファイルのアップロード ---
  11.     req = urllib2.Request(url, data=image)
  12.     # ヘッダーに保存するファイル名を指定する
  13.     req.add_header('filename', '04.jpg')
  14.     res = urllib2.urlopen(req)
  15.     # --- ファイルのダウンロード ---
  16.     req = urllib2.Request(url)
  17.     req.add_header('filename', '04.jpg')
  18.     res = urllib2.urlopen(req)
  19.     f = open('test.jpg', 'wb')
  20.     f.write(res.read())
  21.     f.close()
  22.     # --- ファイルのダ削除 ---
  23.     req = urllib2.Request(url)
  24.     req.add_header('filename', '04.jpg')
  25.     req.get_method = lambda: 'DELETE'
  26.     res = urllib2.urlopen(req)
  27. elapsed_time = time.time() - start
  28. print ("elapsed_time:{0}".format(elapsed_time)) + "[sec]"




24.5秒ぐらい



続いて、MariaDBのテンポラリ


  1. # -*- coding:utf-8 -*-
  2. import MySQLdb
  3. import time
  4. con = MySQLdb.connect(
  5.     host='192.168.1.103',
  6.     user='admin',
  7.     db='sample',
  8.     passwd='P@ssw0rd',
  9.     charset='utf8')
  10. cur = con.cursor()
  11. # 登録用のデータを準備
  12. with open('cc2.jpg', 'rb') as f:
  13.     image = f.read()
  14. start = time.time()
  15. for i in xrange(100):
  16.     cur.execute("INSERT INTO imagetmp (name, image) VALUES ('04.jpg', %s)", [image,])
  17.     con.commit()
  18.     cur.execute("SELECT image FROM imagetmp where name = '04.jpg'")
  19.     row = cur.fetchone()
  20.     f = open('test.jpg', 'wb')
  21.     f.write(row[0])
  22.     f.close()
  23.     cur.execute("DELETE FROM imagetmp where name = '04.jpg'")
  24.     con.commit()
  25. elapsed_time = time.time() - start
  26. print ("elapsed_time:{0}".format(elapsed_time)) + "[sec]"
  27. cur.close()
  28. con.close()



8秒ぐらい


・・・遅すぎて使い物にならない。
良い案だと思ったけど、ちゃんとメモリにキャッシュするようにしないとダメか。

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2016/02/21(日) 18:06:36|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Alpine Linux nginx-luaをインストール

Alpine Linuxにnginxをインストールしようと検索してみると、


# apk search nginx
nginx-1.8.1-r0
collectd-nginx-5.5.0-r1
nginx-lua-1.8.0-r5
nginx-lua-doc-1.8.0-r5
nginx-vim-1.8.1-r0
nginx-initscripts-1.8.0-r0
nginx-doc-1.8.1-r0




nginx-luaって、ひょっとしてlua拡張同梱版では?
Debian 7 + nginx 1.6.2 + lua-nginx-moduleの環境構築

インストールしてみました。


# apk add nginx-lua
(1/4) Installing nginx-initscripts (1.8.0-r0)
Executing nginx-initscripts-1.8.0-r0.pre-install
(2/4) Installing luajit (2.0.4-r0)
(3/4) Installing pcre (8.38-r0)
(4/4) Installing nginx-lua (1.8.0-r5)
Executing busybox-1.24.1-r7.trigger
OK: 443 MiB in 49 packages





nginx.confを編集し、luaのプログラムを直接記載。


# vi /etc/nginx/nginx.conf



適当にlocation /luaを追加します。


    server {                                                    
        listen     80;                                                
        server_name localhost;                
                                                                                
        #charset koi8-r;                                        
                                                                
        #access_log logs/host.access.log main;                            
                                    
        location / {                                                        
            root html;                                        
            index index.html index.htm;                            
        }    

        location /lua {                        
            default_type 'text/plain';                                    
            content_by_lua "ngx.say('Hello,lua!')";        
        }




nginx起動


# service nginx start




ブラウザでhttp://[サーバーIP]/luaを表示してみると、
ちゃんとluaが動いてくれました。

671_01.png

これは便利。


テーマ:サーバ - ジャンル:コンピュータ

  1. 2016/02/21(日) 16:08:43|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

luvi 実行時引数の取得と環境変数の取得

luviを軽く触ってみています。
luviでLuaプログラムをバイナリの実行形式に変換する


今回は実行時引数や環境変数の取得方法を調べてみます。


実行時引数



実行時引数は、argsという変数に格納されています。
サンプルのmain.luaはこんな感じになります。


  1. -- 引数の個数
  2. print(#args)
  3. -- 引数を表示
  4. print(args[0])
  5. print(args[1])
  6. print(args[2])




プログラムに実行時引数を渡すには、「 -- [引数]」という風に指定します。


$ ./luvi my_app -- first second
2
./luvi
first
second






環境変数



環境変数はenvモジュールを使用して、取得や設定が行えます。


  1. local env = require('env')
  2. -- 環境変数のキーの個数
  3. print(#env.keys())
  4. -- キー名を表示
  5. for i = 1, #env.keys() do
  6.     print(env.keys()[i])
  7. end
  8. -- キーの値を表示
  9. print(env.get('HOME'))
  10. -- 環境変数に値を設定
  11. env.set('TEST_KEY', 'TEST_VALUE')
  12. print(env.get('TEST_KEY'))
  13. -- 値を削除
  14. env.unset('TEST_KEY')
  15. print(env.get('TEST_KEY'))



テーマ:プログラミング - ジャンル:コンピュータ

  1. 2016/02/18(木) 22:44:14|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

luvi + luv http postのサンプル

luvi + luvでhttp getしてみました。
luvi luvを使用してhttp getリクエストを実行する

ついでにpostしてみます。
postの方法については、こちらを参考にしました。
telnetでhttpとか


とりあえず動いたレベルのソースですが備忘録&バックアップとして。


  1. local uv = require('uv')
  2. function split(str, pat)
  3. local t = {} -- NOTE: use {n = 0} in Lua-5.0
  4. local fpat = "(.-)" .. pat
  5. local last_end = 1
  6. local s, e, cap = str:find(fpat, 1)
  7. while s do
  8.      if s ~= 1 or cap ~= "" then
  9.      table.insert(t,cap)
  10.      end
  11.      last_end = e+1
  12.      s, e, cap = str:find(fpat, last_end)
  13. end
  14. if last_end <= #str then
  15.      cap = str:sub(last_end)
  16.      table.insert(t, cap)
  17. end
  18. return t
  19. end
  20. function http_get(host, port, resource)
  21.     local hostinfo = uv.getaddrinfo(host)
  22.     local ip = hostinfo[1].addr
  23.     local client = uv.new_tcp()
  24.     uv.tcp_connect(client, ip, port)
  25.     uv.write(client, string.format('GET %s HTTP/1.1\n\n', resource))
  26.     local res_all = ''
  27.     uv.read_start(client, function(err, chunk)
  28.         if chunk then
  29.             res_all = res_all .. chunk
  30.         else
  31.             uv.close(client)
  32.         end
  33.     end)
  34.     uv.run('default')
  35.     
  36.     local response = {}
  37.     local r = split(res_all, '\r\n')
  38.     local h = split(r[1], ' ')
  39.     response.status_code = h[2]
  40.     response.status_name = h[3]
  41.     
  42.     local body_index = 2
  43.     while true do
  44.         local line = r[body_index]
  45.         body_index = body_index + 1
  46.         if line == '' then
  47.             break
  48.         end
  49.     end
  50.     
  51.     response.body = r[body_index]
  52.     for i = body_index + 1, #r do
  53.         response.body = response.body .. '\r\n' .. r[i]
  54.     end
  55.     
  56.     return response
  57. end
  58. function http_post(host, port, resource, post_values)
  59.     local hostinfo = uv.getaddrinfo(host)
  60.     local ip = hostinfo[1].addr
  61.     
  62.     local post_value = ''
  63.     for k,v in pairs(post_values) do
  64.         if post_value ~= '' then
  65.             post_value = post_value .. '&'
  66.         end
  67.         post_value = post_value .. string.format('%s=%s', k, v)
  68.     end
  69.     local client = uv.new_tcp()
  70.     uv.tcp_connect(client, ip, port)
  71.     uv.write(client, string.format('POST %s HTTP/1.1\n', resource))
  72.     uv.write(client, 'Content-Type: application/x-www-form-urlencoded\n')
  73.     uv.write(client, string.format('Content-Length: %d\n\n', string.len(post_value)))
  74.     uv.write(client, post_value)
  75.     local res_all = ''
  76.     uv.read_start(client, function(err, chunk)
  77.         if chunk then
  78.             res_all = res_all .. chunk
  79.         else
  80.             uv.close(client)
  81.         end
  82.     end)
  83.     uv.run('default')
  84.     
  85.     local response = {}
  86.     local r = split(res_all, '\r\n')
  87.     local h = split(r[1], ' ')
  88.     response.status_code = h[2]
  89.     response.status_name = h[3]
  90.     
  91.     local body_index = 2
  92.     while true do
  93.         local line = r[body_index]
  94.         body_index = body_index + 1
  95.         if line == '' then
  96.             break
  97.         end
  98.     end
  99.     
  100.     response.body = r[body_index]
  101.     for i = body_index + 1, #r do
  102.         response.body = response.body .. '\r\n' .. r[i]
  103.     end
  104.     
  105.     return response
  106. end




utils.luaとした場合、main.luaからの呼び出しサンプル。


  1. local bundle = require('luvi').bundle
  2. bundle.register("utils", "utils.lua")
  3. require('utils')
  4. local response = http_get('127.0.0.1', '8080', '/sample.php?name=symfo')
  5. print(response.status_code)
  6. print(response.body)
  7. data = {
  8.     name = 'symfo',
  9.     key = 'value'
  10. }
  11. local response = http_post('127.0.0.1', '8080', '/sample.php', data)
  12. print(response.status_code)
  13. print(response.body)





【参考URL】

telnetでhttpとか

Split Join

Luaのお勉強 いろいろなループ方法(while,repeat,for,pairs)

Luaのお勉強 文字列操作

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2016/02/17(水) 23:08:50|
  2. Lua
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ