一个计算方差的bash函数,使用bc进行计算,默认精度是20(bc的-l选项)
Continue reading “Bash计算方差” »
一个计算方差的bash函数,使用bc进行计算,默认精度是20(bc的-l选项)
Continue reading “Bash计算方差” »
Original:http://fosswire.com/2008/02/03/sudo-vs-su/
Original written by Jacob
你可能已经见过这两个命令中的一个。Ubuntu用户对sudo更加熟悉一点,与此同时SUSE,Fedora和Debian用户更加常用su命令。到底两个命令的区别是什么呢?
两个命令都允许你得到root权限。两者的区别在于如何获得这个权限。 Continue reading “<br/><small><i>随机日志:</i></small><br /> sudo与su(原创翻译)” »
今天和同学聊天,提到Google Earth,突然想装一个玩玩。于是在网上找到了google的APT源,想从源里面安装。添加源然后update后,直接输入sudo aptitude install google然后按了tab安装了一个叫googleearth-package的软件包,以为这个就是google的APT源里面下载的Google Earth。但是安装好后却没在菜单中找到Google Earth的选项。
从新立得中搜索这个软件包,才发现这个软件包的作用是从Google Earth的bin安装包创建deb包(不知道为什么,Google Desktop和Picasa的Linux版都有官方的deb包,就Google Earth没有)。难怪在安装这个软件包时会把fakeroot也安装上去……
Continue reading “<br/><small><i>随机日志:</i></small><br /> 通过googleearth-package生成Google Earth的deb安装包” »
写这个日志的主要目的是想抛砖引玉得到更好的解决方案,为了准确描述我的需求只好废话比较多地讲一下具体的需求了:-)
最近有一个需求,需要限制某个用于察看线上日志的log用户的权限,要让权限要尽可能小但是又能看到日志文件。这样的需求很明显需要用chroot来完成。但是细想起来有一个日志目录访问问题。
假设目录所在文件夹是/var/logs,为了保证log用户能访问到这个文件夹,至少需要chroot环境中包含这个目录。如果直接这么做,log用户的chroot环境就与日志所在文件夹混在一起,不方便维护。我想到的解决方案是使用mount将目录bind到另一个文件夹下,然后在这个文件夹上级目录创建chroot环境。
例如:log用户的chroot环境处于/home/log中,那么使用mount --bind /var/logs /home/log/home/log。这样就可以让log用户进入chroot环境后看到日志,而又可以分开维护chroot文件夹和日志文件夹。
继续顺着这个思路往下走,就遇到了这篇日志的主要问题:如何使用脚本添加、删除挂载。
最终目的是尽可能自动化地进行chroot环境的创建及删除,所以同样地也要做到挂载的自动创建及删除。在挂载方面需要自动化完成以下目的:
第一条相对简单,在创建chroot脚本里直接写相应的mount语句并加入echo XXX >>/etc/fstab就可以。
第二条是我遇到的难点。如何识别“对应目录”以及如何识别fstab里对应的挂载信息?这个过程非常重要,必须要保证清理干净。实际情况是我还需要将/dev绑定到chroot环境中,如果不清理干净,其他人可能会直接rm删除chroot环境,导致/dev路径下的文件被删除。
我目前的解决方案:
创建挂载点:
echo "/var/logs /home/log/home/log/logs bind defaults,bind 0 0 #CHROOT_MOUNT_BIND_LOG" >>/etc/fstabmount -a清理挂载点
MOUNT_POINT=`grep CHROOT_MOUNT_BIND_LOG /etc/fstab|awk '{print $2}'`umount ${MOUNT_POINT}sed -i '/CHROOT_MOUNT_BIND_LOG/d' /etc/fstab这个方案个人感觉有点糟糕,不是很精确。希望大家能提供更好的思路:-)
getopts是一个Bash built-in,可以用它来实现与getopt(3)一致的参数解析功能。
注意它和getopt(1)的区别。getopt是一个单独的命令,而getopts是bash内置命令。
关于option与argument的区别,我这里实在给不出准确的定义,只能根据自己的理解试着解释一下。
argument是通常所说的命令行参数,在C语言里就是argv数组,根据参数出现的顺序从argv[1]开始依次递增(argv[0]里是被执行的程序本身的程序名)。在Bash里,$0表示脚本的名称,$1开始往后是各个argument。
option有点混乱。我的理解是:一个Option是以-(hyphen-minus character)或--开头的字符串,它后面有可选的argument,如果有则只有一个。也就是说,一个option由一个或两个argument组成
根据上面的描述命令行参数(Arguments)可以分为3类(抱歉我这里会用比较山寨的方法来描述这三类,如果有对应的标准名称,请留言指出)
getopts的基本用法类似下面的例子:
while getopts :s:h opt do case $opt in s) echo "-s=$OPTARG" ;; :) echo "-$OPTARG needs an argument" ;; h) echo "-h is set" ;; *) echo "-$opt not recognized" ;; esac done
这个例子中,定义了一个optstring(:s:h)。其中第一个:字符,打开了getopts的silent模式,可以自行对未识别的选项进行处理而不是让getopts自己报错。随后的s:定义了一个带参数的选项,如果-s使用时没有带上对应的argument则可以在随后的case语句中做相应的报错处理。最后的h定义了一个不带参数的选项。getopts的使用基本就是这样了,更详尽的getopts的optstring的定义和使用请参考bash(1)
上面的例子里我没有给出如何解析非选项参数(Non-option argument)。如果我执行./test.sh -s test_string -h filename,那么仅靠getopts是无法获取到filename这个字符串的。
仔细阅读bash(1)之后就会发现,getopts在访问到第一个non-option argument的时候即会停止解析,并设置$OPTIND为第一个non-option argument在$@中的指针。例如上面这个./test.sh -s test_string -h filename例子,getopts解析完之后会将$OPTIND设置为4。
结合$OPTIND变量和shift这个bash built-in,可以写出一个完整的解析所有参数的脚本。以下是一个例子,已经有恰当的注释信息,应该不需要额外解释了。:
#!/bin/bash declare -a NOA # Array used to store non-option argument while [ $# -ne 0 ] do # if OPTIND > $#+1, getopts will not change OPTIND's value,so set it to 0 OPTIND=0 while getopts :s: opt do case $opt in s) echo "-s=$OPTARG" ;; \?) echo "-$OPTARG not recognized" ;; esac done # if getopts find a non-option argument # it will stop parsing and return OPTIND # as index to the first non-option argument # # if getopts doesn't find any non-option argument # it will set OPTIND=$#+1 if [ $OPTIND -ne $(($#+1)) ] then shift $(($OPTIND-1)) # This is just my favorate way to append element to an array in shell. # Feel free to change it NOA=(`echo ${NOA[*]}` $1) shift else break; # getopts doesn't find any non-option argument fi done echo ${NOA[*]}
yegle.net及其子域名被DNS污染,发生时间北京时间2011年2月20日14时30分左右
184.105.128.93 yegle.net
Congrats for your being listed as “a good service provider”, certified.
R.I.P. yegle.net & *.yegle.net
射手影音最近做了一件很有争议的事情:将SPlayerX摆上了Mac AppStore。SPlayerX是一个Fork自MPleryX的影音播放器。这次射手为了完全规避GPL协议的限制,将字幕下载部分功能用二进制可执行程序方式释出,以fork运行的方式调用这个名为sscl的二进制文件下载字幕。
姑且不论其将二进制文件与GPL协议软件捆绑发行是否违反GPL协议以及GPL协议软件与Mac AppStore的协议是否有冲突。射手这次的做法恰好为所有Mac用户送上了sscl这个大礼,可以使用这个工具自动匹配本地硬盘的视频文件。
原来的设想是用AppleScript写一个脚本,并在Finder里自动监控特定目录,这样每当某目录下有新视频文件添加时就会自动下载字幕。但是我对AppleScript实在不熟悉,加上相关参考资料太少,遂作罢用bash写了一个脚本。如果有AppleScript高手,请改写之:-)
果然抛砖引玉,请参考利用Hazel让Mac自动下载电影字幕更加自动化进行字幕下载操作:-)
sscl的字幕下载目的目录是固定的,所以脚本里就直接Hardcode进去了。
注意:
射手影音并没有为sscl单独设置一个license,我只能根据SPlayerX本身免费下载认为它是freeware。提取该文件单独运行引起的版权上的争议不在本文讨论范围内。
本文中提到的find、mktemp为GNU findutils和GNU coreutils里的版本,请通过MacPort或其他Port系统安装之后再执行
功能描述:
执行脚本时,在预设的目录内查找mkv和avi文件,过滤掉某些0day release里的sample文件。
对于每个文件,如果不存在对应的.chn.srt字幕文件,就调用sscl进行下载并复制到电影文件所在文件夹。
使用方法:
1、下载sscl文件。该文件可以从SPlayer Mercurial源里获取,地址是:http://hg.splayer.org/splayerx/raw/0b9e84441210/binaries/x86_64/sscl
2、修改该文件权限,终端下chmod +x sscl
3、将以下代码保存为sub.sh。请根据你系统内的bash路径修改shabang,我的系统bash是在/Users/yegle/Gentoo/bin/bash的,一般的mac系统应该是在/bin/bash。同时还要修改SSCL为你系统内sscl二进制文件路径,以及MOVIE_DIR你的电影文件所在路径。
4、在终端下执行sh sub.sh,即可自动匹配你的MOVIE_DIR目录下所有电影文件并自动将字幕复制到你的电影文件所在文件夹。如果有字幕没有下载到,将会在命令行里提示某个视频没有找到对应字幕。
#!/Users/yegle/Gentoo/bin/bash MOVIE_DIR=/Users/yegle/Downloads/ MOVIE_LIST=`mktemp` SSCL=/Users/yegle/sscl rm -rf "$HOME/Library/Application Support/SPlayerX/SVPSub/"* find $MOVIE_DIR -regextype posix-extended -iregex '.*\.(mkv|avi)$'|grep -iv sample >$MOVIE_LIST while read movie_file_path do movie_filename=`basename "$movie_file_path"` movie_path=`dirname "$movie_file_path"` if [ ! -e "${movie_file_path%.*}.chn.srt" ] then $SSCL --video-file "$movie_file_path" --pull >/dev/null 2>&1 ls "$HOME/Library/Application Support/SPlayerX/SVPSub/${movie_filename%.*}.chn.srt" >/dev/null 2>&1 \ && mv "$HOME/Library/Application Support/SPlayerX/SVPSub/${movie_filename%.*}".*.srt "$movie_path" \ || echo $movie_file_path subtitle not found fi done < $MOVIE_LIST
自从twitter废弃basic auth之后,dabr的登录就一直是个头疼的事情。虽然官方提供了数据库存储oauth access token的方案,但是这样还需要多个数据库支持…麻烦…
大家也知道,twip4是有一个模拟OAuth登录的功能的,也就是说输入用户名密码完成oauth认证。这个模拟OAuth功能是@tifan同学完成的(大家鼓掌!),稍加修改后这个oauth_proxy.php还可以通用化。以下就是将oauth_proxy.php使用于dabr实现免翻墙登录的方法。
警告:不要在任何非自己搭建的dabr上输入密码!不要在不支持https的dabr上输入自己的用户名密码!(理论上说,没有使用https,GFW可以抓到你的twitter用户名密码)
以下操作假设你已经有一个搭建好的可用的dabr站点,如果没有,请先参考官方wiki搭建好。假设这个站点是 http://example.com/dabr/
下载文件
免翻墙dabr需要从twip项目里取到以下文件:oauth_proxy.php、simple_html_dom.php
下载路径是
http://twip.googlecode.com/svn/trunk/oauth_proxy.php http://twip.googlecode.com/svn/trunk/include/simple_html_dom.php
将这两个文件放在dabr的根目录里,也就是
http://example.com/dabr/oauth_proxy.php http://example.com/dabr/simple_html_dom.php
修改文件
首先要修改oauth_proxy.php里,include simple_html_dom.php的路径。将oauth_proxy.php里,开头的
include('include/simple_html_dom.php');
修改为
include('simple_html_dom.php');
然后修改common/user.php文件。找到 function user_oauth(),该函数的最后一部分是:
// redirect user to authorisation URL $authorise_url = 'http://api.twitter.com/oauth/authorize?oauth_token='.$token['oauth_token']; header("Location: $authorise_url");
修改为:
// redirect user to authorisation URL $authorise_url = 'http://api.twitter.com/oauth/authorize?oauth_token='.$token['oauth_token']; if($_POST){ header('Location: ' . BASE_URL.'oauth_proxy.php?p='.base64_encode($_POST['password']).'&u='.base64_encode($_POST['username']).'&g='.urlencode($authorise_url)); } else{ header("Location: $authorise_url"); }
最后修改登录页面的html,加入登陆表单html。仍然是common/user.php,找到function theme_login(),该函数里开头一部分是:
$content = 'blablablabla';
在该行下方添加一行:
$content .=' <p>Try the new oauth-simulate login</p> <form action="'.BASE_URL.'oauth" method="post"> <p>Username: <input type="text" name="username"/></p> <p>Password: <input type="password" name="password"/></p> <p><input type="submit" value="Login"/></p> </form>';
如果你愿意改呢,还可以继续在这个基础上改得漂亮一点,反正以我的审美…凑合了…
现在返回dabr首页,你将看到一个用户名密码输入框,输入你的twitter用户名密码后即可完成登录。
不想看废话的同学们可以直接跳转到安装步骤
什么是Ports系统?
众所周知Mac OSX是一个UNIX操作系统。UNIX操作系统的认证是Open Group给的,只有经过他们认证之后才能自称自己是UNIX操作系统并使用UNIX的商标(毕竟人家这是注册商标,不能随便用)。
得益于UNIX标准的建立,越来越多在Linux上开发的开源软件已经可以直接在UNIX下编译安装而不需要考虑跨平台问题,这意味着在Mac OSX上也可以享受绝大多数Linux下开源软件的最新版本。
注意到,我这里提到的是“编译安装”。即使你是一个对编译安装感觉很平常的Linuxer,在Mac下编译安装也不是一件简单的事情,因为你需要自行解决一大堆依赖。有多复杂,你可以尝试安装一次LFS。虽然Linux下常见的包管理系统Mac下没有,但是Mac上有相对于包管理系统来说更加强大的Ports系统(IMO),让这些软件包的安装过程自动化了。
Ports系统的历史还真不好找,从wiki获得的信息是,这是早期BSD系统就开始有的一套比较“原始”的包管理系统:自动从官方网站下载源码包、解压、打补丁、编译安装,并维护各个软件包之间的依赖关系。使用Ports系统,可以通过自动化方式从源码安装软件,而无需考虑其背后的繁琐操作。
除了BSD系统上的Ports系统之外,Linux下常见的Ports系统有:Gentoo Portage和ArchLinux ABS。在Mac OSX上也有多个Ports系统可以选择,比较有名的有MacPorts和HomeBrew(Sorry,还有一个什么Brew的忘记名字了…感谢blackgigi提醒:-))。Gentoo-prefix反而是一个不太常用的Mac下的Ports系统。
Continue reading “在Mac OSX上安装gentoo-prefix” »
可到http://yubikey.taobao.com/购买
从@ohsc那里了解到yubikey这个东西。作为信息安全的学生,我的第一反应是:两眼发亮。为什么两眼发亮呢?慢慢解释。
首先要从什么是OTP说起。
OTP是One-Time Password的简称,中文对应的准确翻译应该叫“一次一密”。根据香农(这个人…信息论、现代密码学,以及其他乱七八糟东西的发明者,牛逼至极的人物啊!)创立的现代密码学理论,一次一密是不可能被破解的,除此之外所有的其他加密方案都至少能被暴力破解,虽然破解的难度是指数级的。(当然,香农说的一次一密不可破解是有前提条件的,具体参考维基百科上的”一次性密码本“词条)。具体来说,一次一密就是在每次加密会话过程中,对传送的明文使用不同的密钥进行加密,每次使用的密钥是随机、不可预测、不重复使用的,从而保证了加密是绝对不可破解的。
当然,我说的是简单化的一次一密的实现,实际操作过程中,密钥的长度必须大于等于明文长度,而且密钥必须是可验证的(所以也可以看成是可预测的)。真正的一次一密,等于需要一个安全信道来传送不少于明文长度的密钥,几乎是没有意义的。
其实生活中已经有很多一次一密的例子,例如中国银行的E-TOKEN、魔兽世界安全令牌、中国建设银行的动态口令卡(纸制),这些都是一次一密的。
国内的一次一密电子令牌基本上使用的是SecurID,EMC公司下属的RSA公司出品的。这种一次一密解决方案使用一个预先定义的time-based的函数计算密码,称为Time-synchronized one-time password。每个token出厂前与服务器同步时间,在出厂后,token和服务器以相同的时钟计算,每分钟变化一次。
在验证token上读取的数字时,服务端可以设置允许的误差值,例如允许前后5分钟内产生的密钥输入都认为是有效的,这样可以最大限度避免token的时钟漂移。
经仔细查证后,上文描述有误。准确的实现是:RSA的服务端验证时允许前后30秒或前后60秒内的密钥为有效密钥。服务端会保留当前token,前一token,后一token三个token值,如果用户输入与当前token一致则不做变化。如果用户输入的是前一token或后一token,服务器将记录这个SecurID的ID对应的offset,下次验证时考量这个offset。如果用户超过了这三个token的值范围,用户将被提示输入SecurID显示的下一个token,如果与上一个输入的token顺序一致,系统将判断验证通过,并记录这个较大的offset值。
这样的方案安全性很高,很多公司内部的vpn系统、线上服务器登陆系统等等都使用了SecurID进行认证。缺点很明显:价格高,据说每个的成本在¥200(网易出的那个山寨版我就不评论了…售价居然才60左右…只能说不太靠谱了…),而且需要配套RSA的服务端方案;需要电池保证时钟运作,因此存在更换token的情况。
另一种完全不同的一次一密方案是使用数学方法生成密钥序列,称为Mathematical-algorithm-based one-time password。这种算法使用数学函数生成密钥序列,然后依次使用密钥序列,从而不需要考虑时间因素。由于密钥序列生成过程中没有时间因素,实际生产的硬件token可以不包含电池供电,免去服务端与token的对时,成本可以下降,同时也没有电池耗尽更换token的担忧(更换token=安全隐患,因为需要人的参与,人永远是任何安全体系的最大漏洞…)。维基百科上举例了一个使用hash chain方法产生此类OTP的方案:找到一个单向函数f(例如任意一个hash函数),给定一个初始种子s。根据f和s产生序列:f(s), f(f(s)), f(f(f(s)))…。然后将该序列倒置,依次作为密钥使用。第三方如果偶然获取到序列中某个密钥,他就必须要通过f的反函数来计算下一个密钥,而f的单向性保证了这样的计算是不可行的。
yubikey使用的是第二种方案。它是一个廉价的OTP解决方案,10枚yubikey的平均价格是$28,由yubico提供验证服务器并提供API供开发者调用。它不需要电池供电,也没有液晶屏显示密钥。在插入电脑之后,它会被识别为一个USB键盘,在任意输入框聚焦并按一下yubikey上的硬件按钮,yubikey将自动模拟键盘输入一串一次性密钥。由于yubikey在电脑上被识别为USB键盘,它可以做到最好的免驱动支持(现在没有操作系统不支持USB键盘了吧?),可以在Windows/MacOSX/Linux上使用。关于yubikey使用的OTP生成方案,强烈建议阅读一下官方提供的文档来了解:http://yubico.com/files/Security_Evaluation_2009-09-09.pdf
要注意的是,yubikey每次插拔都会在内置的非易失性存储器上的Session Counter增加1,该Session Counter总长度为16bit,在每天插拔20次的频率下,该Counter在9年左右到达满值。这个寿命还是很让人满意的。
yubikey是一个非常开放的硬件设备,它本身的硬件实现原理、服务端架设代码、服务端API代码,都是完全开放的。从而在它之上衍生了很多开源项目与之搭配使用。从yubico的wiki页面可以看到一个简单的列表。稍微列举一下:
近期评论