工作中, 需要有历遍目录进行一些操作. python自带的os.walk很强大, 但是没有maxdepth这种层数参数.
os.walk是原本是一个递归. 下面是它的代码:
273 try:
274 # Note that listdir and error are globals in this module due
275 # to earlier import-*.
276 names = listdir(top)
277 except error, err:
278 if onerror is not None:
279 onerror(err)
280 return
281
282 dirs, nondirs = [], []
283 for name in names:
284 if isdir(join(top, name)):
285 dirs.append(name)
286 else:
287 nondirs.append(name)
288
289 if topdown:
290 yield top, dirs, nondirs
291 for name in dirs:
292 path = join(top, name)
293 if followlinks or not islink(path):
294 for x in walk(path, topdown, onerror, followlinks):
295 yield x
296 if not topdown:
297 yield top, dirs, nondirs
BTW:: 这里需要注意*nux的ENAMETOOLONG 错误.
递归无法按"层"历遍目录. 它只能一条一条路径走尽.
朋友说使用循环也可以实现递归, 这种代码从来没有写过. 也一直在迷惑。
但是受 http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/2/ 的启发.
突然明白循环是怎么做到递归的。 于是自己使用循环自己写了一个历遍的函数:
def loop_walk(top, n):
stack = Queue.Queue()
sub_stack = Queue.Queue()
dirs = []
files = []
error = None
stack.put([top])
while True:
if stack.empty():
# stack被取完了, 下一层队列
stack, sub_stack = sub_stack, stack
if n <= 1:
yield [], [], None
return
else:
n -= 1
continue
else:
try:
top_list = stack.get(False)
except Queue.Empty:
yield [], [], None
return
for top in top_list:
try:
for item in os.listdir(top):
item = os.path.join(top, item)
if os.path.isdir(item):
dirs.append(item)
else:
files.append(item)
except:
# 出错, 比如没有权限
#traceback.print_exc()
error = top
yield dirs, files, error
if dirs:
sub_stack.put(dirs)
dirs = []
files = []
error = None
代码长度double了.........
Sunday, August 15, 2010
Sunday, July 18, 2010
IO笔记3
read(2)和write(2)都有一个特点: 期待被处理的数据与已经被处理的数据量可以不一致.
比如:
char buffer[5000];
size_t count = read(1, buffer, 4096);
调用read读4096个bytes, 但是是不是真的已经读了4096个bytes, 这是没有必然要求的.
socket的I/O是最明显的.
如果不一致, 就要求程序员去处理. 不过, 这都是常事了, 都有满足这样需求的函数.
但是, 这就需要程序员可以自己分清这两种情况的函数.
不要认为sys.stdin.read(4096)和os.read(sys.stdin.fileno(), 4096)是一样的.
$ (echo -e "12345\n"; sleep 10) | python -c '
import sys
print sys.stdin.read(4096)'
上面的python程序是被block了10秒才运行print的. 但是下面的是马上收到数据的:
$ (echo -e "12345\n"; sleep 10) | python -c '
import sys
import os
print os.read(sys.stdin.fileno(), 4096)'
C的standard I/O是一组保证可以返回指定数据(量)的函数
standard I/O增加了buffer, 以减少read, write的次数. 原则就是每次调用read的时候读入BUF_SIZE的数据到buffer空间中, 下面是read函数的原型:
ssize_t read(int fd, void *buf, size_t count);
count是会根据file descriptor的不同变化, 如:
1. terminate device时为1024
2. 不是terminate device时为是page size, 或者程序员使用setvbuf指定
standard I/O有三个种非格式化函数:
1. character-at-a-time I/O
2. line-at-a-time I/O
3. direct I/O
无论使用哪种函数, 它都是如下的方式:
read(fd, buffer_ptr, BUF_SIZE);
那怕你只是想使用fgetc得到一个字符. 都是调用上面的函数. 一般情况BUF_SIZE >= 1024.
standard I/O除了缓存外. 还保证了返回的数据是想得到的, 如:
1. character-at-a-time I/O时, 保证返回一个字符
2. line-at-a-time I/O时, 保证返回一行数据, 以NULL结尾.
3. direct I/O时, 保证返回指定的数据结构.
否则, 会多次调用上面的read函数, 直到取得的数据满足要求, 过程中会出来下面的情况:
1. block;
2. EOF;
3. Error
比如:
char buffer[5000];
size_t count = read(1, buffer, 4096);
调用read读4096个bytes, 但是是不是真的已经读了4096个bytes, 这是没有必然要求的.
socket的I/O是最明显的.
如果不一致, 就要求程序员去处理. 不过, 这都是常事了, 都有满足这样需求的函数.
但是, 这就需要程序员可以自己分清这两种情况的函数.
不要认为sys.stdin.read(4096)和os.read(sys.stdin.fileno(), 4096)是一样的.
$ (echo -e "12345\n"; sleep 10) | python -c '
import sys
print sys.stdin.read(4096)'
上面的python程序是被block了10秒才运行print的. 但是下面的是马上收到数据的:
$ (echo -e "12345\n"; sleep 10) | python -c '
import sys
import os
print os.read(sys.stdin.fileno(), 4096)'
C的standard I/O是一组保证可以返回指定数据(量)的函数
standard I/O增加了buffer, 以减少read, write的次数. 原则就是每次调用read的时候读入BUF_SIZE的数据到buffer空间中, 下面是read函数的原型:
ssize_t read(int fd, void *buf, size_t count);
count是会根据file descriptor的不同变化, 如:
1. terminate device时为1024
2. 不是terminate device时为是page size, 或者程序员使用setvbuf指定
standard I/O有三个种非格式化函数:
1. character-at-a-time I/O
2. line-at-a-time I/O
3. direct I/O
无论使用哪种函数, 它都是如下的方式:
read(fd, buffer_ptr, BUF_SIZE);
那怕你只是想使用fgetc得到一个字符. 都是调用上面的函数. 一般情况BUF_SIZE >= 1024.
standard I/O除了缓存外. 还保证了返回的数据是想得到的, 如:
1. character-at-a-time I/O时, 保证返回一个字符
2. line-at-a-time I/O时, 保证返回一行数据, 以NULL结尾.
3. direct I/O时, 保证返回指定的数据结构.
否则, 会多次调用上面的read函数, 直到取得的数据满足要求, 过程中会出来下面的情况:
1. block;
2. EOF;
3. Error
Friday, July 16, 2010
IO笔记2
两层buffer的存在
23 #include <stdio.h>
24
25 int main(int argc, char *argv[]){
26 int retval ;
27 while(1){
28 char c[BUFSIZ];
29 retval = read(0, c, 1);
30 printf("%c\n", *c);
31 }
32 return 0;
33 }
上面的代码, 用户输入一次, read函数被调用N次(数据的长度)。也就是说用户输入的数据已经被缓存了。
再如下:
23 #include <stdio.h>
24
25 int main(int argc, char *argv[]){
26 int retval ;
27 int i;
28 int c;
29 printf("%d\n", BUFSIZ);
30 for(i = 0; i < BUFSIZ / 2; i++){
31 c = fgetc(stdin);
32 }
33 return 0;
34 }
上面的代码fgetc被调用N次(数据的长度), 但是read的调用情况如下:
1. 当stdin不是terminate device时, 被调用一次, read的count参数为4096
2. 当stdin是terminate device时, 被调用两次, read的count参数为1024
* 至少怎么得到这种数据, 答案是使用strace凶器。
libc会根据stdin是什么使用setvbuf对FILE对象设置buffer.
从上面两个例子可以知道:
1. 使用standard I/O从terminate device读数据时, 其实经过了两个buffer机制。
2. standard I/O读不同file descriptor时的buffer大小会变化。 加上从APUE中知道的,情况会是这样
* 当stdin, stdout是terminate device时, standard I/O会使用行缓存, buffer大小为1024.
* 当stdin, stdout不是terminate device时, standard I/O会使用full buffer, buffer大小为4096.
好, 知道这两种buffer机制与buffer大小了, 移步看这一篇文章会有很好的收获:
* http://www.pixelbeat.org/programming/stdio_buffering/
这文章从一个例子开始, 如下:
# tail -f access.log | cut -d' '|uniq
为什么上面的命令没有输出? 呵呵, 其中就是IO缓存的机制.
预读数据, 减少read, write
使用standard I/O都是会预读一定数量的数据, 用于减少调用read, write的次数.
使用standard I/O的好处就是程序员无需操心这个预读数据的大小, 只需要知道它是预读的即可.
如果不知道会预读的话, 上面的URL的例子就无法明白.
23 #include <stdio.h>
24
25 int main(int argc, char *argv[]){
26 int retval ;
27 while(1){
28 char c[BUFSIZ];
29 retval = read(0, c, 1);
30 printf("%c\n", *c);
31 }
32 return 0;
33 }
上面的代码, 用户输入一次, read函数被调用N次(数据的长度)。也就是说用户输入的数据已经被缓存了。
再如下:
23 #include <stdio.h>
24
25 int main(int argc, char *argv[]){
26 int retval ;
27 int i;
28 int c;
29 printf("%d\n", BUFSIZ);
30 for(i = 0; i < BUFSIZ / 2; i++){
31 c = fgetc(stdin);
32 }
33 return 0;
34 }
上面的代码fgetc被调用N次(数据的长度), 但是read的调用情况如下:
1. 当stdin不是terminate device时, 被调用一次, read的count参数为4096
2. 当stdin是terminate device时, 被调用两次, read的count参数为1024
* 至少怎么得到这种数据, 答案是使用strace凶器。
libc会根据stdin是什么使用setvbuf对FILE对象设置buffer.
从上面两个例子可以知道:
1. 使用standard I/O从terminate device读数据时, 其实经过了两个buffer机制。
2. standard I/O读不同file descriptor时的buffer大小会变化。 加上从APUE中知道的,情况会是这样
* 当stdin, stdout是terminate device时, standard I/O会使用行缓存, buffer大小为1024.
* 当stdin, stdout不是terminate device时, standard I/O会使用full buffer, buffer大小为4096.
好, 知道这两种buffer机制与buffer大小了, 移步看这一篇文章会有很好的收获:
* http://www.pixelbeat.org/programming/stdio_buffering/
这文章从一个例子开始, 如下:
# tail -f access.log | cut -d' '|uniq
为什么上面的命令没有输出? 呵呵, 其中就是IO缓存的机制.
预读数据, 减少read, write
使用standard I/O都是会预读一定数量的数据, 用于减少调用read, write的次数.
使用standard I/O的好处就是程序员无需操心这个预读数据的大小, 只需要知道它是预读的即可.
如果不知道会预读的话, 上面的URL的例子就无法明白.
Sunday, July 11, 2010
IO笔记
IO部分总是很乱。不知道是因为API多还是其它原因:
0. 阻塞的存在
1. glibc的section3手册和linux的section2有同名函数。
2. posix, ISO都有要求
3. terminal IO与其它IO有不同的表现
4. IO缓存的机制
5. 还有众多古老的名词....
EOF
EOF是什么? 什么时候才会产生? 还是和ctrl_c一样是signal ?
如下代码的运行結果是 -1
19 #include <stdio.h>
20
21 int
22 main(int argc, char *argv[])
23 {
24 printf("%d\n", EOF);
25 return 0;
26
27 }
表示EOF是 -1 ?
当某一次使用 ssize_t read(int fd, void *buf, size_t count); 函数从一个file descriptor中读数据时(count>0), 函数得到0个字节表示读到文件的尾部了. 这时read函数返回0.
可读端的pipe关闭后, 只读端pipe在读完后会产生EOF:
2 import os
3 import sys
4 import time
5
6 read_end, write_end = os.pipe()
7
8 pid = os.fork()
9 if pid < 0:
10 print "Error"
11 sys.exit(1)
12 if pid == 0:
13 # parent
14 os.close(write_end)
15 try_time = 1
16 # 因为无法得到child process会发多少数据, 只能使用死循环去读数据
17 while True:
18 print "%s time(s) call read" % try_time
19 content = os.read(read_end, 1)
20 if not content:
21 break
22 os.write(1, content)
23 try_time += 1
24 sys.exit(0)
25
26 else:
27 # child
28 os.close(read_end)
29 os.write(write_end, "#" * 100)
30 # 关了parent就能读到EOF
31 os.close(write_end)
32 sys.exit(0)
文件系统中的文件是有固定大小(某一状态), 但是在terminal IO里,是没有一个固定的尾部的, 需要输入者指定什么时候才是end-of-file, 所以, ctrl_D出现了. ctrl_D是一个特殊控制符。被tty的驱动处理(默认情况下用户程序不能从read函数得到, 除非要求tty不处理)
在了解ctrl_D前, 应该先要了解IO的缓存机制.
standard IO缓存 与 底层IO缓存
在此这前, 我对getchar这个函数不解, 其实就是不解如下的代码:
19 #include <stdio.h>
20
21 int main(int argc, char *argv[]){
22 char c ;
23 while(c = getchar() ){
24 printf("%c\n", c);
25 }
26 }
不要以为简单调用getchar函数可以实现vim这种交互.
当调用read去读stdin的数据时, 是行缓存的.上面的代码在第一次调用getchar时把一行的数据读到buffer里(回车键返回), 下次再调用getchar时会从buffer里取. buffer没有数据后再等待用户输入.
标准IO与系统底层IO这两套IO需要分开. 不然会出现事与愿违的情况, 如:
使用setbuf对FILE对象进行了设置后, 然后使用调用printf操作. 結果没有出现想要的设置效果。例如:
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27
28 int main(int argc, char *argv[]){
29 //
30 FILE *input = fdopen(1, "r");
31 FILE *output = fdopen(1, "w");
32 setbuf(input, NULL);
33 setbuf(output, NULL);
34 char c ;
35
36 printf("Hello World");
37 sleep(10);
38 }
上面的printf的内容是过了10秒后才打印的, 明显, setbuf没有起作用。 但是如果修改为如下就不同了:
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27
28 int main(int argc, char *argv[]){
29 //
30 FILE *input = fdopen(1, "r");
31 FILE *output = fdopen(1, "w");
32 setbuf(input, NULL);
33 setbuf(output, NULL);
34 char c ;
35
36 fprintf(output, "Hello World");
37 sleep(10);
38 }
上面代码的区别在于:printf使用了stdin这个FILE对象(默认是line buffer), fprintf使用了指定的FILE对象。standard IO的缓存是通过修改FILE对象实现的。
read和write会不会缓存, 缓存机制是什么? 这与read, write操作的对象有很大的关系, 例如:
28 int main(int argc, char *argv[]){
29
30 while(1){
31 char c;
32 (void *)read(0, &c, 1);
33 (void *)write(1, &c, 1);
34 }
35 }
上面虽然使用了read, write, 还是用户输入还是行缓存的, 无法像vim一样交互操作。这时要想非行缓存, 需要操作到tty的缓存机制。 如下的一段python代码设置了tty的缓存方式:
1 #coding:utf-8
2 import os
3 import sys
4 import termios
5
6 STDIN_FILENO = sys.stdin.fileno()
7
8 old_attr = termios.tcgetattr(STDIN_FILENO)
9 new_attr = termios.tcgetattr(STDIN_FILENO)
10
11 new_attr[3] &= ~ (termios.ICANON | termios.ECHO)
12 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, new_attr)
13 try:
14 print '请使用vim的移动键'
15 while True:
16 c= os.read(STDIN_FILENO, 1)
17 if c == 'j':
18 print "下"
19 elif c == 'k':
20 print "上"
21 elif c == 'h':
22 print '左'
23 elif c == 'l':
24 print '右'
25 except KeyboardInterrupt, e:
26 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, old_attr)
回到ctrl_D的问题
在terminal IO里, 因为默认是使用缓存的, 赋于ctrl_D两种功能:
1. 相当于flush操作. 即时把输入的数据返回给read函数, 不用等待'\n'的出现。
2. 让tty返回0字节给read函数. 表示EOF。 在单独输入ctrl_D后产生这种效果
控制符
控制符都是tty驱动提供的一种方便功能, 有少量的控制符会产生signal的:
^Z和^C
还有少量的是无法修改的:
\r和\n
如下代码把“a“作为backspace功能:
1 #coding:utf-8
2 import os
3 import sys
4 import termios
5
6 STDIN_FILENO = sys.stdin.fileno()
7
8 old_attr = termios.tcgetattr(STDIN_FILENO)
9 new_attr = termios.tcgetattr(STDIN_FILENO)
10
11 new_attr[6][termios.VERASE] = 0x61
12 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, new_attr)
13 try:
14 print "请使用a键删除数据"
15 os.read(0,100)
16 except KeyboardInterrupt, e:
17 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, old_attr)
0. 阻塞的存在
1. glibc的section3手册和linux的section2有同名函数。
2. posix, ISO都有要求
3. terminal IO与其它IO有不同的表现
4. IO缓存的机制
5. 还有众多古老的名词....
EOF
EOF是什么? 什么时候才会产生? 还是和ctrl_c一样是signal ?
如下代码的运行結果是 -1
19 #include <stdio.h>
20
21 int
22 main(int argc, char *argv[])
23 {
24 printf("%d\n", EOF);
25 return 0;
26
27 }
表示EOF是 -1 ?
当某一次使用 ssize_t read(int fd, void *buf, size_t count); 函数从一个file descriptor中读数据时(count>0), 函数得到0个字节表示读到文件的尾部了. 这时read函数返回0.
可读端的pipe关闭后, 只读端pipe在读完后会产生EOF:
2 import os
3 import sys
4 import time
5
6 read_end, write_end = os.pipe()
7
8 pid = os.fork()
9 if pid < 0:
10 print "Error"
11 sys.exit(1)
12 if pid == 0:
13 # parent
14 os.close(write_end)
15 try_time = 1
16 # 因为无法得到child process会发多少数据, 只能使用死循环去读数据
17 while True:
18 print "%s time(s) call read" % try_time
19 content = os.read(read_end, 1)
20 if not content:
21 break
22 os.write(1, content)
23 try_time += 1
24 sys.exit(0)
25
26 else:
27 # child
28 os.close(read_end)
29 os.write(write_end, "#" * 100)
30 # 关了parent就能读到EOF
31 os.close(write_end)
32 sys.exit(0)
文件系统中的文件是有固定大小(某一状态), 但是在terminal IO里,是没有一个固定的尾部的, 需要输入者指定什么时候才是end-of-file, 所以, ctrl_D出现了. ctrl_D是一个特殊控制符。被tty的驱动处理(默认情况下用户程序不能从read函数得到, 除非要求tty不处理)
在了解ctrl_D前, 应该先要了解IO的缓存机制.
standard IO缓存 与 底层IO缓存
在此这前, 我对getchar这个函数不解, 其实就是不解如下的代码:
19 #include <stdio.h>
20
21 int main(int argc, char *argv[]){
22 char c ;
23 while(c = getchar() ){
24 printf("%c\n", c);
25 }
26 }
不要以为简单调用getchar函数可以实现vim这种交互.
当调用read去读stdin的数据时, 是行缓存的.上面的代码在第一次调用getchar时把一行的数据读到buffer里(回车键返回), 下次再调用getchar时会从buffer里取. buffer没有数据后再等待用户输入.
标准IO与系统底层IO这两套IO需要分开. 不然会出现事与愿违的情况, 如:
使用setbuf对FILE对象进行了设置后, 然后使用调用printf操作. 結果没有出现想要的设置效果。例如:
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27
28 int main(int argc, char *argv[]){
29 //
30 FILE *input = fdopen(1, "r");
31 FILE *output = fdopen(1, "w");
32 setbuf(input, NULL);
33 setbuf(output, NULL);
34 char c ;
35
36 printf("Hello World");
37 sleep(10);
38 }
上面的printf的内容是过了10秒后才打印的, 明显, setbuf没有起作用。 但是如果修改为如下就不同了:
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27
28 int main(int argc, char *argv[]){
29 //
30 FILE *input = fdopen(1, "r");
31 FILE *output = fdopen(1, "w");
32 setbuf(input, NULL);
33 setbuf(output, NULL);
34 char c ;
35
36 fprintf(output, "Hello World");
37 sleep(10);
38 }
上面代码的区别在于:printf使用了stdin这个FILE对象(默认是line buffer), fprintf使用了指定的FILE对象。standard IO的缓存是通过修改FILE对象实现的。
read和write会不会缓存, 缓存机制是什么? 这与read, write操作的对象有很大的关系, 例如:
28 int main(int argc, char *argv[]){
29
30 while(1){
31 char c;
32 (void *)read(0, &c, 1);
33 (void *)write(1, &c, 1);
34 }
35 }
上面虽然使用了read, write, 还是用户输入还是行缓存的, 无法像vim一样交互操作。这时要想非行缓存, 需要操作到tty的缓存机制。 如下的一段python代码设置了tty的缓存方式:
1 #coding:utf-8
2 import os
3 import sys
4 import termios
5
6 STDIN_FILENO = sys.stdin.fileno()
7
8 old_attr = termios.tcgetattr(STDIN_FILENO)
9 new_attr = termios.tcgetattr(STDIN_FILENO)
10
11 new_attr[3] &= ~ (termios.ICANON | termios.ECHO)
12 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, new_attr)
13 try:
14 print '请使用vim的移动键'
15 while True:
16 c= os.read(STDIN_FILENO, 1)
17 if c == 'j':
18 print "下"
19 elif c == 'k':
20 print "上"
21 elif c == 'h':
22 print '左'
23 elif c == 'l':
24 print '右'
25 except KeyboardInterrupt, e:
26 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, old_attr)
回到ctrl_D的问题
在terminal IO里, 因为默认是使用缓存的, 赋于ctrl_D两种功能:
1. 相当于flush操作. 即时把输入的数据返回给read函数, 不用等待'\n'的出现。
2. 让tty返回0字节给read函数. 表示EOF。 在单独输入ctrl_D后产生这种效果
控制符
控制符都是tty驱动提供的一种方便功能, 有少量的控制符会产生signal的:
^Z和^C
还有少量的是无法修改的:
\r和\n
如下代码把“a“作为backspace功能:
1 #coding:utf-8
2 import os
3 import sys
4 import termios
5
6 STDIN_FILENO = sys.stdin.fileno()
7
8 old_attr = termios.tcgetattr(STDIN_FILENO)
9 new_attr = termios.tcgetattr(STDIN_FILENO)
10
11 new_attr[6][termios.VERASE] = 0x61
12 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, new_attr)
13 try:
14 print "请使用a键删除数据"
15 os.read(0,100)
16 except KeyboardInterrupt, e:
17 termios.tcsetattr(STDIN_FILENO, termios.TCSADRAIN, old_attr)
Wednesday, June 23, 2010
无线网络配置
总是有一种怪感觉: 不能太依赖GUI程序。
在我的记忆中, 还是存在着一种场面:系统无法正常进入X而无法正常使用linux的痛苦记忆。总是感觉GUI是学习使用linux的拦路虎。
网络照样是CLI行先。之前我的router是配置成WEP的, 都是使用wireless-tools工具集可以很好处理。 但是慢慢地, 这种加密网络已经被淘汰了。 WEP逐渐出的时, WPA流行起来,同时linux也产生了新的一套wireless配置机制:nl80211. 这是为什么wireless-tools工具集无法使用WPA网络的原因
特别是在没网络,不能google的时候更是无奈。 对!这种“无奈”是我最不喜欢看到的! 我很讨厌这种感觉。
这个问题已经解决了, 不存在是否有google。也不存在是否有Networking-manager。 (可以直奔可爱的gentoo世界)
把配置copy出来, 按实现情况修改, 去掉不用的, psk使用wpa_passphrase得到。 一切都是没有问题的
所以一般情况下, 我都是CLI程序行先的。这也是防止出现我很不喜欢的感觉。
网络照样是CLI行先。之前我的router是配置成WEP的, 都是使用wireless-tools工具集可以很好处理。 但是慢慢地, 这种加密网络已经被淘汰了。 WEP逐渐出的时, WPA流行起来,同时linux也产生了新的一套wireless配置机制:nl80211. 这是为什么wireless-tools工具集无法使用WPA网络的原因
* 关于wireless-tools使用的WE: http://linuxwireless.org/en/developers/Documentation/Wireless-Extensions
其实这都是一次性的, 因为有脚本的存在。
我也是一个懒人~~~谁都不想每次都搞十几钟才上得了网。命令还是比较好办, 就麻烦的是配置文件, wpa_supplicant的配置文件也不是省油的。
特别是在没网络,不能google的时候更是无奈。 对!这种“无奈”是我最不喜欢看到的! 我很讨厌这种感觉。
相信解决的方法是一定会存在的~~~~
“就地出材”是一条出路, 即:不联网也可配置wpa_supplicant!
copy是方法, How ? 从wpa_supplicant的man里copy出可使用的配置文件来。
在man 5 wpa_supplicant里看到: Catch all example that allows more or less all configuration modes.
这个问题已经解决了, 不存在是否有google。也不存在是否有Networking-manager。 (可以直奔可爱的gentoo世界)
把配置copy出来, 按实现情况修改, 去掉不用的, psk使用wpa_passphrase得到。 一切都是没有问题的
* 如果这一步无法做到, 还是去使用GUI吧, 或者是思考一下问题出在哪里。
============= 华丽的分隔线 ===================
下面是N久在docs里存放的文字, 随便一起放出:
其实就是MAC的限制 + web登陆认证。
还是很管用的。 至少市场卖的路由没有针对这一系统的web登陆。
为了自己的机器可以上网。只需要满足上面的条件即可。
然后使用browser访问web认证即可。
下面是N久在docs里存放的文字, 随便一起放出:
计算机的网络是最常见的配置了。来到北京这边。朋友的宿舍里的网络和广东的不一样:
1. 一个宿舍只有几台计算机上网。
2. 可以上网的机器都被登记MAC地址。
3. 可以上网的机器都分有固定的IP, netmask, DNS, gateway
4. 需要web登陆认证方可使用网络。
5. WEP方式
其实就是MAC的限制 + web登陆认证。
还是很管用的。 至少市场卖的路由没有针对这一系统的web登陆。
为了自己的机器可以上网。只需要满足上面的条件即可。
针对于有线的情况:
ifconfig eth1 hw ether 00:1e:65:18:e2:a8
ifconfig eth1 10.3.52.132 netmask 255.255.255.0
route add default gw 10.3.52.1
然后使用browser访问web认证即可。
有线的倒很清楚怎么解决它。 无线呢? 也很简单
$ sudo route add default gw 10.3.52.1针对于无线的情况(是WEP网络):
$ sudo ifconfig wlan0 hw ether xxxxxxxx
$ sudo iwlist wlan0 scan
可以得到ssid名~~
$ sudo iwconfig wlan0 ssid 'who' key 'password'Monday, June 21, 2010
由setrlimit引发的学习
POSIX标准中有这样一个函数: sysconf(3). 自己写了小段代码:
19 #include <unistd.h>
20 #include <stdio.h>
21
22 int main(int argc, char *argv[]){
23 int fd_max_number = sysconf(_SC_OPEN_MAX);
24 printf("%d\n", fd_max_number);
25
26 }
使用strace可以知道它其实是调用了getrlimit(2),
什么limit? 全称为 resource limit. 这是kernel分给每个进程独立的一组数据。代表了进程可以使用的最大resource上限。具体有哪些, 可以见getrlimit(2)的manual
kernel也有一堆limit参数, 使用sysctl(2)来修改, kernel的limit应该被称为"limit of limits"。
下面的有关于文件描述符的limit:
* http://www.karakas-online.de/forum/viewtopic.php?t=9834
* 其中提到一点很有意义:file descriptor与open file
在了解setrlimit(2)配置file descriptor时, 有一个文件引起了我的高度注意:
/etc/security/limits.conf
疑问:
1. setrlimit是system call, 为什么会使用这样一个配置文件的?
2. limits.conf是pam_limits module的配置文件, 如果用户不加载此module时,kernel的setrlimit又是处理的?
不解的情况下, 在kernel的源代码堆里纠结时, 发现了一个常常会看到的一个词:SELinux
FAQ了一把, 得知SELinux是在kernel里加入复杂的access control。比如role-based access control
疑问又来了: Linux是一个可高度裁剪(scale)的系统, 如何做到去掉Linux Security Modules可以不影响现有的system call的呢?
这其中的机制比较吸引我。 google了一把, 得到一篇好文, 分享:
* http://www.ibm.com/developerworks/linux/library/l-selinux/
Wednesday, June 9, 2010
系统里的hostname
1. 修改host name需要reboot吗?
2. host name与/etc/hosts有什么关系呢?
3. gethostname为什么不受/etc/nsswitch.conf的配置?
这三个问题在不了解host name是什么的时候, 比较纠结.
是否要reboot这个问题是最直接让我产生dig这个host name的动力, 还有就是工作中, 碰到一台机器无法使用sudo命令, 于是花时间学习学习.
平时看hostname(3)时, 发现hostname(3)与/etc/nsswitch.conf扯在一起, 这使host name与DNS中的记录纠结在一起. 更是希望了解之间的关系
在找资料的过程中, 本人发现了一个很有意思的方法:
* Linux kernel与GNU分开.
什么意思呢? 分界是为了把不同时期的产物, 概念之类的分开. 比如: 当你认host name是kernel的一个变量时, 那么它就与DNS中的记录有明显的不同.
gethostname是system call, 它不是glibc的东西, 所以它与glibc中的DNS查询机制(/etc/nsswitch.conf)是扯不上关系的. gethostbyname, gethostbyaddr都是glibc的东西
就算没有glibc的存在, kernel中的host name照样存在!
按上面的方法, 已经可以很清楚地知道host name与/etc/hosts, /etc/nsswitch.conf是没有关系的.
linux kernel提供了实时修改kernel参数的方法, 是无需要reboot内核就可以生效的. 如sysctl(2), 也有CLI的sysctl(3). 也可以修改/proc/sys/kernel下的文件.
在实际中, GNU软件又常常会使用到host name!
在工作中碰到一个这样的问题: 每当运行sudo时shell就hang住!
它被block了吗?
于是使用strace一查, sudo是在等socket的IO. 发现这台机器的DNS請求是发不出去的
为什么sudo需要使用网络呢?
这其实就是程序期望得到FQDN格式的host name的結果.
得到FQDN格式的host name就使得host name与DNS查询纠结在一起.
通过学习hostname命令的代码, 可以得到hostname -f其实是等同于下面的代码
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
int main(int argc, char *argv[]){
char hostname[64];
if ( gethostname( hostname, sizeof(hostname) ) != 0){
perror("1");
}
struct hostent * host_struct;
if ( (host_struct = gethostbyname( hostname )) == NULL ){
perror("2");
}
printf("%s\n", host_struct->h_name);
}
可以得到这样的信息: 得到FQDN格式的host name, 是需要使用到
1. host name
2. DNS
这就与linux下DNS查询顺序策略有关系(/etc/nsswitch.conf)
python里有一段很明了的代码(来自socket.py):
def getfqdn(name=''):
"""Get fully qualified domain name from name.
An empty argument is interpreted as meaning the local host.
First the hostname returned by gethostbyaddr() is checked, then
possibly existing aliases. In case no FQDN is available, hostname
from gethostname() is returned.
"""
name = name.strip()
if not name or name == '0.0.0.0':
name = gethostname()
try:
hostname, aliases, ipaddrs = gethostbyaddr(name)
except error:
pass
else:
aliases.insert(0, hostname)
for name in aliases:
if '.' in name:
break
else:
name = hostname
return name
这样还可以解开一个疑问: 为什么/etc/hosts里常常会出现hostname和它的FQDN记录
增加这样的信息在这里, 查hostname的FQDN时就无须通过网络得到, 当然, 的确有需求的话, 也是可以的, 如果牛B的话, 就每台机器有一个全球唯一的域名也没有人说
2. host name与/etc/hosts有什么关系呢?
3. gethostname为什么不受/etc/nsswitch.conf的配置?
这三个问题在不了解host name是什么的时候, 比较纠结.
是否要reboot这个问题是最直接让我产生dig这个host name的动力, 还有就是工作中, 碰到一台机器无法使用sudo命令, 于是花时间学习学习.
平时看hostname(3)时, 发现hostname(3)与/etc/nsswitch.conf扯在一起, 这使host name与DNS中的记录纠结在一起. 更是希望了解之间的关系
在找资料的过程中, 本人发现了一个很有意思的方法:
* Linux kernel与GNU分开.
什么意思呢? 分界是为了把不同时期的产物, 概念之类的分开. 比如: 当你认host name是kernel的一个变量时, 那么它就与DNS中的记录有明显的不同.
gethostname是system call, 它不是glibc的东西, 所以它与glibc中的DNS查询机制(/etc/nsswitch.conf)是扯不上关系的. gethostbyname, gethostbyaddr都是glibc的东西
就算没有glibc的存在, kernel中的host name照样存在!
按上面的方法, 已经可以很清楚地知道host name与/etc/hosts, /etc/nsswitch.conf是没有关系的.
linux kernel提供了实时修改kernel参数的方法, 是无需要reboot内核就可以生效的. 如sysctl(2), 也有CLI的sysctl(3). 也可以修改/proc/sys/kernel下的文件.
在实际中, GNU软件又常常会使用到host name!
在工作中碰到一个这样的问题: 每当运行sudo时shell就hang住!
它被block了吗?
于是使用strace一查, sudo是在等socket的IO. 发现这台机器的DNS請求是发不出去的
为什么sudo需要使用网络呢?
这其实就是程序期望得到FQDN格式的host name的結果.
得到FQDN格式的host name就使得host name与DNS查询纠结在一起.
通过学习hostname命令的代码, 可以得到hostname -f其实是等同于下面的代码
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
int main(int argc, char *argv[]){
char hostname[64];
if ( gethostname( hostname, sizeof(hostname) ) != 0){
perror("1");
}
struct hostent * host_struct;
if ( (host_struct = gethostbyname( hostname )) == NULL ){
perror("2");
}
printf("%s\n", host_struct->h_name);
}
可以得到这样的信息: 得到FQDN格式的host name, 是需要使用到
1. host name
2. DNS
这就与linux下DNS查询顺序策略有关系(/etc/nsswitch.conf)
python里有一段很明了的代码(来自socket.py):
def getfqdn(name=''):
"""Get fully qualified domain name from name.
An empty argument is interpreted as meaning the local host.
First the hostname returned by gethostbyaddr() is checked, then
possibly existing aliases. In case no FQDN is available, hostname
from gethostname() is returned.
"""
name = name.strip()
if not name or name == '0.0.0.0':
name = gethostname()
try:
hostname, aliases, ipaddrs = gethostbyaddr(name)
except error:
pass
else:
aliases.insert(0, hostname)
for name in aliases:
if '.' in name:
break
else:
name = hostname
return name
这样还可以解开一个疑问: 为什么/etc/hosts里常常会出现hostname和它的FQDN记录
增加这样的信息在这里, 查hostname的FQDN时就无须通过网络得到, 当然, 的确有需求的话, 也是可以的, 如果牛B的话, 就每台机器有一个全球唯一的域名也没有人说
Subscribe to:
Posts (Atom)