Skip to content

新浪年会

公历的年初,农历的年底。

公司选择在这样的一个时候在这样一个地点来开这样一个年会:没有其它公司员工都有的年终,没有年底双薪,有的只是中奖面不到 1% 的抽奖。

本来以为所谓的年会,应该是一个“会”,也就是领导们讲讲话,大家鼓鼓掌,然后一些员工代表什么也发发言,大家继续鼓鼓掌。哪知道一开始,就吓了一跳:艳舞,惊艳全场。音响,灯光,烟雾,口哨,尖叫,看架势,整个一娱乐晚会。

带了相机,却没有拍到什么好的照片——虽然坐在所谓的 VIP 区域,却是vip的最后一排。想要看拍的好的照片,点击 这里 吧:(http://photo.sina.com.cn/list/photo_s.php?uid=1400314314&ctg_id=99798)

http://photo.sina.com.cn/list/photo_s.php?uid=1400314314&ctg_id=99798
http://photo.sina.com.cn/list/photo_s.php?uid=1151840394&ctg_id=100380
http://photo.sina.com.cn/list/photo_s.php?uid=1495295187&ctg_id=99867
http://photo.sina.com.cn/list/photo_s.php?uid=1400042283&ctg_id=100257
http://photo.sina.com.cn/list/photo_s.php?uid=1402618337&ctg_id=101469

新浪年会

公历的年初,农历的年底。

公司选择在这样的一个时候在这样一个地点来开这样一个年会:没有其它公司员工都有的年终,没有年底双薪,有的只是中奖面不到 1% 的抽奖。

本来以为所谓的年会,应该是一个“会”,也就是领导们讲讲话,大家鼓鼓掌,然后一些员工代表什么也发发言,大家继续鼓鼓掌。哪知道一开始,就吓了一跳:艳舞,惊艳全场。音响,灯光,烟雾,口哨,尖叫,看架势,整个一娱乐晚会。

带了相机,却没有拍到什么好的照片——虽然坐在所谓的 VIP 区域,却是vip的最后一排。想要看拍的好的照片,点击 这里 吧:(http://photo.sina.com.cn/list/photo_s.php?uid=1400314314&ctg_id=99798)

http://photo.sina.com.cn/list/photo_s.php?uid=1400314314&ctg_id=99798
http://photo.sina.com.cn/list/photo_s.php?uid=1151840394&ctg_id=100380
http://photo.sina.com.cn/list/photo_s.php?uid=1495295187&ctg_id=99867
http://photo.sina.com.cn/list/photo_s.php?uid=1400042283&ctg_id=100257
http://photo.sina.com.cn/list/photo_s.php?uid=1402618337&ctg_id=101469

密码保护:又是一年春来到

这是一篇受密码保护的文章。您需要提供访问密码:


密码保护:被保护: 艰难的生活

这是一篇受密码保护的文章。您需要提供访问密码:


TCMalloc:线程缓存的Malloc

作者:Sanjay Ghemawat, Paul Menage

原文:http://goog-perftools.sourceforge.net/doc/tcmalloc.html

翻译:ShiningRay (http://shiningray.cn/tcmalloc-thread-caching-malloc.html)

动机

TCMalloc要比glibc 2.3的malloc(可以从一个叫作ptmalloc2的独立库获得)和其他我测试过的malloc都快。ptmalloc在一台2.8GHz的P4机器上(对于小对象)执行一次malloc及free大约需要300纳秒。而TCMalloc的版本同样的操作大约只需要50纳秒。malloc版本的速度是至关重要的,因为如果malloc不够快,应用程序的作者就很有可能在malloc之上写一个自己的自由列表。这就可能导致额外的代码复杂度,以及更多的内存占用――除非作者本身非常仔细地划分自由列表的大小并经常从自由列表中清除空闲的对象。

TCMalloc也减少了多线程程序中的锁争用情况。对于小对象,几乎已经达到了零争用。对于大对象,TCMalloc尝试使用粒度较好和有效的自旋锁。ptmalloc 同样是通过使用每线程各自的场地来减少锁争用,但是ptmalloc2使用每线程场地有一个很大的问题。在ptmalloc2中,内存可能会从一个场地移动到另一个。这有可能导致大量空间被浪费。例如,在一个Google的应用中,第一阶段可能会为其URL标准化的数据结构分配大约300MB内存。当第一阶段结束后,第二阶段将从同样的地址空间开始。如果第二个阶段被安排到了一个与第一阶段什?用的场地不同的场地,这个阶段不会复用任何第一阶段留下的的内存,并会给地址空间添加另外一个300MB。类似的内存爆炸问题也可以在其他的应用中看到。

TCMalloc的另一个好处是小对象的空间最优表现形式。例如,分配N个8字节对象可能要使用大约8N * 1.01字节的空间。即,多用百分之一的空间。而ptmalloc2中每个对象都使用了一个四字节的头,(我认为)并将最终的尺寸规整为8字节的倍数,最后使用了16N字节。

Continue reading ›

布什的陷阱

转载自: http://tech.idv2.com/2008/01/09/bash-pitfalls/

感谢fcicq,他的new 30 days系列为我们带来了不少好文章。

今天想分析的是这篇Bash Pitfalls, 介绍了一些bash编程中的经典错误。fcicq说可能不适合初学者,而我认为, 正是bash编程的初学者才应该好好阅读一下这篇文章。

下面就逐个分析一下这篇文章中提到的错误。不是完全的翻译,有些没用的话就略过了, 有些地方则加了些注释。

 

1. for i in `ls *.mp3`

常见的错误写法:

for i in `ls *.mp3`; do     # Wrong!

为什么错误呢?因为for…in语句是按照空白来分词的,包含空格的文件名会被拆成多个词。 如遇到 01 – Don’t Eat the Yellow Snow.mp3 时,i的值会依次取 01,-,Don’t,等等。

用双引号也不行,它会将ls *.mp3的全部结果当成一个词来处理。

for i in "`ls *.mp3`"; do   # Wrong!

正确的写法是

for i in *.mp3; do

2. cp $file $target

这句话基本上正确,但同样有空格分词的问题。所以应当用双引号:

cp "$file" "$target"

但是如果凑巧文件名以 – 开头,这个文件名会被 cp 当作命令行选项来处理,依旧很头疼。可以试试下面这个。

cp -- "$file" "$target"

运气差点的再碰上一个不支持 — 选项的系统,那只能用下面的方法了:使每个变量都以目录开头。

for i in ./*.mp3; do

  cp "$i" /target

  ...

3. [ $foo = "bar" ]

当$foo为空时,上面的命令就变成了

[ = "bar" ]

类似地,当$foo包含空格时:

[ multiple words here = "bar" ]

两者都会出错。所以应当用双引号将变量括起来:

[ "$foo" = bar ]      # 几乎完美了。

但是!当$foo以 – 开头时依然会有问题。 在较新的bash中你可以用下面的方法来代替,[[ 关键字能正确处理空白、空格、带横线等问题。

[[ $foo = bar ]]      # 正确

旧版本bash中可以用这个技巧(虽然不好理解):

[ x"$foo" = xbar ]    # 正确

或者干脆把变量放在右边,因为 [ 命令的等号右边即使是空白或是横线开头,依然能正常工作。 (Java编程风格中也有类似的做法,虽然目的不一样。)

[ bar = "$foo" ]      # 正确

4. cd `dirname "$f"`

同样也存在空格问题。那么加上引号吧。

cd "`dirname "$f"`"

问题来了,是不是写错了?由于双引号的嵌套,你会认为`dirname 是第一个字符串,`是第二个字符串。 错了,那是C语言。在bash中,命令替换(反引号``中的内容)里面的双引号会被正确地匹配到一起, 不用特意去转义。

$()语法也相同,如下面的写法是正确的。

cd "$(dirname "$f")"

5. [ "$foo" = bar && "$bar" = foo ]

[ 中不能使用 && 符号!因为 [ 的实质是 test 命令,&& 会把这一行分成两个命令的。应该用以下的写法。

[ bar = "$foo" -a foo = "$bar" ]       # Right!

[ bar = "$foo" ] && [ foo = "$bar" ]   # Also right!

[[ $foo = bar && $bar = foo ]]         # Also right!

6. [[ $foo > 7 ]]

很可惜 [[ 只适用于字符串,不能做数字比较。数字比较应当这样写:

(( $foo > 7 ))

或者用经典的写法:

[ $foo -gt 7 ]

但上述使用 -gt 的写法有个问题,那就是当 $foo 不是数字时就会出错。你必须做好类型检验。

这样写也行。

[[ $foo -gt 7 ]]

7. grep foo bar | while read line; do ((count++) ); done

由于格式问题,标题中我多加了一个空格。实际的代码应该是这样的:

grep foo bar | while read line; do ((count++)); done         # 错误!

这行代码数出bar文件中包含foo的行数,虽然很麻烦(等同于grep -c foo bar或者 grep foo bar | wc -l)。 乍一看没有问题,但执行之后count变量却没有值。因为管道中的每个命令都放到一个新的子shell中执行, 所以子shell中定义的count变量无法传递出来。

8. if [grep foo myfile]

初学者常犯的错误,就是将 if 语句后面的 [ 当作if语法的一部分。实际上它是一个命令,相当于 test 命令, 而不是 if 语法。这一点C程序员特别应当注意。

if 会将 if 到 then 之间的所有命令的返回值当作判断条件。因此上面的语句应当写成

if grep foo myfile > /dev/null; then

9. if [bar="$foo"]

同样,[ 是个命令,不是 if 语句的一部分,所以要注意空格。

if [ bar = "$foo" ]

10. if [ [ a = b ] && [ c = d ] ]

同样的问题,[ 不是 if 语句的一部分,当然也不是改变逻辑判断的括号。它是一个命令。可能C程序员比较容易犯这个错误?

if [ a = b ] && [ c = d ]        # 正确

11. cat file | sed s/foo/bar/ > file

不能在同一条管道操作中同时读写一个文件。根据管道的实现方式,file要么被截断成0字节,要么会无限增长直到填满整个硬盘。 如果想改变原文件的内容,只能先将输出写到临时文件中再用mv命令。

sed 's/foo/bar/g' file > tmpfile && mv tmpfile file

12. echo $foo

这句话还有什么错误码?一般来说是正确的,但下面的例子就有问题了。

MSG="Please enter a file name of the form *.zip"

echo $MSG         # 错误!

如果恰巧当前目录下有zip文件,就会显示成

Please enter a file name of the form freenfss.zip lw35nfss.zip

所以即使是echo也别忘记给变量加引号。

13. $foo=bar

变量赋值时无需加 $ 符号——这不是Perl或PHP。

14. foo = bar

变量赋值时等号两侧不能加空格——这不是C语言。

15. echo <<EOF

here document是个好东西,它可以输出成段的文字而不用加引号也不用考虑换行符的处理问题。 不过here document输出时应当使用cat而不是echo。

# This is wrong:

echo <<EOF

Hello world

EOF# This is right:

cat <<EOF

Hello world

EOF

16. su -c 'some command'

原文的意思是,这条基本上正确,但使用者的目的是要将 -c 'some command' 传给shell。 而恰好 su 有个 -c 参数,所以su 只会将 'some command' 传给shell。所以应该这么写:

su root -c 'some command'

但是在我的平台上,man su 的结果中关于 -c 的解释为

-c, --commmand=COMMAND

            pass a single COMMAND to the shell with -c

也就是说,-c 'some command' 同样会将 -c 'some command' 这样一个字符串传递给shell, 和这条就不符合了。不管怎样,先将这一条写在这里吧。

17. cd /foo; bar

cd有可能会出错,出错后 bar 命令就会在你预想不到的目录里执行了。所以一定要记得判断cd的返回值。

cd /foo && bar

如果你要根据cd的返回值执行多条命令,可以用 ||。

cd /foo || exit 1;

bar

baz

关于目录的一点题外话,假设你要在shell程序中频繁变换工作目录,如下面的代码:

find ... -type d | while read subdir; do

  cd "$subdir" && whatever && ... && cd -

done

不如这样写:

find ... -type d | while read subdir; do

  (cd "$subdir" && whatever && ...)

done

括号会强制启动一个子shell,这样在这个子shell中改变工作目录不会影响父shell(执行这个脚本的shell), 就可以省掉cd - 的麻烦。

你也可以灵活运用 pushd、popd、dirs 等命令来控制工作目录。

18. [ bar == "$foo" ]

[ 命令中不能用 ==,应当写成

[ bar = "$foo" ] && echo yes

[[ bar == $foo ]] && echo yes

19. for i in {1..10}; do ./something &; done

& 后面不应该再放 ; ,因为 & 已经起到了语句分隔符的作用,无需再用;。

for i in {1..10}; do ./something & done

20. cmd1 && cmd2 || cmd3

有人喜欢用这种格式来代替 if...then...else 结构,但其实并不完全一样。如果cmd2返回一个非真值,那么cmd3则会被执行。 所以还是老老实实地用 if cmd1; then cmd2; else cmd3 为好。

21. UTF-8的BOM(Byte-Order Marks)问题

UTF-8编码可以在文件开头用几个字节来表示编码的字节顺序,这几个字节称为BOM。但Unix格式的UTF-8编码不需要BOM。 多余的BOM会影响shell解析,特别是开头的 #!/bin/sh 之类的指令将会无法识别。

MS-DOS格式的换行符(CRLF)也存在同样的问题。如果你将shell程序保存成DOS格式,脚本就无法执行了。

$ ./dos

-bash: ./dos: /bin/sh^M: bad interpreter: No such file or directory

22. echo "Hello World!"

交互执行这条命令会产生以下的错误:

-bash: !": event not found

因为 !" 会被当作命令行历史替换的符号来处理。不过在shell脚本中没有这样的问题。

不幸的是,你无法使用转义符来转义!:

$ echo "hi\!"

hi\!

解决方案之一,使用单引号,即

$ echo 'Hello, world!'

如果你必须使用双引号,可以试试通过 set +H 来取消命令行历史替换。

set +H

echo "Hello, world!"

23. for arg in $*

$*表示所有命令行参数,所以你可能想这样写来逐个处理参数,但参数中包含空格时就会失败。如:

#!/bin/bash

# Incorrect version

for x in $*; do

  echo "parameter: '$x'"

done$ ./myscript 'arg 1' arg2 arg3

parameter: 'arg'

parameter: '1'

parameter: 'arg2'

parameter: 'arg3'

正确的方法是使用 "$@"。

#!/bin/bash

# Correct version

for x in "$@"; do

  echo "parameter: '$x'"

done$ ./myscript 'arg 1' arg2 arg3

parameter: 'arg 1'

parameter: 'arg2'

parameter: 'arg3'

在 bash 的手册中对 $* 和 $@ 的说明如下:

*    Expands to the positional parameters, starting from one.

     When the expansion occurs within double quotes, it

     expands to a single word with the value of each parameter

     separated by the first character of the IFS special variable.

     That is, "$*" is equivalent to "$1c$2c...",

@    Expands to the positional parameters, starting from one.

     When the expansion occurs within double quotes, each

     parameter expands to a separate word.  That  is,  "$@"

     is equivalent to "$1" "$2" ...

可见,不加引号时 $* 和 $@ 是相同的,但"$*" 会被扩展成一个字符串,而 "$@" 会 被扩展成每一个参数。

24. function foo()

在bash中没有问题,但其他shell中有可能出错。不要把 function 和括号一起使用。 最为保险的做法是使用括号,即

foo() {

  ...

}

php基础测试

如何改进以下的这行php代码?这段代码可以被用来测试php工程师应聘者。

< ?
echo(“Search results for query: ” .$_GET['query'] . “.”);
? >

这段代码非常适合用来测试一个php开发人员是否合格。因为这段代码并没有要求太多记忆上的东西(例如函数的记忆),但是对安全,性能,兼容性上都做了考察。

Continue reading ›

MySQL的Query Cache

本文按署名·非商业用途·保持一致授权
作者: surfchen@gmail.com 

原理

QueryCache(下面简称QC)是根据SQL语句来cache的。一个SQL查询如果以select开头,那么MySQL服务器将尝试对其使用 QC。每个Cache都是以SQL文本作为key来存的。在应用QC之前,SQL文本不会被作任何处理。也就是说,两个SQL语句,只要相差哪怕是一个字 符(例如大小写不一样;多一个空格等),那么这两个SQL将使用不同的一个CACHE。不过SQL文本有可能会被客户端做一些处理。例如在官方的命令行客户端里,在发送SQL给服务器之前,会做如下处理:

  • 过滤所有注释
  • 去掉SQL文本前后的空格,TAB等字符。注意,是文本前面和后面的。中间的不会被去掉。

下面的三条SQL里,因为SELECT大小写的关系,最后一条和其他两条在QC里肯定是用的不一样的存储位置。而第一条和第二条,区别在于后者有个 注释,在不同客户端,会有不一样的结果。所以,保险起见,请尽量不要使用动态的注释。在PHP的mysql扩展里,SQL的注释是不会被去掉的。也就是三 条SQL会被存储在三个不同的缓存里,虽然它们的结果都是一样的。

select * FROM people where name='surfchen';
select * FROM people where /*hey~*/name='surfchen';
SELECT * FROM people where name='surfchen';

目前只有select语句会被cache,其他类似show,use的语句则不会被cache。

因为QC是如此前端,如此简单的一个缓存系统,所以如果一个表被更新,那么和这个表相关的SQL的所有QC都会被失效。假设一个联合查询里涉及到了表A和表B,如果表A或者表B的其中一个被更新(update或者delete),这个查询的QC将会失效。

也就是说,如果一个表被频繁更新,那么就要考虑清楚究竟是否应该对相关的一些SQL进行QC了。一个被频繁更新的表如果被应用了QC,可能会加重数 据库的负担,而不是减轻负担。我一般的做法是默认打开QC,而对一些涉及频繁更新的表的SQL语句加上SQL_NO_CACHE关键词来对其禁用 CACHE。这样可以尽可能避免不必要的内存操作,尽可能保持内存的连续性。

那些查询很分散的SQL语句,也不应该使用QC。例如用来查询用户和密码的语句——“select pass from user where name=’surfchen’”。这样的语句,在一个系统里,很有可能只在一个用户登陆的时候被使用。每个用户的登陆所用到的查询,都是不一样的SQL 文本,QC在这里就几乎不起作用了,因为缓存的数据几乎是不会被用到的,它们只会在内存里占地方。

存储块

在本节里“存储块”和“block”是同一个意思QC缓存一个查询结果的时 候,一般情况下不是一次性地分配足够多的内存来缓存结果的。而是在查询结果获得的过程中,逐块存储。当一个存储块被填满之后,一个新的存储块将会被创建, 并分配内存(allocate)。单个存储块的内存分配大小通过query_cache_min_res_unit参数控制,默认为4KB。最后一个存储 块,如果不能被全部利用,那么没使用的内存将会被释放。如果被缓存的结果很大,那么会可能会导致分配内存操作太频繁,系统系能也随之下降;而如果被缓存的 结果都很小,那么可能会导致内存碎片过多,这些碎片如果太小,就很有可能不能再被分配使用。

除了查询结果需要存储块之外,每个SQL文本也需要一个存储块,而涉及到的表也需要一个存储块(表的存储块是所有线程共享的,每个表只需要一个存储 块)。存储块总数量=查询结果数量*2+涉及的数据库表数量。也就是说,第一个缓存生成的时候,至少需要三个存储块:表信息存储块,SQL文本存储块,查 询结果存储块。而第二个查询如果用的是同一个表,那么最少只需要两个存储块:SQL文本存储块,查询结果存储块。

通过观察Qcache_queries_in_cache和Qcache_total_blocks可以知道平均每个缓存结果占用的存储块。它们的 比例如果接近1:2,则说明当前的query_cache_min_res_unit参数已经足够大了。如果Qcache_total_blocks比 Qcache_queries_in_cache多很多,则需要增加query_cache_min_res_unit的大小。

Qcache_queries_in_cache*query_cache_min_res_unit(sql文本和表信息所在的block占用的 内存很小,可以忽略)如果远远大于query_cache_size-Qcache_free_memory,那么可以尝试减小 query_cache_min_res_unit的值。

调整大小

如果Qcache_lowmem_prunes增长迅速,意味着很多缓存因为内存不够而被释放,而不是因为相关表被更新。尝试加大query_cache_size,尽量使Qcache_lowmem_prunes零增长。

启动参数

show variables like ‘query_cache%’可以看到这些信息。

query_cache_limit:如果单个查询结果大于这个值,则不Cache
query_cache_size: 分配给QC的内存。如果设为0,则相当于禁用QC。要注意QC必须使用大约40KB来存储它的结构,如果设定小于40KB,则相当于禁用QC。QC存储的 最小单位是1024 byte,所以如果你设定了一个不是1024的倍数的值,这个值会被四舍五入到最接近当前值的等于1024的倍数的值。
query_cache_type:0 完全禁止QC,不受SQL语句控制(另外可能要注意的是,即使这里禁用,上面一个参数所设定的内存大小还是会被分配);1启用QC,可以在SQL语句使用 SQL_NO_CACHE禁用;2可以在SQL语句使用SQL_CACHE启用。
query_cache_min_res_unit:每次给QC结果分配内存的大小

状态

show status like ‘Qcache%’可以看到这些信息。

Qcache_free_blocks: 当一个表被更新之后,和它相关的cache blocks将被free。但是这个block依然可能存在队列中,除非是在队列的尾部。这些blocks将会被统计到这个值来。可以用FLUSH QUERY CACHE语句来清空free blocks。
Qcache_free_memory:可用内存,如果很小,考虑增加query_cache_size
Qcache_hits:自mysql进程启动起,cache的命中数量
Qcache_inserts:自mysql进程启动起,被增加进QC的数量
Qcache_lowmem_prunes:由于内存过少而导致QC被删除的条数。加大query_cache_size,尽可能保持这个值0增长。
Qcache_not_cached:自mysql进程启动起,没有被cache的只读查询数量(包括select,show,use,desc等)
Qcache_queries_in_cache:当前被cache的SQL数量
Qcache_total_blocks: 在QC中的blocks数。一个query可能被多个blocks存储,而这几个blocks中的最后一个,未用满的内存将会被释放掉。例如一个QC结果 要占6KB内存,如果query_cache_min_res_unit是4KB,则最后将会生成3个blocks,第一个block用来存储sql语句 文本,这个不会被统计到query+cache_size里,第二个block为4KB,第三个block为2KB(先allocate4KB,然后释放 多余的2KB)。每个表,当第一个和它有关的SQL查询被CACHE的时候,会使用一个block来存储表信息。也就是说,block会被用在三处地方: 表信息,SQL文本,查询结果。

转:2008年Linux 12个热点提示

阅读、练习下面的指示,舒适的使用Linux;

1. 尽量不要使用命令Ctrl+D结束会话或关闭终端D

   * set -o 忽略错误激活 Ctrl+D
* set +o 忽略错误禁用 Ctrl+D

2. 别名 — 我们给一个命令引入别名,shell 会用这个值重编码它。

3. 最近高频使用命令 —在控制台执行以下指令:

history|awk ‘{print $2}’|awk ‘BEGIN {FS=”|”} {print $1}’|sort|uniq -c|sort -rn|head -10

4. 杀死一个确定程序的所有进程 。

打开终端输入:ps aux c。如果你要杀死的程序比如是 Firefox,命令将会是这样: ps aux c | grep firefox ,然后kill -9。下一次你运行 ps aux c | grep firefox,这个程序再也不会出现了。

5. 获取基本系统信息

有些命令可以用来确定系统的基本信息,像内核版本、软件信息还有其他方面的东西。下面的命令当执行时立即显示输出。

$ cat /proc/version = “它返回一条完整的信息串”
$ uname -a = “显示系统所有信息还有系统日期和时间”

6. 使用日历

通过下面的命令你可以在不同版本的Linux上获得不同视图和显示的日历。

cal -3 = “简单显示日历”
cal 1 2008 = “此命令显示一年中特定月份的日历”
date -d fri = “显示本周或下周星期五的日期”
date –date=’25 Dec’ +%A = “告诉你今年圣诞节是星期几”

7. 磁盘空间

拥有充足和优化的磁盘空间是系统性能良好的重要方面。对Linux来说,这里有优化存储空间和显示硬盘空间的方法。

df -h = “此命令显示空余硬盘空间”
fdisk -l = “和Windows中显示硬盘分区相似”
ls -lSr = “显示所有文件,最大的在最后”
du -s * | sort -k1,1rn | head = “显示当然目录占用空间排名”

8. 集合操作

Linux下你可以快速操作文件。试试下面的命令,它对你操作文件会有很大的帮助。

LANG=C sort file1 file2 | uniq” = “合并不排序文件”
LANG=C sort file1 file2 | uniq -d = “截取排序文件”
LANG=C comm file1 file2 | sed ‘s/^t*//’ = “合并排序文件”
LANG=C comm -3 file1 file2 | sed ‘s/^t*// = “对称排序文件的不现部分”

9. 文本操作 

文本操作是工作另一个重要的方面。让我看看Linux里的一些命令。

sed -n ‘s/.*.*/1/ip;T;q’ = “从一个HTML页面提取标题”
sed -n ’10,20p;20q’ = “显示10到20行”
sed ‘:a; /$/N; s///; ta’ = “连接相邻行”
sed ‘s/[ t]*$//’ = “移除行尾空白”
sed ‘s/string1/string2/g’ = “替换string1为string2″

10. 搜索文件 

在Linux平台下搜索任何东西更快的方法。

alias ll=’ls -l –color=auto’page” = “快速列出目录”
ls -lrt = “按日期排列文件”
find -name ‘*.[ch]‘ | xargs grep -E ‘expr’ =”在当前目录及以下搜索’expr’ ”
find -type f ! -perm -444 = “找出不是所有人可读的文件”
locate -r ‘file[^/]*.txt’ = “按文件名搜索缓存索引”

11. 僵死窗口

有时候你会遇到僵死的窗口,有两种方法处理这种情况而不必关机或重启。第一,你可以试一试传统的快捷键Ctrl + Alt + Backspace。

另一个方法比前一个更复杂但是更有效。按Ctrl + Alt + F2 进入虚拟控制台。然后用你的用户名、密码登陆,输入以下命令:

ps -ax | grep startx

执行这条命令会给你系统Xserver的PID.然后用下面的命令杀死它

kill -9 PID_Number

如果你想回到每一个控制台,只要按下Alt + F1。

12. 远程操作 

通过“rexec”服务 你可以远程操作,当你在一个网络环境下工作时这非常有用。使用此服务的用户必须通过用户名和密码验证。

MYSQL 常用函数备查

一.             控制流程函数

1CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result …] [ELSE result] END CASE WHEN [condition] THEN result [WHEN [condition] THEN result …] [ELSE result] END

该语句用于在不同情况时,执行不同的语句,实例如下:

Eg1. SELECT CASE WHEN 1>0 THEN ‘true’ ELSE ‘false’ END;

输出:true

Eg2. SELECT CASE BINARY ‘B’ WHEN ‘a’ THEN 1 WHEN ‘b’ THEN 2 END;

输出:NULL

2IF(expr1,expr2,expr3)

如果expr1返回true,则该表达式返回expr2,否则返回expr3

Eg1. SELECT IF(1<2,’yes ‘,’no’);

输出:‘yes ‘

Eg2. SELECT IF(STRCMP(‘test’,'test1′),’no’,'yes’);

上例中STRCMP(expr1, expr2)这个函数在expr1小于expr2时,返回-1,相等时返回0,其余的情况返回1,在上例中返回-1,因此上例的输出为:‘yes’

3IFNULL(expr1,expr2)

该函数在expr1NULL时,返回expr2,否则,返回expr1

Eg1. SELECT IFNULL(1,0);

输出:1

Eg2. SELECT IFNULL(NULL,10);

输出:10

4NULLIF(expr1,expr2)

如果expr1=expr2,则返回NULL,否则,返回expr1

Eg1. SELECT NULLIF(1,1);

输出:NULL

Eg2. SELECT NULLIF(3,4);

输出:3

二.             字符串函数

1.       ASCII(str)

返回值为字符串str 的最左字符的数值。假如str为空字符串,则返回值为 0 。假如str NULL,则返回值为 NULL ASCII()用于带有从 0255的数值的字符。

Eg1. SELECT ASCII(’2′);

输出:50

Eg2. SELECT ASCII(‘de’);

输出:100

2.       CONCAT(str1,str2,…) 

返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。或许有一个或多个参数。

Eg1. SELECT CONCAT(‘Hello’, ‘,’, ‘阿蜜果‘);

输出:‘Hello, 阿蜜果

Eg2. SELECT CONCAT(‘Hello’, NULL, ‘阿蜜果‘);

输出:NULL

3.       CONCAT_WS(separator,str1,str2,…)

CONCAT_WS() 代表 CONCAT With Separator ,是CONCAT()的特殊形式。   第一个参数是其它参数的分隔符。分隔符的位置放在要连接的两个字符串之间。分隔符可以是一个字符串,也可以是其它参数。如果分隔符为 NULL,则结果为 NULL。函数会忽略任何分隔符参数后的NULL值。

Eg1. SELECT CONCAT_WS(‘,’, ‘Hello’, ‘阿蜜果‘);

输出:‘Hello, 阿蜜果

Eg. SELECT CONCAT_WS(‘,’, ‘Hello’, NULL, ‘阿蜜果‘);

输出:‘Hello, 阿蜜果

4.       INSERT(str,pos,len,newstr)

返回字符串 str, 其子字符串起始于 pos位置和长期被字符串 newstr取代的len字符。 如果pos超过字符串长度,则返回值为原始字符串。 假如len的长度大于其它字符串的长度,则从位置pos开始替换。若任何一个参数为null,则返回值为NULL

Eg1. SELECT INSERT(‘hello,Amigo’, 7, 5, ‘Locus’);

输出:hello,Locus

5.       INTER(str, substr)

返回字符串 str中子字符串的第一个出现位置。

Eg1. SELECT INSTR(‘hello,Amigo’, ‘Amigo’);

输出:7

6.       LENGTH(str)

返回值为字符串str的长度,单位为字节。一个多字节字符算作多字节。

Eg1. SELECT LENGTH(‘Amigo’);

输出:5

7.       LOWER(str)

返回字符串 str以及所有根据最新的字符集映射表变为小写字母的字符。

Eg1. SELECT LOWER(‘AMIGO’);

UPPER(str)函数的用法与此类似,在此不再赘述。不过它是将字符串转换为大写的。

输出:amigo

8.       LPAD(str, len, padstr)

返回字符串 str, 其左边由字符串padstr 填补到len字符长度。假如str 的长度大于len, 则返回值被缩短至len字符。

Eg1. SELECT LPAD(‘hi’,4,’!!’);

输出:‘!!hi’

Eg2. SELECT LPAD(‘hi’,1,’!!’);

输出:‘h’

RPAD(…)函数用法与此类似,在此不再赘述。

9.       REPEAT(str,count)

返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count count <= 0,则返回一个空字符串。若strcount NULL,则返回NULL

Eg1. SELECT REPEAT(‘Amigo’, 2);

输出:‘AmigoAmigo’

10.   SUBSTRING(str,pos), SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)

       不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。

Eg1. SELECT SUBSTRING(‘hello,Amigo’,6);

输出:Amigo

Eg2. SELECT SUBSTRING(‘hello,Amigo’, 6, 4);

输出:Amig

三.             数值函数

1.       ABS(X)

返回X的绝对值。

Eg1. SELECT ABS(-5);

输出:5

2.       FLOOR(X)

返回不大于X的最大整数值

Eg1. SELECT FLOOR(2.56);

输出:2

Eg2. SELECT FLOOR(-2.56)

输出:-3

3.       MOD(N,M) , N % M N MOD M

模操作。返回N M除后的余数。

Eg1. SELECT MOD(237, 10);

输出:7

Eg2. SELECT 237 % 10;

输出:7

Eg3. SELECT 237 MOD 10;

输出:7

4.       POW(X, Y)POWER(X, Y)

返回XY乘方的结果值。

Eg1. SELECT POW(2, 3);

输出:8

Eg2. SELECT POWER(2, 4)

输出:16

5.       RAND()RAND(N)

返回一个随机浮点值 v,范围在 0 1 之间 (, 其范围为 0 ≤ v ≤ 1.0)。若已指定一个整数参数 N,则它被用作种子值,用来产生重复序列。

Eg1.  SELECT RAND(20);

输出:0.15888261251047

Eg2. SELECT RAND();

输出:0.9233482386203

若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1))。例如, 若要在7 12 的范围(包括712)内得到一个随机整数, 可使用以下语句:

