• 2007-10-31

    Bash 补全技巧 - [LBE]

    原文:A Bash Completion Tip
    作者:mysurface
    译者:gosman(lianmingchang2008#gmail.com)
    来自:http://gosman.blogbus.com/
    版本:V 1.0.0
    时间:2007-10-31

    Bash 补全对 bash 用户来说是个强大的命令行技巧,按 tab 键就可以对命令行自动补全。不了解 bash 补全的话,可以参看 CLI magic: programmable bash completion

    Bash 补全的一个特色就是在用 tab 补全时能够隐藏未知的扩展名。比如要解压文件,可以输入

    tar -zxvf (tab) (tab)

    我不想列出那些扩展名不是 .tar.gz 的文件。因此,bash 补全智能地将其过滤。那我要分享的技巧又是什么呢?

    如何让某个命令列出其缺省不支持的扩展名呢?举个例子,用 kaffeine 播放视频文件时,我喜欢在终端启动 kaffeine,那样的话我可以在浏览文件立即播放。

    kaffeine 的 bash 补全缺省不支持 .flv。那要如何添加 flv 到 kaffeine 的 bash 补全呢?

    sudo vi /etc/bash_completion

    编辑 /etc/bash_completion,使用哪个编辑器不要紧,只要能搜索‘kaffeine‘就行了。

    更改的内容用粗体表示

    complete -f -X '!*.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|vcd|ps|pes|fli|flv|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp3|MP3|ogg|OGG|ogm|OGM|mp4|MP4|wav|WAV|asx|ASX|mng|MNG|srt)’ xine aaxine fbxine kaffeine

    重启终端,现在 kaffeine 的 bash 补全支持 .flv了。

  • 原文:grep multiple lines
    作者:mysurface
    译者:gosman(lianmingchang2008#gmail.com)
    来自:http://gosman.blogbus.com/
    版本:V 1.0.0
    时间:2007-9-7

    这是个小技巧,grep的A(after,后)选项和B(before,前)选项可以同时输出其匹配行的前后几行。

    比如包含有如下文本的message.txt:

    Aug 5 02:43:12 zion kernel: [ 0.000000] Zone PFN ranges: Aug 5 02:43:12 zion kernel: [ 0.000000] DMA 0 -> 4096 Aug 5 02:43:12 zion kernel: [ 0.000000] Normal 4096 -> 130730 Aug 5 02:43:12 zion kernel: [ 0.000000] HighMem 130730 -> 130730 Aug 5 02:43:12 zion kernel: [ 0.000000] early_node_map[1] active PFN ranges Aug 5 02:43:12 zion kernel: [ 0.000000] 0: 0 -> 130730 Aug 5 02:43:12 zion kernel: [ 0.000000] DMI 2.3 present.

    用带-B1和-A2选项的grep匹配搜索"DMA"。

    grep -B1 -A2 "DMA" message.txt

    输出:

    Aug 5 02:43:12 zion kernel: [ 0.000000] Zone PFN ranges: Aug 5 02:43:12 zion kernel: [ 0.000000] DMA 0 -> 4096 Aug 5 02:43:12 zion kernel: [ 0.000000] Normal 4096 -> 130730 Aug 5 02:43:12 zion kernel: [ 0.000000] HighMem 130730 -> 130730

    grep匹配一个结果,输出多行的功能,在搜索日志文件时很有用。

  • 原文:Writing scripts that needs root permission
    作者:mysurface
    译者:gosman(lianmingchang2008#gmail.com)
    来自:http://gosman.blogbus.com/
    版本:V 1.0.0
    时间:2007-9-4

    当执行需要超级用户(root)权限的命令时,我会使用sudo。sudo提供了一种只要我的帐户密码就可以执行超级用户权限命令的简便方法。

    sudo和su是不一样的,可以参考这里

    但在写脚本时,不能直接使用sudo。例如,我写了个用我的DNS设置来修改/etc/resolv.conf的脚本。修改/etc/resolv.conf需要超级用户权限。但在脚本里,我不能直接使用sudo。

    下面的脚本就不能工作。

    
    #!/bin/bash
    # the lines below doesn't work!!!
    sudo echo "nameserver 202.188.1.5" > /etc/resolv.conf
    sudo echo "nameserver 202.188.0.133" >> /etc/resolv.conf
    cat /etc/resolv.conf
    
    

    可以将所有需要超级用户权限的命令写在一个脚本里,然后在外部用sudo执行此脚本。比如我的脚本是set_dns.sh。

    sudo ./set_dns.sh 

    上面的方法可以工作,但是我想在普通用户执行时会提示需要sudo密码呢?我找到了一个方法,下面的脚本就可以做到。

    
    #!/bin/bash
    if [ "$1" == 'done' ]
    then
        #the commands needs root permission list as below
        echo "nameserver 202.188.1.5" > /etc/resolv.conf
        echo "nameserver 202.188.0.133" >> /etc/resolv.conf
        cat /etc/resolv.conf
    else
        sudo $0 done
    fi
    
    

    我把它写成一个模板,只要替换'then'和'else'之间的那部分就行了。

  • 原文:tabbed-browsing file manager
    作者:mysurface
    译者:gosman(lianmingchang2008#gmail.com)
    来自:http://gosman.blogbus.com
    版本:V 1.1.0
    时间:2007-9-4

    我喜欢nautilus文件管理器,它可以直接访问samba,ftp站点等,但在文件处理时,特别是在打开多个文件夹时,我希望可以像firefox那样用标签页(tab)浏览。

    pcmanfm可以做到这点。当我对pcmanfm了解更多时,我发现它不只是轻量的可以标签页浏览的一个文件管理器而已。

    我们的目标不是使PCMan文件管理器强大,而是使它足够好。

    作者这句话阐述了pcmanfm的设计理念。Pcmanfm关注的是那些经常要通过文件管理器来操作文件的用户,比如更改文件权限和属主,用选择的程序(甚至是命令行)打开文件,在目录设置书签,在当前目录打开终端,root权限访问目录,压缩和解压缩文件,还有标签页浏览等。

    分享一些我使用pcmanfm的技巧。

    打开文件

    你可以设置缺省程序打开指定的文件,右键单击文件选定用其他程序打开,选择程序并勾选复选框。你不仅可以从目录里选择程序,甚至可以使用命令行。

    设置壁纸

    Flubbox用户,通常是运行fbsetbg命令来设置桌面背景。

    fbsetbg mywallper.png

    现在你可以设定fbsetbg为png图片的缺省程序,这样只需双击png图片,就可以将其设置为桌面背景。

    命令行

    pcmanfm支持在命令行使用缺省程序打开文件。

    pcmanfm bash_tutorial.pdf

    pdfview会打开bash_tutorial.pdf文件,如果你设置它为pdf文件的缺省程序的话。gnome-open也可以做到这点。

    文件权限和属主

    更改文件权限和属主,右键单击文件选择“属性”,再选择“权限”标签。

    桌面

    pcmanfm可以管理桌面,~/Desktop下的图标都会出现在桌面。选择编辑(Edit)->属性(Preferences),桌面(Desktop)标签。

    标签页浏览

    中键单击文件夹,会在新标签页打开,+按钮或者简单的Ctrl+t也可以打开新标签页。

    下载PcManFM: http://pcmanfm.sourceforge.net

  • 原文:Use gprof to check your codes for performance issues
    作者:mysurface
    译者:gosman(lianmingchang2008#gmail.com)
    来自:http://gosman.blogbus.com
    版本:V 1.0.0
    时间:2007-8-30

    通过阅读IBM DevelopWorks上的使用 GNU profiler 来提高代码运行速度,我掌握了使用gprof来分析代码的性能瓶颈,以减轻我工作的技术。下面就来分享一下我的经验。

    我们先看看GNU profiler工作的几个简单步骤。

    为了使用gprof,只需在用gcc编译C/C++代码时加上-pg选项。假设要编译的源代码是gp-test.c。

    gcc -pg -g2 -o gp-test{,.c}

    -pg是启用gprof,-g2设置调试模式为2,-o指定二进制输出,我使用了大括号扩展来减少我的输入。

    接着运行可执行文件,将产生gmon.out。

    ./gp-test

    有了gmon.out,我们就可以使用gprof来剖析我们的代码。

    gprof gp-test gmon.out > result.txt 

    我倾向于把输出保存为一个文件'result.txt',以利于将来的比较和分析。

    让我们举一个C例子代码,试着找到关键点。

    #include
    int twoD[10000][10000]={0};
    int update_d1()
    {
    int i,k=0;
    for (i=0;i<10000;i++)
    twoD[i][1]=k++;
    }
    int update_d2()
    {
    int i,k=0;
    for (i=0;i<10000;i++)
    twoD[1][i]=k++;
    }
    int main(int argc, char * argv[])
    {
    int i,j,k=0;
    if (argc!=2)
    return -1;
    if (*(argv[1])=='1')
    update_d1();
    else if (*(argv[1])=='2')
    update_d2();
    else
    printf("\nInvalid value %s\n",argv[1]);
    return 1;
    }

    函数update_d1()和update_d2()循环一样的次数来访问二维数组。设这二维数组为twoD[row][column],update_d1()访问行(row),update_d2()访问列(column)。我们发现这两个函数的运行时间差很大。让我们用gprof剖析一下吧。

    gcc -pg -g -o gp-test{,.c}
    ./gp-test 1
    gprof gp-test gmon.out > t1
    ./gp-test 2
    gprof gp-test gmon.out > t2

    观察剖析结果:

    using update_d1() :
    % cumulative self self total
    time seconds seconds calls ms/call ms/call name
    100.52 0.06 0.06 1 60.31 60.31 update_d1
    using update_d2() :
    % cumulative self self total
    time seconds seconds calls Ts/call Ts/call name
    0.00 0.00 0.00 1 0.00 0.00 update_d2

    update_d1()花费0.06秒,update_d2()少于0.01秒,为什么呢?

    让我们再看看这个二维数组twoD[row][column]。这个数组在物理上映射为一整块内存,而不是按行列排列。这内存块以0行1列开始,而第一行第一列实际是第10001块。

    想象一下update_d1()怎样访问内存?为了访问每行,你需要越过10000块,而update_d2()可以直接访问那10000块。这就是延迟的原因。