I am LAZY bones? AN ancient AND boring SITE

2010年 09月 的归档

sudo的配置

大家都知道,root权限是linux系统中的最高权限,有了root权限,就可以对系统做任何操作。
但是,很多情况下,这样一个笼统的root权限并不能很好地满足需求,比如,有时候想让系统的某几个用户有装包的权限(就是执行apt-get或者yum什么的),但是不能随便更改其他系统配置;又比如,想让某个用户有杀死指定另外一个用户的进程的权限(比如www用户什么的),但是也不能随便杀其他用户的进程。
这样一来,便有了细化这个“最高权限”的需求了。于是,权限管理的一大利器——sudo——便应运而生了。
可能是由于sudo的需求本来就比较复杂,看我上面说的例子,用口语表达都比较拗口;也可能是有sudo需要的安全级别比一般的程序要高一些。导致sudo的配置,看上去有点凌乱和摸不着北,所以这里稍微解释一下。
首先,sudo的配置文件是 /etc/sudoers,虽然你也可以手工打开、编辑、保存。但还是建议使用visudo命令来编辑。这是因为:

  • 它能够防止多个用户同时修改它
  • 它能进行有限的语法检查
  • 它能避免因权限位出错而不被sudo认可

然后,打开配置文件以后可以看到有这几部分:

  • Host_Alias、User_Alias和Cmnd_Alias,分别是主机、用户和命令的别名。
  • Defaults一些默认的特性,比如默认要不要重设环境变量,重设哪几个环境变量,默认以谁的身份执行等等。
  • 后面就是重头戏了,类似这样的一行:
    root ALL=(ALL) ALL
    其实这行是 user machine=(users) commands 这样的格式,也就是,允许在machine登录的 user 用户以users的身份来执行commands命令。这里的machine、users呵呵commands就可以用Host_Alias、User_Alias和Cmnd_Alias来代替了。
  • %group ALL=(ALL) ALL
    和上面的一样,只不过这个按组来限制权限。

还是用例子来说话吧,接着上面的两个例子。

例1. 让系统的某几个用户有装包的权限(就是执行apt-get或者yum什么的),但是不能随便更改其他系统配置。
做法就是将这几个用户加入某个特殊的组里(当然,如果你愿意也可以一个个用户分别设置,哈),比如建了yumer组,把用户都加进去了,然后sudo的配置加上:
%yumer ALL=/usr/bin/yum

例2. 让某个用户(dev)有杀死指定另外一个用户的进程的权限(比如www用户什么的),但是也不能随便杀其他用户的进程。
配置如下:
## Processes
Cmnd_Alias PROCESSES = /bin/kill, /usr/bin/kill, /usr/bin/killall, /usr/bin/pkill
Defaults:dev runas_default=www
dev ALL=(www) PROCESSES

先把几个命令alias成一个 PROCESSES,然后指定dev用户,有以www用户的名义执行PROCESSES里的程序的权限。
本来,dev用户必须使用 sudo -u www kill 1111 来杀死www用户的1111号进程的,但是加个-u显然麻烦,所以有了一行: Defaults:dev runas_default=www
这行的意思,是让sudo知道,只要是dev用户执行的,默认就是www的身份,而不是一般的root身份。

这里只是通过两个简单的例子介绍了sudo最常用的功能,其实sudo还有很多其他的有趣功能。比如,sudo还可以实时将非法操作检测出来,以多种方式记录到日志里,不只是本地日志,还可以通过http等方式传到别的机器等。更多功能,当然得参见man页了,哈哈。

python编程细节──遍历dict的两种方法比较

python以其优美的语法和方便的内置数据结构,赢得了不少程序员的亲睐。
其中有个很有用的数据结构,就是字典(dict),使用非常简单。说到遍历一个dict结构,我想大多数人都会想到 for key in dictobj 的方法,确实这个方法在大多数情况下都是适用的。但是并不是完全安全,请看下面这个例子:

#这里初始化一个dict
>>> d = {'a':1, 'b':0, 'c':1, 'd':0}
#本意是遍历dict,发现元素的值是0的话,就删掉
>>> for k in d:
...   if d[k] == 0:
...     del(d[k])
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
#结果抛出异常了,两个0的元素,也只删掉一个。
>>> d
{'a': 1, 'c': 1, 'd': 0}
 
>>> d = {'a':1, 'b':0, 'c':1, 'd':0}
#d.keys() 是一个下标的数组
>>> d.keys()
['a', 'c', 'b', 'd']
#这样遍历,就没问题了,因为其实其实这里遍历的是d.keys()这个list常量。
>>> for k in d.keys():
...   if d[k] == 0:
...     del(d[k])
... 
>>> d
{'a': 1, 'c': 1}
#结果也是对的
>>>

