colaghost

自己的世界。。。

archlinux下给cpu和显卡节能设置

最近在折腾archlinux,把内核更新到3.0后,发现A卡的官方驱动上不了了,只能上下开源的驱动了,无奈开源驱动的电源管理实在不敢恭维,笔记本键盘部分老是暴热,受不鸟。

下面就从cpu和显卡两个发热大户入手吧!

1、显卡降低频率

从内核2.6.35起就加入了AMD开源驱动的电源管理,可以进行GPU频率调整、显存频率调整、电压调整和温度监控支持等。

我的是A卡,这时候就发挥了它的作用了。

可以用如下命令查看当前显卡的电源管理模式:

$ cat /sys/class/drm/card0/device/power_profile

默认的是”default”,这个使用显卡默认频率不做调整。可以将它改为auto,low,mid,high等模式,auto可以根据当前是使用电池或者电源来自动做调整。这里我将它设置为low,注意有的本本设置为low可能导致部分显示问题。

# echo low > /sys/class/drm/card0/device/power_profile

注意这个设置只在当前运行时立即生效,要在下次启动时也有效的话可以手动将它加进/etc/rc.local配置文件里。

2、CPU动态调节频率功能

查了下有cpufrequtils这个小工具,可以实现自动/手动调节CPU频率,对于笔记本来说是很有用的。

通过pacman安装即可。

$ pacman -S cpufrequtils

安装完后先手动加载驱动。

# modprobe acpi-cpufreq

为了下次启动时自动加载可以把它加到/etc/rc.conf配置文件的MODULES列。

加载完驱动后,可以执行cpureq-info查看下cpu信息。

cpufreq提供了好几个电源调整方案,我用的是cpufreq_ondemand,这个可以根据系统负载动态调整CPU频率,这个也需要加入/etc/rc.conf的MODULES列里。

最后还需要配置下/etc/rc.d/cpufreq,将#governor=”ondemand”那句取消注释后保存即可。

设置好配置文件后,可以运行以下命令来启动守护进程:

# /etc/rc.d/cpufreq start

启动后再执行下cpufreq-info看看当前频率是不是已经降下来了!

若要在启动时自动守护进程,要将cpufreq加入/etc/rc.conf配置文件的DEAMONS列里。

总结

这样设置后温度大概会比原来降低十度左右,不过貌似还是没有安装闭源驱动fglrx时温度低,但总算没那么烫手了!

ubuntu下看flash视频时禁用屏保

最近两天在啃《unix环境高级编程》,一直转在ubuntu下。我吃饭时喜欢一边看电影,可是上优酷看flash视频时又有一个麻烦的地方,就是屏保并不会自动被禁用掉,而是得手动去禁用,看完又得去把它开启,甚是麻烦,就想着自己写一个脚本来实现开启/禁用屏保。

Google了下,关于这方面的结果倒是不少,下面是其中一个脚本:

1
2
3
4
5
6
7
8
#!/bin/sh
while true;
do
    if test -n "`file /tmp/Flash*|grep \"Macromedia Flash Video\\|MPEG v4\"`";then
        gnome-screensaver-command -p
    fi
    sleep 30
done

可惜我发现我的tmp目录下并不会生成/tmp/Flash*,我原先以为是我用shockwave flash的原因,不是在tmp目录下生成缓存。就自己搜索任何可能的目录,看下具体在哪个目录里生成缓存,可惜找不到。

这时候想到linux下是可以通过lsof来监测某一个进程当前打开了哪些文件,结果发现了其实是有在/tmp目录下生成Flash*这样的文件的,只是生成后马上又被删除了,这时候虽说进程还可以进行读写操作,可是在目录下却无法看到。

因此想到了另外一种方法,由于shockwave flash做为chrome下的一个插件,只要监测到chrome载入libgcflashplayer.so的这一个进程打开的所有文件下有/tmp/Flash*类似的文件即可知道当前在播放flash视频,这时候只要运行”gnome-screensaver-commad -p”模拟活动一下即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
while true;
do
	pid=`ps aux | grep /opt/google/chrome/libgcflashplayer.so | grep -v grep | awk '{print $2}'`
	if [ "$pid" != "" ]; then
		data=`lsof -p $pid | grep /tmp/Flash`
		if [ "$data" != "" ]; then
			echo "gnome-screensaver-command"
			gnome-screensaver-command -p
		fi
	fi
	sleep 30