SELECT FLOOR(7 + (RAND() * 6));

6.       ROUND(X)ROUND(X,D)

返回参数X, 其值接近于最近似的整数。在有两个参数的情况下,返回 X ,其值保留到小数点后D位,而第D位的保留方式为四舍五入。若要接保留X值小数点左边的D 位,可将 D 设为负值。

Eg1. SELECT ROUND(-1.23);

输出:-1

Eg2. SELECT ROUND(2.56);

输出:3

7.       SQRT(X)

      返回非负数X的二次方根,如XNULL时,返回NULL

Eg1. SELECT SQRT(4);

输出:2

Eg2. SELECT SQRT(-4);

输出:NULL

四.             日期和时间函数

1. ADDDATE(date,INTERVAL expr type)ADDDATE(expr,days)

       当被第二个参数的INTERVAL格式激活后, ADDDATE()就是DATE_ADD()的同义词。相关函数SUBDATE()则是DATE_SUB()的同义词。

Eg1. SELECT DATE_ADD(’1998-01-02′, INTERVAL 31 DAY);

输出:’1998-02-02′

Eg2. SELECT ADDDATE(’1998-01-02′, INTERVAL 31 DAY);

输出:’1998-02-02′

2. CURDATE()

将当前日期按照‘YYYY-MM-DD’ YYYYMMDD 格式的值返回,具体格式根据函数用在字符串或是数字语境中而定。

