不管是 Mac 或是 Redhat, freebsd, debian ,这些 unix like 的系统,都有内建其本的 Linux 指令,如果你是 Windows 用户,可以安装 Cygwin ,这个软体能够在 Windows 上模拟 Linux 系统。
请先登入你的 unix like OS ,开始学习以下的指令吧。
路径操作 pwd, ls, cd
command | description |
---|---|
pwd | print working directory 显示当前目录 |
ls | list files 显示档案列表 |
ls -l | 最出档案列表明细 |
ls -lrt | 用 modify time 从小到大排序 |
ls -lrS | 用 file size 从小到大排序 |
cd | change directory 改变当前目录 |
cd ~ | 回到个人目录 |
cd - | 回到前一个目录 |
试试输入 pwd 然后按 enter ,系统会印出你当前的目录,例如我的 Account 是 puritys ,平常一登入 Linux 系统,我的当前目录会是在 /Users/puritys (Mac OS), /home/puritys (Linux)
ps 列出 process 列表
- ps aux
- ps auxw
- [www]$ ps aux |grep http
- USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
- root 5424 0.0 3.1 533380 32056 ? Ss 06:01 0:05 /usr/local/sbin/httpd
- daemon 5430 0.0 2.5 830840 26132 ? Sl 06:01 0:22 /usr/local/sbin/httpd
- daemon 5431 0.0 2.3 830840 24004 ? Sl 06:01 0:20 /usr/local/sbin/httpd
- daemon 5432 0.0 2.1 830840 22120 ? Sl 06:01 0:21 /usr/local/sbin/httpd
- daemon 5433 0.0 2.6 920684 26728 ? Sl 06:01 0:22 /usr/local/sbin/httpd
- daemon 5434 0.0 2.9 920684 29604 ? Sl 06:01 0:21 /usr/local/sbin/httpd
ps 印出来的每个栏位都有它的意义,USER 代表 process 使用的身分, PID 为 process id , CPU、 MEM 代表该 process 使用的比例,TIME 是执行多久, COMMAND 是 process 执行的指令 。
如何找出 CPU 使用量最大的 process.
- [www]$ ps aux | awk '{printf "%s %s\n",$3,$11}' | sort
- 0.0 sshd:
- 0.1 /usr/sbin/notifyd
- 0.1 /usr/sbin/ntpd
- 0.2 /System/Library/CoreServices/ZoomWindow.app/Contents/MacOS/ZoomWindowStarter
- 0.3 /Applications/Google
- 5.4 /Applications/Google
- 9.0 /Applications/Google
kill & killall
kill 是用来砍掉 process 用的,上面的 ps 范例中,有一个 id 5430 的 httpd process,如果我要中止这个 process ,就可以用 kill 5430.
- [www]$ kill 5430
- -bash: kill: (5430) - Operation not permitted
一般来说 Linux 系统的 process 是不能随便中止的,首先要有 admin 的权限,再来要加上 -9 来强迫中止 Process ,看下面这个范例。
- [www]$ sudo kill -9 5430
- [www]$ ps aux |grep http
- root 5424 0.0 3.1 533380 32056 ? Ss 06:01 0:05 /usr/local/sbin/httpd
- daemon 5431 0.0 2.3 830840 24004 ? Sl 06:01 0:20 /usr/local/sbin/httpd
- daemon 5432 0.0 2.1 830840 22120 ? Sl 06:01 0:21 /usr/local/sbin/httpd
- daemon 5433 0.0 2.6 920684 26728 ? Sl 06:01 0:22 /usr/local/sbin/httpd
- daemon 5434 0.0 2.9 920684 29604 ? Sl 06:01 0:21 /usr/local/sbin/httpd
- //5430 的 process 成功被中止,而消失了
停掉相同的 process ,Apache server 一次会 fork 出多个 process ,可以用 killall 这个指令来一次删除所有的 process。
- sudo killall -9 /usr/local/sbin/httpd
find
find 是 Linux 系统中很常被用到的指令,因为软体工程师没办法记住每一个庞大系统中,每个档案的路径,使用 find 可以快速的帮我们找到每一个档案
- find [path] -name *.cc
- [www]$ find . -name *.js
- ./hterm/js/hterm.js
- ./hterm/js/hterm_frame.js
- ./hterm/js/hterm_keyboard.js
- [www]$ find /etc/ -name *.conf
- /etc//AFP.conf
- /etc//apache2/extra/httpd-autoindex.conf
- /etc//apache2/extra/httpd-dav.conf
du
du 可以用来计算档案大小,当系统的硬碟爆炸的时候就会用到它。
- [root]$ du -sh /etc/*
- 4.0K /etc/AFP.conf
- 0B /etc/afpovertcp.cfg
- 4.0K /etc/aliases
- 0B /etc/aliases.db
- 148K /etc/apache2
- 0B /etc/asl
计算资料夹大小的时候,可能会有一种需求,就是我不想要记算副档案为 conf 的档案,这时就可以用到 --exclude ( Mac OS 不支援这个功能) 。
- [root]$ du -sh --exclude *.conf /usr/local/*
- 47M /usr/local/bin
- 36K /usr/local/builder
- 808K /usr/local/sbin
- 404M /usr/local/share
cat, zcat
cat 印出档案原始内容
cat xxx.txt
zcat 印出 gzip 档的内容,这个指令会先将 tar.gz 解压缩,然后印出内容。
zcat zzz.gz
tar 打包与解压缩
tar -zxvf 解开 tar 档
tar -zxvf xxx.tar.gz
tar -zcvf 将指定的档案打包成 tar 压缩档
tar -zcvf aaa.tar.gz dir/
- -z 代表用 gzip 加解压缩
- -x 解开 tar 档
- -c 打包 tar 档
zip 加解压缩
gzip test (产生 test.gz)
gunzip test.gz (解开成 test)
tail
即时显示档案最新新增的行数
tail -f file
显示档案最后 5 行
tail -n 5 file
ctrl+r 搜寻曾经输入过的指令
ctrl + r 是我超常使用的 Linux 指令,这个指令可以帮你搜寻你最近使用过的 command ,当你按了 ctrl + r ,会看到 reverse-i-search 的讯息,这时你只要输入你想要搜寻的单母,系统就会在右边出现 match 到的指令。
例如这个范例,我输入 ta ,而我最近一次输入有 ta 字眼的指令是 tail -f ... ,所以系统就会自动帮我找出来,按下 Enter 后,就可以执行这行指令。
- [root]$ (reverse-i-search)`ta': tail -f test
当系统已找到我最近使用的指令,这时我可能还想再找更久之前的指令,我们只要再按一次 ctrl+r ,系统就会自动再往前搜寻一次相关的指令。
grep 搜寻文字
grep 是一个很好用的过泸与文字搜寻指令。
greg -Ri xxx *.txt
grep -l function *.cc
grep -o name *.txt
- -i case insensitive ,不区分英文字大小写
- -o 印出符合的字串
- -R Recursive
- -l 印出符合字串的档名
- [[:blank:]] grep 空白符号
- [[:digit:]] grep 数字
- [[:alpha:]] grep 英文字
- [www]$ echo "abc def" | grep 'abc'
- abc def
- [www]$ echo "abc def" | grep -o 'abc'
- abc
- [www]$ echo -e "Mars \nFeb \nMonk" | grep 'M'
- Mars
- Monk
- [www]$ echo -e "Mars \nFeb \nMonk" | grep 'M\|F'
- Mars
- Feb
- Monk
Awk
awk 是个好用的资料处理指令,一般表格式的资料非常适合用 awk , awk 预设会以空白将资料做分隔,字串会被分割成多个栏位 ,用 $1 代表第一个栏位 ,$2 代表第二个栏位。
首先我要建立一个空白分格的资料,使用简单的指令 echo -e "a a a\nb b b" ,"\n" 这个符号代表分行,可以资料分成两行。
再来我用 awk 印出每一行的第一个栏位
- [root]$ echo -e "Jackie 50\nMarry 90" |awk '{print $1}'
- Jackie
- Marry
用 awk 印出每一行的第二个栏位
- [root]$ echo -e "Jackie 50\nMarry 90" |awk '{print $2}'
- 50
- 90
Awk 除了印资料内容之外,也可以用来做资料的加总,范例如下。
- [root]$ echo -e "1 \n 2\n 3" |awk '{sum += $1} END {print sum}'
- 6
sed
sed 是一个文字 replace 的指令,可以让我们用简单的 regular express 取代字串,如果我想把文字里的 "function " 改成 "public function" ,那么我可以用 sed 's/string/replace to/g' 这个指令,若是我想要取代某个档案里的文字,就只要加上 "-i" 即可。
- [www]$ echo "function xxx()" | sed 's/function/public function/g'
- public function xxx()
- [www]$ sed -ri 's/function/public function/g' test.php
- // Mac
- [www]$ grep -l oauth *.php | awk "{printf \"sed 's/oauth/zauth/g' %s > tmp && mv tmp %s \n\", \$1, \$1}" |sh
time 计算程式执行时间
- [www]$ time tcsh -c "repeat 10 php test.php"
- real 0m2.785s
- user 0m0.659s
- sys 0m0.141s
合并常用的 Linux 指令
砍掉指定的 process,如果我想要砍掉 vim 跟 php 的所有 process ,那么我可以用下面这个指令,先用 ps aux 加上 grep 找出 vim, php 的 process ,再用 awk 组出 kill 的指令,最后丢给 sh 处理。
- [www]$ ps aux |grep 'vim\|php'|grep -v grep | awk '{printf "sudo kill -9 %s\n",$2}' | sh
将 Apache access log 中的所有 IP, 转成 hostname 。
- [www]$ tail -n 5 access | awk '{print $1}' | sort | uniq | awk '{printf "host %s\n", $1}' | sh
- 125.233.54.169.in-addr.arpa domain name pointer 7d.e9.36a9.ip4.static.sl-reverse.com.
- 78.244.54.169.in-addr.arpa domain name pointer 4e.f4.36a9.ip4.static.sl-reverse.com.
- 254.237.178.188.in-addr.arpa domain name pointer 188-178-237-254-static.dk.customer.tdc.net.
将目录下的所有副档名为 php 的档案,副档名改为 php5 。
- [www]$ ls *.php | sed 's/\.php//g' | xargs -t -n 1 -I% mv %.php %.php5
- mv aaa.php aaa.php5
如何将所有档案里的某一个 function 全部取代
假如我碰到一个问题 ,"LOG4CXX_DEBUG" 这个 function 会造成 RHEL4 环境 coredump ,所以我想要把这个 function 都注解掉,首先我用 grep -Rl LOG4CXX_DEBUG * |grep .cc$
找出所有使用 LOG4CXX_DEBUG 的 C/C++ 档案。
找出所有的档案后,再来 sed 来测试取代的语言, grep -Rl LOG4CXX_DEBUG * |grep .cc$ |xargs -t -n 1 cat | sed 's/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/'
,这个指令执行完成后,这时还不会真的修改档案内容,而是将 replace 后的结果印出来,这样我们可以先确认印出来的结果是否符何我们的预期。
确定没问题后,使用 sed -i
,系统就会真的将档案里的内容取代。
- [www]$ grep -Rl LOG4CXX_DEBUG * |grep .cc$ |xargs -t -n 1 sed -i 's/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/'
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gServer.cc
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gServer2.cc
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gClient.cc
- sed -i s/LOG4CXX_DEBUG/\/\/LOG4CXX_DEBUG/ client/gClient2.cc
最后再搜寻一次 LOG4CXX_DEBUG,确认所有的 LOG4CXX_DEBUG 都被注解了。
- [www]$ grep -R LOG4CXX_DEBUG *
- client/gServer.cc: //LOG4CXX_DEBUG(logger, " xx."<< endl);
- client/gServer.cc: //LOG4CXX_DEBUG(logger, "Cannot find "<< __FUNCTION__ << " Line " << __LINE__ << endl);
- client/gServer2.cc: //LOG4CXX_DEBUG(logger, "Call xxx "<< __FUNCTION__ << " Line " << __LINE__ << endl);
找出档案里的所有英文字
- [www]$ cat en |grep -o '[a-z]*' | sort | uniq
- said
- since
- single
- the
从 /usr/lib shared object 中扫出某个 function
- [www]$ nm -A -C /usr/lib/*.so |grep zero_nan
- /usr/lib/libm-2.17.so:00030090 r zero_nan
- /usr/lib/libm-2.17.so:00032800 r zero_nan
- /usr/lib/libm-2.17.so:00034e10 r zero_nan
作业
接下来有一些简单的作业,看你是否可以完成它罗
- 移除副档名 .log ,以及五天前建立的档案。
- 计算档案内的所有不重复英文单字。
- 计算档案内的所有中文字数,重复的中文算两个字。
- 计算所有 tar, gz, zip 等等的档案 size 总合。
- 计算档案的所有行数,但是不包含空白。
- 找出 CPU 最多的 process
- 将档案内的 call(1, false, 'input') ,改成 apply([1, false, 'input']) 。
- 移除 PHP 档案中有使用 error_log 的 function 。
- 使用 tar ,打包某个档案,并将其档案命名为 "年-月-日.tar.gz"
- 找出档案内的所有 email 。
- 印出五天前(120 小时前)的 timestamp。
- 记算 httpd 这种 process 的记忆体使用量。