done

用expect来实现自动交互的shell脚本

有时候可能实现自动交互过程,如自动登陆到远程主机等,由于需要输入用户名密码神马的,得自己呆在那里等它登陆完成,比较麻烦,单纯用shell脚本又没法完成,因为像ssh连接远程主机是不从stdin读入数据的。这时候就需要expect出马了。

Expect是基于TCL的,作为一个脚本语言,expect能在无需管理员参与的情况下实现自动交互(比如passwd,fsck,telnet等),expect也能用于自动测试一些应用程序。

搜索一下其实网上很多使用expect来完成密码登陆的例子的:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
auto_login_ssh () {
    expect -c "set timeout -1;
                spawn -noecho ssh -o StrictHostKeyChecking=no $2 ${@:3};
                expect *assword:*;
                send -- $1\r;
                interact;";
}
 
auto_login_ssh passwd user@

但实际上这个脚本不能做到完全自动化,一旦密码错误或者远程主机未响应神马的,expect还是正常退出,并不能判断到底哪一步出问题了。由于使用expect后,程序的exit status是expect的,所以这时候对expect做处理。当expect遇不到期望的输出值时,就会执行eof分支,这时候我们只要在eof分支加上退出值即可以判定到底是在哪一步出了问题。

这里用两个简单的脚本说明,这样比较容易弄清楚。

called.sh

1
2
#!/bin/bash
echo "a"

可以看出上述脚本是输出“a”,也就是期望输出值应该为”a”。下面看用expect实现的交互脚本:
caller.sh

1
2
3
4
5
6
7
8
9
#!/bin/sh
expect -c "set timeout -1;
           spawn called.sh;
           expect{
               \"b\"{exit 1;}
               eof{exit 2;}
           }
           "
echo $?

实际上called.sh的输出值是”a”,但caller.sh的期望值为”b”,这时候实际上是跳到eof,这时候按状态2退出,也就是说$?实际上为2.这时候就可以判断交互脚本具体的执行情况。

这里只是一个简单的实例而已,并没有任何实际的意义,但是它说明了如何处理一些异常的情况,这样只要将上面的自动完成ssh连接远程主机的脚本加上异常情况处理即可变成一个真正完全自动交互的脚本了,以下是做修改后的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
auto_smart_ssh () {
    expect -c "set timeout -1;
                spawn ssh -o StrictHostKeyChecking=no $2 ${@:3};
                expect {
                    *assword:* {send -- $1\r;
                                 expect {
                                    *denied* {exit 2;}
                                    eof
                                 }
                    }
                    eof         {exit 1;}
                }
                "
    return $?
}
 
auto_smart_ssh passwd user@host ls /var
echo -e "\n---Exit Status: $?"

注:以上自动完成ssh连接远程主机例子来自于apt-blog.net

ubuntu10.04下无法连接网络(acer 4745G笔记本)

今天在笔记本上安装了ubuntu10.04,但无奈网卡驱动不了,一直都在爆没有合适的驱动设备,有线、无线都无法连接。

后来google了一下,找到了一个Atheros AR8151的有线网卡驱动(4745G的为此有线网卡),有需要的童鞋可以到这里下载:AR81Family-Linux-v1.0.1.9.tar.gz

下载后编译安装就行了!怎么,不会编译安装?解压后打开终端进入文件夹路径,然后敲入make && sudo make install,直接回车就行了。

安装后应该就可以连接有线网络了,但这时候无线的话还得另外一个驱动。不过这时候在系统->系统管理->硬件驱动里可以找到合适的,系统已经帮你搞好了,激活后就可以了。

写在快结束的暑假

暑假前计划了挺多,例如说看下python跟英语语法,不过现在这两个都流产了。之前还特地买了薄冰的《英语语法》,现在一直摆在桌上堆的书里,压根就没碰过。

暑假只回家一个星期,严格来说在家呆的时间只有五天,两天在车上。貌似是我这种赖家型的人呆得最少的假期了,可能以后也没有多少时间呆在家里了,怀念以前可以跟家里人呆在一起的时光。

基本上这一个半月都是在公司实习度过的吧,不停地看协议、看代码和写代码。