其实,这个例子是我简化过的,我是在一个多线程的程序里发现这个问题的,所以,我的建议是:遍历dict的时候,养成使用 for k in d.keys() 的习惯。
不过,如果是多线程的话,这样就绝对安全吗?也不见得:当两个线程都取完d.keys()以后,如果两个线程都去删同一个key的话,先删的会成功,后删的那个肯定会报 KeyError ,这个看来只能通过其他方式来保证了。

mysql数据库表名的大小写问题

记一下一个从昨天一直找到今天才找到原因的问题,希望可以帮助到也在苦苦查找原因的后来人。
有个hive开发环境,元数据库用的是mysql。然后从一个mysql迁移到另一个以后,就发生了莫名其妙的错误,表现在:mysqldump 出来,用 mysql < xxx.sql 导入以后,数据库连接正常,写入也有权限,但是对某些表插入数据的时候,莫名地报主键冲突的错误(那表的主键只有一个字段,主键约束也很简单,select 发现没有和要插入的数据重复的)。 究其原因,可以看到mysql里有两张表,表名除大小写以外都一样。。。这样判断主键是否重复的时候,就会把两个表合起来判断了(mysql 5.0.45 有此问题,其他版本未测试)。 后来通过google,发现mysql数据库在windows下,由于windows的文件名是不分大小写的,所以表名默认也不分大小写;但是在linux服务器下,默认是区分大小写的。。。但是这个方式反而容易引发一系列的兼容性问题,比如从一个复制数据到另一个的时候,可能由于表名大小写不同而访问不到。因此mysql也提供了一个关闭区分表名大小写的方法: 修改 mysql 的配置文件 /etc/my.cnf 在[mysqld]那段里添加这么一行: lower_case_table_names=1
然后再重启一下mysqld,就会自动把所有表名转换成小写存储,问题也就迎刃而解了。

关于我的网络

近一个月来,都在断断续续折腾网络,遇到蛮多不爽的,流水帐记录一下。
首先是拉宽带,杭州有电信、网通、联通,由于联通是新入的,所以搞活动比较多,也最便宜,于是优先考虑,结果打电话过去,告诉他地址之后,人家就说“对不起,我们的网络暂时还不到您的小区!”(都怪我住得太偏了,唉。。)
无奈只能问问老牌的电信,一问1M 1年980,2M 1180,但是还需要初装费100块,觉得还是有点小贵,再问网通,人家1M、2M都是980,选1M还可以送个不值钱的蚕丝被,而且不用初装费,然后又听说网通其实现在用户少,平时限速不严,常常1M的带宽下载也能300+KB/s。又贪图了那100块钱的初装费,就装了1M的网通。
话说,网通的上门速度还真不错,当天打电话,就来给安装了,晚上回去一试,速度果然还可以,就开心地以为没啥问题了呢,到后来才发现那句老话──一分钱,一分货──还是有道理,这个网通果然还是存在不少毛病:首先是网络不稳定,你上得正开心呢,冷不丁就给你来次断线,还好我不怎么玩网络游戏,不然就更郁闷了。再者,我之前都是通过ssh隧道翻墙的,但是自打用了网通以后,就很难连上国外主机的22端口(80端口非常正常)了,奇怪的是,我ssh到国内主机很正常,从国内主机ssh到国外主机也很正常,但是就是不能直接ssh出去,于是基本确定是网通封了某些IP的某些端口或者是网通没有国际线路的带宽?于是郁闷地打丫投诉电话,接线员基本不能理解我说的是什么问题,我想他毕竟只是接线员而已,只要能记录问题就行,也就不多说了,说第二天给派人上门维修,于是第二天就上门了一个可爱的网通工作人员,进门我给他开电脑看问题,一看到linux,就直接不看了,打开他自己带的笔记本,插上我的网线,用他自己的账号拨号上网,然后打开网通的主页,点了一个电影开始放起来,一边对我说:“你看,网络一切正常,速度还不错~”。。。我那个无奈啊。。。后来花了很多时间跟他解释什么是 ssh(他居然压根不知道什么是ssh,什么是端口)、上网不只是能看电影能偷菜就行的等等。然后我帮他一字一句地把上门服务地详情录入到网通的系统里。。。
还好,经过我的N次电话之后,现在勉强能ssh出去了,虽然ssh隧道的速度和看电影的速度不是一个级别的,但是好歹能上推了。。。
这里给广大网友提个醒:如果你上网不只是为了看电影的话,一定要慎选网通。不然真是劳民伤财啊。。。打96171都花了我不少钱了。