Eg1. SELECT CURDATE();

输出:’2008-01-01′

Eg2. SELECT CURDATE() + 0;

输出:20080101

3. CURTIME()

将当前时间以‘HH:MM:SS’ HHMMSS 的格式返回, 具体格式根据函数用在字符串或是数字语境中而定。

Eg1. SELECT CURTIME();

输出:’15:15:26′

4. DATE(expr)

提取日期或时间日期表达式expr中的日期部分。

Eg1. SELECT DATE(’2007-12-31 23:59:59′);

输出:’2007-12-31′

5. DATEDIFF(expr, expr2)

DATEDIFF() 返回起始时间 expr和结束时间expr2之间的天数。Exprexpr2为日期或 date-and-time 表达式。计算中只用到这些值的日期部分。

Eg1. SELECT DATEDIFF(’1997-12-31 23:59:59′,’1997-12-30′);

输出:1

Eg2. SELECT DATEDIFF(’1997-11-30 23:59:59′,’1997-12-31′);

输出:-31

6. DAYOFMONTH(date)

返回date 对应的该月日期,范围是从 131

Eg1. SELECT DAYOFMONTH(’2008-01-05′);

输出:5

7. MONTH (time)

返回date对应的月份,范围时从 1 12

Eg1. SELECT MONTH(’2007-01-05′);