关于协议基本上看的都是英文,不知道看了这么多英语功力有没有提升,还翻译了一篇关于sip的呼叫例子的文章放在了博客上yy,算是成果吧。目前的工作主要是关于voip方面的,看了几个开源包,仔细阅读了其中一个开源包的代码,基本上把整个设计都摸清了,这时候才感慨外国人做事之认真,基本上每个细节都考虑到,而且用c的功力也非一般人所能及的,竟然都是用面向对象的思想来实现的,感觉自己能看懂,但是目前肯定是写不出这种水平的代码。目前实现了一个测试用的二无sip软UA,无界面且无法运行在windows上。这是我的第一个Linux程序,当时还是挺兴奋的,代码理了一遍又遍,虽然也就那么六七百行代码。

先前的《linux程序设计》倒是把该看的都看得差不多了,但是基本上没有实战,除了那个软UA用到的标准流和多线程跟信号处理,感觉在linux下写程序其实比windows下来得容易,接口都很简洁(windows的api函数名真的不是一般的长),而且实现起来也很简单,像你想多创建一个进程,直接用fork()就可以复制出一个与当前一模一样的子进程(甚至是进程映像),而在windows下你不得不传入好几个结构体用来确定返回的句柄是否要被子进程继承,还得指定一大堆控制优先级和进程创建的标志,杂七杂八的东西都掺合在一起,让人甚是头疼,甚至是难以理解。

这本书最后的几章是讲入门级的设备驱动程序开发的,原先是打算在最后仔细看的。无奈后来在无意中被《深度探索C++对象模型》这本书所吸引,放不下手就只能等把这本书看完了再接着看回它了。

暑假到目前过得还算是充实吧,白天上班,晚上回来看会儿电影洗完澡就接着看书,很忙,但觉得成长得比较快。公司是任务型的,让自己没有了拖拖拉拉的借口,不知道自己是不是有被逼迫的心理,没人逼着或是不到最后关头就不会急着去做某事。

暑假就快完了,保持自己的冲劲吧!接下去就是大四了,即将的毕业生,将来等着我去冲刺了。

统计源码文件行数的小程序

这些天在公司一直在看一个开源包,由于某种原因突然想看下这个开源包到底写了多少行代码。简单的方法:一个个文件查看再利用计算器进行加法运算!但这方法也太笨了点吧,再说,源文件那么多,我又那么懒。

想来想去还是写个脚本吧,以后或许也还有用。

记得wc -l可以直接统计文件的行数,不过输出结果是类似于“86 a.cpp”这样的形式的,还得用cut把后面的文件名给去掉。这样只需把整个文件夹的文件扫描一遍即可得到最后想要的行数了。

不过还有两个问题:一个是文件夹里的子文件夹没被扫描到,因为循环时是判断为普通文件的才进行统计;另一个是由于源文件后缀形式多样,有.java,.c,.c++等等等,必须有参数把它们传进脚本里。

第一个问题好办,不就是个递归吗?可是由于本人对SHELL编程的熟悉程度不够,递归时如何返回值就搞了很久,一直用return却只是获取不到,不知何故!最后直接用一个全局变量解决了这个问题。

第二个问题最开始就想着把每个后缀名作为单独的参数传进去,这样就涉及到参数个数不确定的问题。知道有shift这个东东可以循环扫描参数,但是又不知道如何把它们保存下来。搞到最后还是直接用”c:java”这种形式做为一个参数传进去算了,再用awk进行分解,awk里又涉及到访问外部变量和循环语句等的使用,甚是蛋疼,查了一部分资料。

最终效果是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#! /bin/sh
lines=0
count_line ()
{
	cd $1
	for file in $(ls); do
		if [ -d $file ]; then
			count_line $file $2
		else
			flag=$(echo $2 | awk -v exc=${file##*.} 'BEGIN {FS=":"}{for(i=1; i<=NF; i++){if($i==exc){print 1;break;} if(i==NF)print 0}}')
			if [ $flag -eq 1 ]; then
				lines=$(($lines+$(echo $(wc -l $file) | cut -d ' ' -f 1)))
			fi
		fi
	done
	if [ "$1"!="." ]; then
		cd ..
	fi
}
 
if [ $# -lt 2 ]; then
	echo "Requires the path and the param!"
else
	count_line $1 $2
	echo "All files have $lines lines"
fi