前几天开始从xfce转移到awesome,为了修改好配置文件,花了2个小时把《programming in lua》这本书快速的翻了一遍。经过几天边学边做,目前的awesome桌面看起来有那么回事了~
主要修改的地方:tag的设置,右上角的电量、网速、CPU、内存和音量监控,以及一些简单的外观修改。
下面记录一点备忘的内容。
通过LUA_PATH设置的路径在.config/awesome/rc.lua中无效,在rc.lua中的require似乎无法读取LUA_PATH的设定,所以所有的lua文件我都放置在.config/awesome目录下。
在rc.lua中直接运行io.popen或awful.uitl.pread都会导致桌面hang-up,在编写音量显示的widget的时候困了我很长一段时间,我一直以为是自己程序写错了,后来发现了一个官方的bug说明,于是将音量读取中的“amixer sget Master,0”放置到timer中执行,一切OK。
CPU,MEM,NET的情况分别位于以下三个位置:
/proc/stat /proc/meminfo /proc/net/dev
其中/proc/stat的解读稍微有点不同。其中第一行的数据,从第二项开始依次为:
- user:从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。
- nice:从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
- system:从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
- idle:从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
- iowait:从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies)
- irq:从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
- softirq:从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)
关于单位jiffies,是Linux内核中的一个全局变量,代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。jiffies的单位就是1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。
对于计算CPU使用率来说,只有前四个值是有效的。取两个时间段之间的四个值,分别为user1,user2,nice1,…,idle2,则这段时间内的CPU使用率为:
used1 = user1 + nice1 + system1 used2 = user2 + nice2 + system2 total1 = used1 + idle1 total2 = used2 + idle2 rate = (used2 - used1) / (total2 - total1)
另外,lua中的string处理的模式匹配和正则不完全一样:
.(点): 与任何字符配对 %a: 与任何字母配对 %c: 与任何控制符配对(例如n) %d: 与任何数字配对 %l: 与任何小写字母配对 %p: 与任何标点(punctuation)配对 %s: 与空白字符配对 %u: 与任何大写字母配对 %w: 与任何字母/数字配对 %x: 与任何十六进制数配对 %z: 与任何代表0的字符配对 %x(此处x是非字母非数字字符): 与字符x配对. 主要用来处理表达式中有功能的字符(^$()%.[]*+-?)的配对问题, 例如%%与%配对 [数个字符类]: 与任何[]中包含的字符类配对. 例如[%w_]与任何字母/数字, 或下划线符号(_)配对 [^数个字符类]: 与任何不包含在[]中的字符类配对. 例如[^%s]与任何非空白字符配对 +: 匹配前一字符1次或多次 *: 匹配前一字符0次或多次 -: 匹配前一字符0次或多次 ?: 匹配前一字符0次或1次
附带部分源码:
battery.lua
我使用的是tp_smapi控制电池,而且可以安装两块电池。不同的机器可能不同。
battery_widget = widget({type="textbox", align="right"})
function get_battery_string(num)
local battery_root = "/sys/devices/platform/smapi/"
local str = ""
io.input(battery_root .. "BAT" .. num .. "/state")
local state = io.read()
if state ~= "none" then
str = "[B" .. num .. ":"
if state == "idle" then
-- str = str .. ""
elseif state == "charging" then
str = str .. "IN "
elseif state == "discharging" then
str = str .. "OUT "
else
str = str .. "Err "
end
io.input(battery_root .. "BAT" .. num .. "/remaining_percent")
str = str .. io.read() .. "]"
end
io.input():close()
return str
end
function update_battery()
battery_widget.text = get_battery_string(0) .. get_battery_string(1)
end
update_battery()
battery_timer = timer({timeout = 30})
battery_timer:add_signal("timeout", update_battery)
battery_timer:start()
volume.lua
volume_widget = widget({ type = "textbox" })
function update_volume1(widget)
widget.text = "Vol"
end
function update_volume(widget)
local str = awful.util.pread("amixer get Master,0")
print(str)
local volume = tonumber(string.match(str, "(%d?%d?%d)%%"))
status = string.match(str, "%[(o[^%]]*)%]")
local display_string = "[V:"
if string.find(status, "on", 1, true) then
display_string = display_string .. volume .. "]"
else
display_string = display_string .. "M]"
end
widget.text = display_string
end
-- update_volume(volume_widget) !this line will hang-up awesome, DO NOT uncomment it
awful.hooks.timer.register(10, function () update_volume(volume_widget) end)
sys.lua
require("string_ex")
require("number_ex")
sys_widget = widget({type="textbox"})
local update_time = 2
local old_cpu_used = 0
local old_cpu_total = 0
local old_e_in = 0
local old_e_out = 0
local old_w_in = 0
local old_w_out = 0
function get_cpu_rate()
io.input("/proc/stat")
local str = io.read("*line")
io.input():close()
local values = string_ex.split(string_ex.trim(str), " ")
local used = values[2] + values[3] + values[4]
local total = used + values[5]
local rate = 100 * (used - old_cpu_used) / (total - old_cpu_total)
old_cpu_used = used
old_cpu_total = total
return math.ceil(rate)
end
function get_mem_rate()
io.input("/proc/meminfo")
local mem_total = io.read("*line")
local mem_free = io.read("*line")
local mem_buf = io.read("*line")
local mem_cache = io.read("*line")
io.input():close()
mem_total = tonumber(string.match(mem_total, " (%d+) kB"))
mem_free = tonumber(string.match(mem_free, " (%d+) kB"))
mem_buf = tonumber(string.match(mem_buf, " (%d+) kB"))
mem_cache = tonumber(string.match(mem_cache, " (%d+) kB"))
local rate = math.ceil((mem_total - mem_free - mem_buf - mem_cache) * 100 / mem_total)
return rate
end
function get_net_rate()
io.input("/proc/net/dev")
local str = io.read("*all")
io.input():close()
local e_in, e_out = string.match(str, "eth0:%s+(%d+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)%s")
local w_in, w_out = string.match(str, "wlan0:%s+(%d+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+(%d+)%s")
local e_rate_in = (e_in - old_e_in) / update_time
local e_rate_out = (e_out - old_e_out) / update_time
local w_rate_in = (w_in - old_w_in) / update_time
local w_rate_out = (w_out - old_w_out) / update_time
old_e_in = e_in
old_e_out = e_out
old_w_in = w_in
old_w_out = w_out
return math.ceil(e_rate_in / 1000), math.ceil(e_rate_out / 1000), math.ceil(w_rate_in / 1000), math.ceil(w_rate_out / 1000)
end
function update_sys()
local str = "[C:" .. get_cpu_rate() .. "|M:" .. get_mem_rate()
local net_e_in, net_e_out, net_w_in, net_w_out = get_net_rate()
str = str .. "|e:" .. net_e_in .. "/" .. net_e_out .. ", w:" .. net_w_in .. "/" .. net_w_out .. "]"
sys_widget.text = str
end
cpu_timer = timer({timeout = update_time})
cpu_timer:add_signal("timeout", update_sys)
cpu_timer:start()
截屏的快捷键(基于scrot):
-- save screenshots by press print key
awful.key({ }, "Print",
function()
awful.util.spawn("scrot -e 'mv $f ~/Resources/Images/screenshots/ 2>/dev/null'")
end),
音量控制的快捷键(基于alsamixer的控制):
-- volume control
awful.key({ }, "XF86AudioLowerVolume",
function()
awful.util.spawn("amixer sset Master,0 5%-")
update_volume(volume_widget)
end),
awful.key({ }, "XF86AudioRaiseVolume",
function()
awful.util.spawn("amixer sset Master,0 5%+")
update_volume(volume_widget)
end),
awful.key({ }, "XF86AudioMute",
function()
awful.util.spawn("amixer sset Master toggle")
update_volume(volume_widget)
end)
