Effective Linux (1) commandline hongjiang 2012.2.29
Dancing in commandline 1) getting to know your shell 2) shortcut keys 3) command history 4) tips (bash & zsh)
我的终端环境 xubuntu(11.10) + zsh(4.3.11) + gnome-terminal(3.0.1) zsh 的语法与 bash 接近,两者相互借鉴 有关 zsh 的技巧,可参考我 delicious 收录的 http://delicious.com/w.hongjiang/zsh
了解你所用的 shell $ echo $SHELL  看到的结果可靠吗? 假设默认是 Bash ,执行下面的,结果是什么结果 $ ksh  $ echo $SHELL 那么  $SHELL  变量是从哪里来的? $ cat /etc/passwd | grep $UID 或  $awk -F:  '/'"$UID"'/{print $NF}'  /etc/passwd 另: $SHELL  是可被改写的
了解你所用的 shell 正确的方式: $ ps –fp $$  UID  PID  PPID  C STIME TTY  TIME CMD 1000  2454  2449  0 22:53 pts/1  00:00:00 /usr/bin/zsh $$  是大多 shell 内置变量,表示当前进程 ID $$  变量不可被改变
了解你所用的 shell 脚本首行声明为  #!/bin/sh  但你能确定它以那种 shell 执行么?  为什么 jetty 的脚本里不那么写,而写为  #!/usr/bin/env bash
了解你所用的 shell Debian/Ubuntu 下 /bin/sh 是 /bin/dash 的一个软连接 Redhat/CentOS  下  /bin/sh 是 /bin/bash 的软连接 $ apt-cache show dash Debian Almquist Shell (dash) 是一款兼容  POSIX  的  shell ,衍生自  ash 。由于它执行脚本比  bash  快,依赖的库少 ( 使得它更稳健,受软硬件故障影响少 ) ,  Debian  使用它作为默认的系统  shell 。 Dash  与  Bash  的差异? http://www.igigo.net/archives/169
了解你所用的 shell shell 配置的执行顺序 1: /etc/profile 2: ~/.bash_profile  如果有则执行 3: ~/.bash_rc  如果有则执行 4: ~/.bash_login  如果有则执行 5: ~/.profile  如果有则执行 注: redhat 里  .bash_rc  是由  .bash_profile 去调用的
了解你所用的 shell bash  下通过  set  和  shopt  命令设置 eg: set –e 默认情况下 shell 脚本中某一行出错,后续的代码仍会执行的。当设置了 -e 参数,每行命令若以非零值返回 , 则立即退出。 Every script you write should include set -e at the top.  zsh 下通过  set  和  setopt  命令设置
了解你所用的 shell 常见重定向  cmd > file 2>file  与  cmd > file 2>&1  的差异 command > file 2>file  的意思是将命令所产生的标准输出信息 , 和错误的输出信息送到 file  中 . command  > file 2>file  这样的写法 ,stdout 和 stderr 都直接送到 file 中 , file 会被打开两次 , 这样 stdout 和 stderr 会互相覆盖 , 这样写相当使用了 FD1 和 FD2 两个同时去抢占 file  的管道。 而 command >file 2>&1  这条命令就将 stdout 直接送向 file, stderr  继承了 FD1 管道后 , 再被送往 file, 此时 ,file  只被打开了一次 , 也只使用了一个管道 FD1, 它包括了 stdout 和 stderr 的内容。
了解你所用的 shell zsh  中的重定向,花样更多一些 http://www.cs.elte.hu/zsh-manual/zsh_7.html 或见  zsh-lovers  中的 Redirection-Examples
快捷键 先解决冲突 Alt + F  会先被应用程序菜单快捷键所捕获的问题 : 隐藏 gnome-terminal 的 menubar $ gconftool --type boolean --set /apps/gnome-terminal/profiles/Default/default_show_menubar false 若要想显示,鼠标右键有显示菜单栏的选项。
快捷键 Ctrl + u  删除整行 Ctrl + k  删除光标到行尾 (Ctrl +a , Ctrl + k  相当于  Ctrl + u) Ctrl + w  删除前一个单词  Alt + Backspace  也是类似效果 Alt + d  删除后一个单词 Ctrl + h  向前删除一个字符 Ctrl + d  向后删除一个字符 Ctrl + y  粘贴所删除的 Ctrl + f  向右移动  Alt + f  向右移动一个单词 Ctrl + b  向左移动  Alt + b  向左移动一个单词
快捷键 _ 表示光标所在位置: $ command arg1  _  arg2 arg3 C+A C+E C+F C+B Alt+F Alt+B
快捷键 gnome-terminal 下滚动屏幕的快捷键  bash 和 zsh  默认是  Shift+PgUp  和  Shift+PgDn  用来翻屏。 Ctrl+Shift+ 上  / Ctrl+Shift+ 下 ,则是向上和向下滚动一行。 see:  http://library.gnome.org/users/gnome-terminal/stable/gnome-terminal Ctrl+PgUp/PgDn  相当于  Alt+1/2/3  切换到下一个 tab Ctrl+Shit+PgUp/PgDn  则将当前 tab 左移或者右移 注:解决 screen 中屏幕滚动的问题, see my screenrc
快捷键 命令行输入了一半后,发现需要先执行某个命令 比如 , cd /tmp/dd  ,还没有输入完,发现需要先创建这个目录。以往的做法是  Ctrl+a  到命令的前头,输入  $ mkdir /tmp/dd && cd /tmp/dd 简单的方式是, Ctrl+u   删除此行命令,然后执行其他命令之后,再  Ctrl+y   粘贴之前的命令 zsh 下, 用   alt+q  可以替代上面的两步  ctrl+u , ctrl + y
历史命令 快速执行历史的第 n 个命令 $ history $ !100 快速的执行上一个命令 $ !! 执行一个命令后,发现权限不足 $ sudo !!
历史命令 调用上一个命令中的参数 eg:  创建了一个路径很长的目录 $ mkdir /verylongpath/dir $ cd  到刚才创建的目录,要再敲一边? Alt  + .  (或  Esc + . )  可以调出上个命令的参数
历史命令 $ echo  !*  上个命令中的所有参数 $ echo  !^   上个命令中的第一个参数 $ echo  !$   上个命令中的最后一个参数 $ echo  !:n   上个命令中的第 n 个参数 $  !!:p   显示上个命令,但不执行
历史命令 在多个终端中共享历史命令 zsh  在 .zshrc 中增加一行:  setopt histignorealldups sharehistory bash $ echo "shopt -s histappend" >> ~/.bashrc $ echo "PROMPT_COMMAND=\"history -a; \$PROMPT_COMMAND\""  >> ~/.bashrc
历史命令 对 ctrl-r  的增强 bash  中绑定  up  和  down  在匹配的条件中选择 bind '"\e[A": history-search-backward' bind '"\e[B": history-search-forward' zsh 中的绑定: bindkey "^[[A" history-search-backward bindkey "^[[B" history-search-forward 这样  ctrl-r  后搜索  mvn  然后可以用  up/down  选择所有 mvn 的历史命令 或输入  mvn  然后用 up/down  选择所有历史命令中以 mvn 开头的
tips 终端退出后,进程也被中止了,如何避免? 1)  是 Daemon 程序 : nohup ,  disown 2)  是交互操作: screen 思考:  java  xxx &  关闭终端, java 进程是否还会存在? Java –server 模式呢? ppid  变成了谁?
tips 正确的结束一个进程 我们的 web server 脚本里直接用 kill -9 是否合适? 若 java 程序在 exit 时执行了 hook , Runtime.getRuntime().addShutdownHook 会如何?  参考 jetty 脚本里的结束方式。 先发送 HUP 信号 (1) ,不灵再 发送 KILL 信号 (9)
tips Screen 的配置 我的 .screenrc defscrollback 30000 hardstatus alwayslastline &quot;%{=b}%{-b}%{R}[%{=b B}%-w%{=b BK}%>%n %t%{-}%+w%{-b}%< %=%{R}]%{G}[%Y-%m-%d %c]&quot; termcapinfo xterm* ti@:te@ 设置  screen 默认的 shell alias screen='screen -s zsh'
tips bash 快速 cd 到上层任何指定路径 $ upto() { cd &quot;${PWD/\/$@\/*//$@}&quot; } $ pwd /a/very/long/cumbersome/directory $ upto very $ pwd /a/very 将 upto 函数放入  .bashrc  里
tips bash 里转换大小写的函数 commandfu 上面看到的: 注意,仅仅限于 bash ,也就时说需严格用  #!/bin/bash $ lower() { echo ${@,,}; } $ upper() { echo ${@^^}; }
tips 比较两个 antx.properties 不同之处 $ cat t1 t2 | sort -u | awk -F= '{a[$1]++;m[$1]=m[$1]&quot; &quot;$2} END{for(i in a) if(a[i] == 2)print i&quot;= &quot;m[i]}'
tips 2012 年有几个黑色星期五?苹果会不会再打折? $ export LANG=en_US.utf-8 $ for i in {1..12};do ncal -m$i | grep -E &quot;2012|Fr.*13&quot; | grep -B1 &quot;Fr&quot; ; done
tips 最简单的通过 http 方式共享当前目录 $ python –m SimpleHTTPServer

Effective linux.1.(commandline)

  • 1.
    Effective Linux (1)commandline hongjiang 2012.2.29
  • 2.
    Dancing in commandline1) getting to know your shell 2) shortcut keys 3) command history 4) tips (bash & zsh)
  • 3.
    我的终端环境 xubuntu(11.10) +zsh(4.3.11) + gnome-terminal(3.0.1) zsh 的语法与 bash 接近,两者相互借鉴 有关 zsh 的技巧,可参考我 delicious 收录的 http://delicious.com/w.hongjiang/zsh
  • 4.
    了解你所用的 shell $echo $SHELL 看到的结果可靠吗? 假设默认是 Bash ,执行下面的,结果是什么结果 $ ksh $ echo $SHELL 那么 $SHELL 变量是从哪里来的? $ cat /etc/passwd | grep $UID 或 $awk -F: '/'&quot;$UID&quot;'/{print $NF}' /etc/passwd 另: $SHELL 是可被改写的
  • 5.
    了解你所用的 shell 正确的方式:$ ps –fp $$ UID PID PPID C STIME TTY TIME CMD 1000 2454 2449 0 22:53 pts/1 00:00:00 /usr/bin/zsh $$ 是大多 shell 内置变量,表示当前进程 ID $$ 变量不可被改变
  • 6.
    了解你所用的 shell 脚本首行声明为 #!/bin/sh 但你能确定它以那种 shell 执行么? 为什么 jetty 的脚本里不那么写,而写为 #!/usr/bin/env bash
  • 7.
    了解你所用的 shell Debian/Ubuntu下 /bin/sh 是 /bin/dash 的一个软连接 Redhat/CentOS 下 /bin/sh 是 /bin/bash 的软连接 $ apt-cache show dash Debian Almquist Shell (dash) 是一款兼容 POSIX 的 shell ,衍生自 ash 。由于它执行脚本比 bash 快,依赖的库少 ( 使得它更稳健,受软硬件故障影响少 ) , Debian 使用它作为默认的系统 shell 。 Dash 与 Bash 的差异? http://www.igigo.net/archives/169
  • 8.
    了解你所用的 shell shell配置的执行顺序 1: /etc/profile 2: ~/.bash_profile 如果有则执行 3: ~/.bash_rc 如果有则执行 4: ~/.bash_login 如果有则执行 5: ~/.profile 如果有则执行 注: redhat 里 .bash_rc 是由 .bash_profile 去调用的
  • 9.
    了解你所用的 shell bash 下通过 set 和 shopt 命令设置 eg: set –e 默认情况下 shell 脚本中某一行出错,后续的代码仍会执行的。当设置了 -e 参数,每行命令若以非零值返回 , 则立即退出。 Every script you write should include set -e at the top. zsh 下通过 set 和 setopt 命令设置
  • 10.
    了解你所用的 shell 常见重定向 cmd > file 2>file 与 cmd > file 2>&1 的差异 command > file 2>file 的意思是将命令所产生的标准输出信息 , 和错误的输出信息送到 file 中 . command > file 2>file 这样的写法 ,stdout 和 stderr 都直接送到 file 中 , file 会被打开两次 , 这样 stdout 和 stderr 会互相覆盖 , 这样写相当使用了 FD1 和 FD2 两个同时去抢占 file 的管道。 而 command >file 2>&1 这条命令就将 stdout 直接送向 file, stderr 继承了 FD1 管道后 , 再被送往 file, 此时 ,file 只被打开了一次 , 也只使用了一个管道 FD1, 它包括了 stdout 和 stderr 的内容。
  • 11.
    了解你所用的 shell zsh 中的重定向,花样更多一些 http://www.cs.elte.hu/zsh-manual/zsh_7.html 或见 zsh-lovers 中的 Redirection-Examples
  • 12.
    快捷键 先解决冲突 Alt+ F 会先被应用程序菜单快捷键所捕获的问题 : 隐藏 gnome-terminal 的 menubar $ gconftool --type boolean --set /apps/gnome-terminal/profiles/Default/default_show_menubar false 若要想显示,鼠标右键有显示菜单栏的选项。
  • 13.
    快捷键 Ctrl +u 删除整行 Ctrl + k 删除光标到行尾 (Ctrl +a , Ctrl + k 相当于 Ctrl + u) Ctrl + w 删除前一个单词 Alt + Backspace 也是类似效果 Alt + d 删除后一个单词 Ctrl + h 向前删除一个字符 Ctrl + d 向后删除一个字符 Ctrl + y 粘贴所删除的 Ctrl + f 向右移动 Alt + f 向右移动一个单词 Ctrl + b 向左移动 Alt + b 向左移动一个单词
  • 14.
    快捷键 _ 表示光标所在位置:$ command arg1 _ arg2 arg3 C+A C+E C+F C+B Alt+F Alt+B
  • 15.
    快捷键 gnome-terminal 下滚动屏幕的快捷键 bash 和 zsh 默认是 Shift+PgUp 和 Shift+PgDn 用来翻屏。 Ctrl+Shift+ 上 / Ctrl+Shift+ 下 ,则是向上和向下滚动一行。 see: http://library.gnome.org/users/gnome-terminal/stable/gnome-terminal Ctrl+PgUp/PgDn 相当于 Alt+1/2/3 切换到下一个 tab Ctrl+Shit+PgUp/PgDn 则将当前 tab 左移或者右移 注:解决 screen 中屏幕滚动的问题, see my screenrc
  • 16.
    快捷键 命令行输入了一半后,发现需要先执行某个命令 比如, cd /tmp/dd ,还没有输入完,发现需要先创建这个目录。以往的做法是 Ctrl+a 到命令的前头,输入 $ mkdir /tmp/dd && cd /tmp/dd 简单的方式是, Ctrl+u 删除此行命令,然后执行其他命令之后,再 Ctrl+y 粘贴之前的命令 zsh 下, 用 alt+q 可以替代上面的两步 ctrl+u , ctrl + y
  • 17.
    历史命令 快速执行历史的第 n个命令 $ history $ !100 快速的执行上一个命令 $ !! 执行一个命令后,发现权限不足 $ sudo !!
  • 18.
    历史命令 调用上一个命令中的参数 eg: 创建了一个路径很长的目录 $ mkdir /verylongpath/dir $ cd 到刚才创建的目录,要再敲一边? Alt + . (或 Esc + . ) 可以调出上个命令的参数
  • 19.
    历史命令 $ echo !* 上个命令中的所有参数 $ echo !^ 上个命令中的第一个参数 $ echo !$ 上个命令中的最后一个参数 $ echo !:n 上个命令中的第 n 个参数 $ !!:p 显示上个命令,但不执行
  • 20.
    历史命令 在多个终端中共享历史命令 zsh 在 .zshrc 中增加一行: setopt histignorealldups sharehistory bash $ echo &quot;shopt -s histappend&quot; >> ~/.bashrc $ echo &quot;PROMPT_COMMAND=\&quot;history -a; \$PROMPT_COMMAND\&quot;&quot; >> ~/.bashrc
  • 21.
    历史命令 对 ctrl-r 的增强 bash 中绑定 up 和 down 在匹配的条件中选择 bind '&quot;\e[A&quot;: history-search-backward' bind '&quot;\e[B&quot;: history-search-forward' zsh 中的绑定: bindkey &quot;^[[A&quot; history-search-backward bindkey &quot;^[[B&quot; history-search-forward 这样 ctrl-r 后搜索 mvn 然后可以用 up/down 选择所有 mvn 的历史命令 或输入 mvn 然后用 up/down 选择所有历史命令中以 mvn 开头的
  • 22.
    tips 终端退出后,进程也被中止了,如何避免? 1) 是 Daemon 程序 : nohup , disown 2) 是交互操作: screen 思考: java xxx & 关闭终端, java 进程是否还会存在? Java –server 模式呢? ppid 变成了谁?
  • 23.
    tips 正确的结束一个进程 我们的web server 脚本里直接用 kill -9 是否合适? 若 java 程序在 exit 时执行了 hook , Runtime.getRuntime().addShutdownHook 会如何? 参考 jetty 脚本里的结束方式。 先发送 HUP 信号 (1) ,不灵再 发送 KILL 信号 (9)
  • 24.
    tips Screen 的配置我的 .screenrc defscrollback 30000 hardstatus alwayslastline &quot;%{=b}%{-b}%{R}[%{=b B}%-w%{=b BK}%>%n %t%{-}%+w%{-b}%< %=%{R}]%{G}[%Y-%m-%d %c]&quot; termcapinfo xterm* ti@:te@ 设置 screen 默认的 shell alias screen='screen -s zsh'
  • 25.
    tips bash 快速cd 到上层任何指定路径 $ upto() { cd &quot;${PWD/\/$@\/*//$@}&quot; } $ pwd /a/very/long/cumbersome/directory $ upto very $ pwd /a/very 将 upto 函数放入 .bashrc 里
  • 26.
    tips bash 里转换大小写的函数commandfu 上面看到的: 注意,仅仅限于 bash ,也就时说需严格用 #!/bin/bash $ lower() { echo ${@,,}; } $ upper() { echo ${@^^}; }
  • 27.
    tips 比较两个 antx.properties不同之处 $ cat t1 t2 | sort -u | awk -F= '{a[$1]++;m[$1]=m[$1]&quot; &quot;$2} END{for(i in a) if(a[i] == 2)print i&quot;= &quot;m[i]}'
  • 28.
    tips 2012 年有几个黑色星期五?苹果会不会再打折?$ export LANG=en_US.utf-8 $ for i in {1..12};do ncal -m$i | grep -E &quot;2012|Fr.*13&quot; | grep -B1 &quot;Fr&quot; ; done
  • 29.
    tips 最简单的通过 http方式共享当前目录 $ python –m SimpleHTTPServer