2 -- return output & return value
4 cmd
= cmd
..[[ 2>&1; echo -e "\nKylin_RETURN$?"]]
5 local _pfile
= assert(io
.popen(cmd
))
6 local _s
= _pfile
:read("*all")
8 _
,_
,_s
, _r
= string.find(_s
, "(.*)\nKylin_RETURN(%d+)")
9 return _s
, tonumber(_r
)
14 local _f
= assert(io
.open(file
, "r"))
15 local _t
= _f
:read("*all")
20 function mywrite(file
, s
)
21 local _tn
= os
.tmpname()
22 local _tf
= assert(io
.open(_tn
, "w"))
25 assert(0 == os
.execute("sudo cp ".._tn
.." "..file
), "[Error] - ".."cp ".._tn
.." "..file
)
26 return os
.execute("rm ".._tn
)
29 function read_file_lines(filename
)
30 local t
= myread(filename
)
32 string.gsub(t
, "(.-[\n$])", function(l
) table.insert(lines
,l
) end)
36 function flush_file_lines(filename
, lines
)
37 mywrite(filename
, table.concat(lines
))
41 if (v
== 1) then return 2 end
45 function sec2string(t
)
46 sec
= assert(tonumber(t
))
49 elseif (sec
< 60*60 ) then
50 return string.format("%d分%d秒", sec
/60, sec
%60)
51 elseif (sec
< 86400) then
52 return string.format("%d小时%d分%d秒", sec
/(3600), (sec
%3600)/60,sec
%3600%60)
54 return string.format("%d天%d小时%d分%d秒",sec
/(86400), (sec
%86400)/(3600),
55 (sec
%86400%3600)/60, sec
%86400%3600%60)
60 return string.format("%02d:%02d:%02d/%4d年%02d月%02d日",
61 t
["hour"],t
["min"],t
["sec"],t
["year"],t
["month"],t
["day"])
64 function size2hum(size
)
65 s
= assert(tonumber(string.sub(size
, 1, -2)), "size2hum: Not number")
66 u
= string.lower(string.sub(size
, -1, -1))
67 assert(u
== "b" or u
== "k" or u
== "m", [[size2hum: Unit not 'b' or 'k' or 'm']])
70 if (s
< 1024 ) then return s
.."Byte"
71 elseif (s
< 1048576 ) then return string.format("%.2f", s
/1024).." Kb"
72 elseif (s
< 1073741824 ) then return string.format("%.2f", s
/1024/1024).." MB"
73 elseif (s
< 1073741824*1024) then return string.format("%.2f", s
/1024/1024/1024).." GB"
74 else return string.format("%.2f", s
/1024/1024/1024/1024).."TB"
77 if (s
< 1024 ) then return s
.." Kb"
78 elseif (s
< 1048576 ) then return string.format("%.2f", s
/1024).." Mb"
79 elseif (s
< 1073741824 ) then return string.format("%.2f", s
/1024/1024).." GB"
80 else return string.format("%.2f", s
/1024/1024/1024).." TB"
83 if (s
< 1024 ) then return s
.." Mb"
84 elseif (s
< 1048576 ) then return string.format("%.2f", s
/1024).." Gb"
85 else return string.format("%.2f", s
/1024/1024).." TB"
91 -- do string.gsub on a file instead of on a string
92 function file_gsub(file
, s
, g
)
93 local _f
= assert(io
.open(file
, "r"))
94 local _t
= _f
:read("*all")
95 _t
= string.gsub(_t
, s
, g
)
98 local _tn
= os
.tmpname()
99 local _tf
= assert(io
.open(_tn
, "w"))
103 assert(0 == os
.execute("sudo cp ".._tn
.." "..file
), "[Error] - ".."cp ".._tn
.." "..file
)
104 os
.execute("rm ".._tn
)
108 function message_err(s
)
109 print([[<div class="messageblock messageblock-error">
110 <div class="messageblock-internal">
111 <p><ul><strong>出现了下面的错误</strong><li>]]..s
..[[
116 function ui_message_err(s
)
117 print([[<div class="messageblock messageblock-error">
118 <div class="messageblock-internal">
119 <p><ul><strong>出现了下面的错误</strong><li>]]..s
..[[
124 function ui_message_warning(s
)
125 print([[<div class="messageblock messageblock-warning">
126 <div class="messageblock-internal">
132 function ui_message_info(s
)
133 print([[<div class="messageblock messageblock-info">
134 <div class="messageblock-internal">
139 function ui_message_success(s
)
140 local success
= " ... <font color=green><strong>成功</strong></font><br>"
144 function ui_redblue_img(red
, blue
)
145 wred
= red
*300/(red
+blue
)
146 wred
= string.format("%d", wred
)
148 return "<img src=images/red.gif width="..wred
.." height=10><img src=images/blue.gif width="..wblue
.." height=10>"
151 function ui_myexec(cmd
)
154 if _r
~= 0 then ui_message_err(_s
) return nil end
157 -------------------- CGI utility --------------------------------
160 local _t
= myexec("set")
161 string.gsub(_t
, "(.-)=(.-)\n", function(n
,v
)
163 if(string.sub(n
,1,2) == "F_") then _tbl
[string.sub(n
,3,-1)] = v
end
168 -------------------------- Network utility -------------------
170 --------------------- LVM and Raid utility ------------------
172 -- return a table {["vgname"]}.{["size"], ["pvs"]}
176 local fstr
= myexec("sudo vgdisplay")
177 for str
in string.gmatch(fstr
, "(---%s*Volume group.-\n)%s*\n") do
178 string.gsub(str
, "VG%s*Name%s*(%S+).-VG%s*Size%s*(.-)\n.-Total%s+PE%s+(%d+)\n", function(v
, s
, pe
)
179 lvm
[v
] = {["size"] = s
, ["pvs"] = "", ["totalpe"] = pe
}
182 fstr
= myexec("sudo pvdisplay")
183 string.gsub(fstr
, "PV%s+Name%s+(%S+)\n.-VG%s+Name%s+(%S+)\n", function(p
,v
)
184 lvm
[v
]["pvs"] = lvm
[v
].pvs
.." "..p
191 function is_vg_exist(vgname
)
193 for k
,v
in pairs(vg
) do
194 if k
==vgname
then return true end
200 t
= myexec("/bin/df /mnt")
202 string.gsub(t
, "(%S+)%s*(%S+)%s*(%S+)%s*(%S+)%s*(%S+)%s*/mnt", function(p
,t
,u
,a
,c
)
209 if lvtbl
then return lvtbl
else return nil end
212 function display_lv()
214 if not lv
then print("something wrong: no logic volume") return end
217 <div class="sysinfo">
219 <tr class="boxheader">
220 <td class="boxheader">共享信息</td>
224 <table border="0" width="100%" align="center">
226 print([[<tr valign="top"><td><strong>共享卷使用</strong></td><td>]]
227 ..ui_redblue_img(lv
.used
,lv
.free
)..
228 "( 已使用"..size2hum(lv
.used
..'k').." / 共"..size2hum(lv
.total
..'k')..")<strong> 空闲 "..size2hum(lv
.free
..'k').."</strong></td></tr>")
229 print("</table></td></tr></table>")
232 -- return table {["md"]}.{"active", "level", "devices", "size", "err"}
233 function get_mdstat()
234 local fstr
= myexec("cat /proc/mdstat")
236 for str
in string.gmatch(fstr
, "(md%d%s*:.-\n)%s*\n") do
238 string.gsub(str
, "(md%d+)%s*:%s*(%S+)%s*(%S+)%s*(.-)\n%s*(%d+)%s*blocks%s*(.-)\n", function(m
,a
,l
,d
,s
,e
)
239 mdstat
["/dev/"..m
] = {["active"]=a
,
245 string.gsub(str
,"(md%d+)%s*:.-resync%s*=%s*([0-9%.]+).*$", function(m
, y
)
246 mdstat
["/dev/"..m
]["resync"] = y
251 for k
,v
in pairs(mdstat
) do
252 mdstat
[k
]["size"] = size2hum(mdstat
[k
]["size"].."k")
253 mdstat
[k
]["devices"] = string.gsub(mdstat
[k
]["devices"], "(%S+)%[.-%]", "/dev/%1")
258 -- return table: {["device"] = ["filesystem"]}
260 local fstr
= myexec("cat /etc/mtab")
262 string.gsub(fstr
, "(/dev/%S+)%s+(/%S*)", function(d
,f
)
268 -- return table {["device"] }. {["size"],["vendor"],["model"]}
269 function _get_physical_disks()
270 local fstr
= myexec("sudo fdisk -l")
273 string.gsub(fstr
, "Disk%s+(/dev/%S+):%s+(.-),", function(d
, s
)
274 disktbl
[d
] = {["size"] = s
}
275 local istr
= myexec("sudo /usr/bin/sginfo "..d
)
276 string.gsub(istr
, "Vendor:%s*(%S.-)\nProduct:%s+(%S.-)\n", function(v
,p
)
277 disktbl
[d
]["vendor"] = v
278 disktbl
[d
]["model"] = p
285 -- return table {["device"] }. {["size"],["vendor"],["model"], ["used"]}
286 function _get_block_devices(mtab
, vg
, raid
, ttype
)
287 local disks
= _get_physical_disks()
288 for d
in pairs(mtab
) do
289 local d1
=string.match(d
, "(%S+)%d")
291 for d2
in pairs(disks
) do
292 if d1
== d2
then disks
[d1
]["used"] = "fs" end
296 for m
in pairs(raid
) do
297 for d1
in string.gmatch(raid
[m
].devices
, "(%S+)%d") do
299 for d2
in pairs(disks
) do
300 if d1
== d2
then disks
[d1
]["used"] = "raid" end
306 for v
in pairs(vg
) do
307 for d1
in string.gmatch(vg
[v
].pvs
, "(%S+)%d") do
309 for d2
in pairs(disks
) do
310 if d1
== d2
then disks
[d1
]["used"] = "lvm" end
317 for m
in pairs(raid
) do
319 ["size"] = raid
[m
].size
,
320 ["devices"] = raid
[m
].devices
,
321 ["model"] = raid
[m
].level
323 for v
in pairs(vg
) do
324 for d1
in string.gmatch(vg
[v
].pvs
, "(%S+%d+)") do
325 if d1
== m
then disks
[m
]["used"] = "lvm" end
333 -- return physical disks table {["device"] }. {["size"],["vendor"],["model"], ["used"]}
335 local mtab
= get_mtab()
337 local raid
= get_mdstat()
338 return _get_block_devices(mtab
, vg
, raid
, "d")
342 -- return block device table {["device"] }. {["size"],["vendor"],["model"], ["used"]}
343 function get_block_devices()
344 local mtab
= get_mtab()
346 local raid
= get_mdstat()
347 return _get_block_devices(mtab
, vg
, raid
, "b")
350 -- parted a disk to 2 partitions: 1.swap and 2.xfs, then mount swap,write to fstab
351 function do_disk(disk
)
352 local success
= "<font color=green><strong>成功</strong></font><br>"
353 local fstr
= myexec("sudo parted "..disk
.." p")
354 local disksize
= string.match(fstr
, "\nDisk%s+"..disk
..":%s+(%S+)\n")
355 print("<br>disksize: "..disksize
)
356 if not disksize
then ui_message_err("Not get disk size") return end
358 ["label"] = "sudo parted -s "..disk
.." mklabel msdos",
359 ["swap"] = "sudo parted -s "..disk
.." mkpart primary linux-swap 0 512",
360 ["xfs"] = "sudo parted -s "..disk
.." mkpart primary xfs 512 "..disksize
363 local conf
= disk
.."1\tswap\tswap\tdefaults\t0\t0\n"
365 print("<br>正在为磁盘 "..disk
.."分区")
366 myexec("sudo swapoff "..disk
.."1")
367 err
, ret
= myexec(cmd
.label
)
368 if ret
~= 0 then ui_message_err(err
) return nil end
369 err
, ret
= myexec(cmd
.swap
)
370 if ret
~= 0 then ui_message_err(err
) return nil end
371 err
, ret
= myexec(cmd
.xfs
)
372 if ret
~= 0 then ui_message_err(err
) return nil else print(success
) end
374 file_gsub("/etc/fstab", "\n"..disk
.."1.-\n", "\n")
375 err
, ret
= mywrite("/etc/fstab", myread("/etc/fstab")..conf
)
376 myexec("sudo mkswap "..disk
.."1 && sudo swapon "..disk
.."1")
381 -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
382 -- ############## SAMBA Utilities #################
383 -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
385 smbshare
.config
= "/etc/samba/smb.conf"
386 smbshare
.version
= "# Generated by smbshare util.\n# Author: kang, 2008-09-26\n# e-mail: kkmm99@gmail.com\n"
388 -- return a table from smb.conf: {share,} = {name = value,}
389 function smbshare
.get()
390 local t
= myread(smbshare
.config
)
391 t
= string.gsub(t
, "\n%s*#[^\n]+", "\n")
392 t
= string.gsub(t
, "\n%s*;[^\n]+", "\n")
393 t
= string.gsub(t
, "\n+", "\n") --remove multi lines to one line
394 t
= string.gsub(t
, "%[", "\n%[") -- make an tag "\n\n" at every end of a share
395 t
= string.gsub(t
, "$", "\n\n"); -- make sure there is a tag at end of file
398 string.gsub(t
, "%[(.-)%]%s*\n(.-\n)\n", function(sh
, p
)
400 string.gsub(p
, "%s*(.-)%s*=%s*(.-)%s*\n", function(n
,v
)
407 -- write the table to smb.conf
408 function smbshare
.put(tb
)
409 smbconf
= smbshare
.version
.."[global]\n"
410 for n
, v
in pairs(tb
.global
) do
411 smbconf
= smbconf
.."\t"..n
.." = "..v
.."\n"
414 for s
,k
in pairs(tb
) do
415 if s
~= "global" then
416 smbconf
= smbconf
.."["..s
.."]\n"
417 for n
, v
in pairs(tb
[s
]) do
418 smbconf
= smbconf
.."\t"..n
.." = "..v
.."\n"
422 mywrite(smbshare
.config
, smbconf
)
425 -- return a template share table
426 function smbshare
.new()
427 return {["path"] = "/tmp",
428 ["comment"] = "no comment",
430 ["create mask"] = 666,
431 ["directory mask"] = 777,
437 -- ADD or set a share, and write to smb.conf
438 function smbshare
.set(share
, path
, readlist
, writelist
, comment
)
439 local conftable
= smbshare
.get()
440 local tb
= smbshare
.new()
443 tb
["readlist"] = ","..readlist
444 tb
["writelist"] = ","..writelist
445 tb
["comment"] = comment
446 conftable
[share
] = tb
447 smbshare
.put(conftable
)
450 -- REMOVE a share from smb.conf
451 function smbshare
.remove(share
)
452 local conftable
= smbshare
.get()
454 for s
, v
in pairs(conftable
) do
455 if s
~= share
then t
[s
] = v
end
460 -- return a local user table: {user,} = {uid,gid,comment,home,shell}
461 function get_local_user()
462 local fstr
= myread("/etc/passwd")
464 string.gsub(fstr
, "[%^\n](%S+):%S+:(%d+):(%d+):(.-):(%S+):([^\n]+)",
465 function(u
,uid
,gid
,c
,h
,s
)
466 if tonumber(uid
) >= 1000 then
467 tbl
[u
] = {["uid"] = uid
, ["gid"] = gid
, ["comment"] = c
, ["home"] = h
, ["shell"] = s
}
472 -- return a samba user table: {user = uid, }
473 function get_samba_user()
474 local fstr
= myexec("sudo cat /etc/samba/private/smbpasswd")
476 string.gsub(fstr
, "([%w_]+):(%d+)[^\n]+", function(u
,uid
) tbl
[u
] = uid
end)
479 -- smbshare.set("a new share", "/root/seconf", "nouser", "nogroup", "ok, comment")
480 -- smbshare.remove("a new share")