输出:1

8. HOUR(time)

       返回time 对应的小时数。对于日时值的返回值范围是从 0 23

Eg1. SELECT HOUR(’11:47:1′);

9. MINUTE(time)

返回 time 对应的分钟数,范围是从 0 59

Eg1. SELECT MINUTE(’2007-01-05 11:51:23);

输出:51

10. SECOND(time)

返回time对应的秒数, 范围是从 059

Eg1. SELECT SECOND(’11:56:43);

输出:43

11. LAST_DAY(date)

获取一个日期或日期时间值,返回该月最后一天对应的值。若参数无效,则返回NULL

Eg1. SELECT LAST_DAY(’2008-02-01′);

输出:29

12. NOW()

返回当前日期和时间值,其格式为 ‘YYYY-MM-DD HH:MM:SS’ YYYYMMDDHHMMSS 具体格式取决于该函数是否用在字符串中或数字语境中。

Eg1. SELECT NOW();

输出:’2007-01-05 11:54:30′

13. SUBDATE(date,INTERVAL expr type) SUBDATE(expr,days)

       当被第二个参数的 INTERVAL型式调用时, SUBDATE()DATE_SUB()的意义相同。对于有关INTERVAL参数的信息, 见有关 DATE_ADD()的讨论。

Eg1. SELECT SUBDATE(’2008-01-05′, INTERVAL 31 DAY);

输出:2007-12-05

14. SYSDATE()

返回当前日期和时间值,格式为‘YYYY-MM-DD HH:MM:SS’ YYYYMMDDHHMMSS 具体格式根据函数是否用在字符串或数字语境而定。

在一个存储程序或触发器中, SYSDATE()返回其执行的时间, 而非存储成都或触发语句开始执行的时间。这个NOW()的运作有所不同。

Eg1. SELECT SYSDATE();

输出:2008-01-05 12:01:41