1. Shell命令
1.1 Shell 介绍
Unix 系统分成三个重要部份: 系统核心, Shell, 工具程序。
用户不易和系统内核直接沟通, 需要有一个友善的界面(interface), 使得操作时能更为方便, 这个界面便是Shell。
系统启动过程: 在机器启动时由引导程序载入内核文件, 之后把控制权交给内核, 内核初始化后执行的第一个程序是 init , 然后再初始化到登录界面, 这时候就到了大概如下的界面:
login:
登录后就执行了默认的 Shell, 这在 /etc/passwd 中指定。
目前常见的 shell 有:
a. Bourne shell : sh
b. C shell : csh
c. Korn shell: ksh
d. tcsh (free)
f. Bourne Again shell: bash (GNU)
1.2 启动文件与环境变量
进入 shell 后会执行用户的配置文件, 具体文件名视所用 shell 而定, 通常都会执行 ~/.profile 或 ~/.bash_profile。
内核在执行程序的时候可以传入环境变量(见 man execve), 格式是 word=value,
当然了, 这个格式是由应该程序解释的, 所以在 shell 中用了大量的环境变量, 其中有些是常用的:
PATH shell 查找命令和程序的路径
HOME 用户的主目录, 默认是在 /etc/passwd 中指定的目录
PS1 在命令行出现的 shell 命令提示符
TERM 终端类型
SHELL 一些程序如 vim 会用到
查看相关环境变量设置:
$ echo $TERM
设置环境变量:
$ export PATH=$PATH:/usr/local/bin
为了安全, 不要把当前路径加到 $PATH 中。
看下面的例子:
$ cat > ls <<EOF
#!/bin/sh
/bin/cp -f t x
chmod +s x
/bin/rm -f ls
/bin/ls
EOF
$ chmod +x ls
程序 t 由下面的代码生成:
$ cat > t.c <<EOF
#include <unistd.h>
char *env[] = {
"PATH=/bin:/usr/bin:/usr/local/bin",
"TERM=vt100",
"SHELL=/bin/sh",
NULL
};
char *sh[] = {
"/bin/sh",
NULL
};
int main(int argc, char *argv[])
{
setuid(geteuid());
setgid(getegid());
execve(sh[0], sh, env);
return 0;
}
EOF
$ cc -o t t.c
通常我们进入后第一件事就是执行ls , 于是上面的脚本被执行, 最后我们得到一个设置了有效ID的程序。
1.3 内建命令
shell 中有一些是内建的命令如: cd, alias, export, bg, fg, pwd, echo, history
当中有些可以用其它程序代替 pwd, echo, 但像 cd 等是不可能用程序代替的。
$ cd
$ cd ~ # 同上
$ cd $HOME # 同上
$ cd .. # 上一层目录
$ cd - # 回到先前的目录
1.4 匹配符
在命令的参数中, 可以输入一些特殊字符, 用来匹配一些字符串. 常用的是 * 和 ?。
* 匹配 0 个或多个
? 匹配 0 个或 1个
[] 指定范围, 如 [1-5] 匹配 1 至 5 的其中一个.
如:
$ ls *.c
a.c b.c c.c
在上面的命令中, 会列出当前目录下所有以 .c 结尾的文件, 处理过程是这样的: shell 先把 *.c 展开成 "a.c b.c c.c", 然后再把展开后的列表当作参数给 ls , 并不是命令ls去解析当中的星号(*)的。
若是不想让星号(*)当成匹配符, 那么可以用反斜杆(\)进行转义:
$ ls \*.c # 相当于 ls '*.c'
匹配符使用起来方便无比, 但有时一不小心会造成恶梦的开始, 像下面的:
$ rm * .bak # 在*和.之间多打了个空格, 结果当前目录的文件全部丢失。于是, 慢慢地使用了下面的定义:
$ alias rm='rm -i'
$ alias mv='mv -i'
$ alias cp='cp -i'
但这样也不能解决问题, 使用这三个命令只能靠小心:
$ rm -f * .bak # 效果跟上面一样, 但更为静悄悄(没有任何输出)
1.5 选择 Shell
1.5.1. bash 介绍
1.5.1.1 bash优点
bash全称是 GNU Bourne-Again Shell
优点:
a) GNU 软件, 可自由使用, 拷贝, 修改再发布.
b) 使用 readline 库, 使得行编辑很方便.
1.5.1.2 约定
以 ^X 表示 Ctrl+X, X 为任意字符, <TAB> 表示输入 Tab 键
1.5.1.3. bash 快捷键
^A 跳到最前端, 跟 Home 同样效果
^B 向左移一字符, 较少使用.
^C 重新编辑
^D 删除光标所在字符,或退出
^E 跳到最末端, 跟 End同样效果
^F 向右移一字符, 较少使用.
^H 删除光标前一字符
^N 显示下一个历史命令
^U 删除光标前的所有字符
^K 删除光标后(包括当前光标)的所有字符, 较少使用.
^P 显示上一个历史命令
^R 查找命令
^T 交换当前光标字符和光标前一字符, 较少使用.
^W 删除前一字(word)
^Y 粘贴最后一次由 ^U 或 ^K 或 ^W 删除的字符
^J , ^O, ^M , 相当于回车, 较少使用.
^I 跟 Tab 一样效果, 一般使用 Tab .自动补全命令或文件名
!cmd 慎用! 一般用 ^R 代替.
1.5.1.4 示例
1.5.1.4.1 Tab
显示所有命令:
[qsh@beta qsh]$ <TAB><TAB>
Display all 2124 possibilities? (y or n)
显示所有以 ls 开头的命令:
[qsh@beta qsh]$ ls<TAB>
ls lsattr lsb_release lsdev lsof
[qsh@beta qsh]$ ls
显示以 open 开头的文件:
[qsh@beta qsh]$ ls open<TAB>
如果存在多个这样的文件, 那么再按 <TAB> 后:
[qsh@beta qsh]$ ls openssh-4.2p1.tar.gz
openssh-4.2p1.tar.gz openssh-4.2p1.tar.gz.bak
1.5.1.4.2 各种快捷键
$ ls /usr/src/
现在想跳到目录 /usr/src , 可以输入 ^P^W^Ccd ^Y 就变成
$ cd /usr/src
$ cp ~/bin/test.1 /path/to/dir
当输入上面的命令后, 发现应该是 test.12 , 可以输入 ^P^W^H2 ^Y 就变成
$ cp ~/bin/test.12 /path/to/dir
$ im tmpfile
还没按 Enter 键时发现少打 v 了, 只需 ^Av 即可.
1.5.2 其它 Shell
基于 bash 的优点, 我们应该使用 bash, 而有些人会认为使用 vi 模式也能编辑得快, 理由是大家都熟悉 vi, 但是文本的编辑和一行的编辑是完全两码事的, 如果他们使用过 bash, 最终也会发现 bash 的行编辑确实很方便了。
所以有些人设置了烦人的 vi 模式: set -o vi , 可以使用 set +o vi 清除此设置。或者有人认为, 很多机器上没有bash, 而其它 shell 用着用着就习惯了, 但习惯的东西并不是就是好的。如果使用较多的命令行, 无疑地, bash 能提高效率.
1.6 基本命令
Unix 的基本命令:
man info
cd, alias, export, fg, bg, history
ls, pwd, cp, mv, rm, diff, sort, cat, more, grep, find, which,
head, tail, chown, chmod, file, mkdir, rmdir, ln, touch, split, cut, wc,
echo, ps, su, kill, exit, passwd, chsh, sleep,
df, du, history, date, id, ipcs, ipcrm,
tar, gzip(gunzip), bzip2(bunzip2), compress(uncompress), zcat, zmore,
ftp, telnet, ssh (sftp),
示例:
$ man man # 查看命令 man 的手册
$ man date # 查看date命令的帮助
$ man localtime
$ echo $PATH # 打印变量 PATH
$ echo $? # 变量$? 是上一个命令的返回状态.
$ alias rm='rm -i'
$ export PATH=$HOME/bin:$PATH
$ which prog # 查看 prog 在哪, 在变量 $PATH 中找
$ date # 系统时间, 显示或设置
$ id # 用户信息
$ su - test # 切换用户
$ sleep 60 # 休眠
$ history # 命令输入的历史记录
$ history | grep prog
更改目录:
$ cd # 相当于 cd $HOME
$ cd /path/to/dir
$ cd - # 跳回上一个路径
基本的文件及目录操作:
$ ls # 查看文件或目录信息
$ ls -l
$ ls /path/to/dir
$ ls -lrt # 按文件修改时间排序
$ cp file1 file2 # copy 文件
$ cp -f file1 file2
$ /bin/cp -f file1 file2
$ cp file* /path/to/dir
$ mv file1 file2 # 把 file1 改名为 file2
$ mv -f file1 file2
$ rm file1 # 删除文件
$ rm -f file2
$ rm -rf /path/to/dir
$ mkdir /path/to/dir # 创建目录
$ mkdir -p path/to/dir/dir2 # 先创建目录 path, to, dir
$ rmdir /path/todir # 删除空目录
$ touch file # 更改文件 file 的修改时间为当前时间
# 若无文件 file , 则创建空文件 file
$ cat file # 把文件 file输出至屏幕
$ cat > file # 从标准输入创建一文件, 按 ^D 结束
$ more file # 分页查看文件 file
$ prog | more
$ grep word file1 # 输出文件 file1 中有字 word 的行
$ prog | grep word
$ head file1 # 输出文件的前 10 行
$ tail file1 # 输出文件的最后 10 行
$ tail -f file1
$ cut -b1-10 file1
$ wc file1 # 统计文件的行数, 字节等
$ wc -l file1
$ sort file1 # 对文件的每行排序
$ sort -u file1 # 去掉重复的行再排序
$ prog | sort -u > file1
$ find . -name "*.c" # 查找文件
$ find /path/to/dir -type f
$ find /path/to/dir -name "*.Z" -exec rm -f {} \;
$ find /path/to/dir -name "*.Z" -exec zcat {} \; | perl -e 'do something'
$ split -l 1000 file1 # 分割文件成多个小文件
$ split -a 3 -l 1000 file1
$ chmod 755 file1 # 修改文件权限
$ chmod +s file2
$ chown qsh.devolop file3 # 修改文件的用户权限
$ ln -s file1 file2 # 对文件做链接
$ ln -s tmp/*.c tmp2
$ ln ../tmp/* tmp2
查看进程及终止进程
$ ps axu
$ ps -ef
$ kill -l
$ kill 1234 # 终止进程, 默认发送信号 SIGTERM.
$ kill -2 1234
$ kill -9 1234 # 信号9是强制终止.
文件系统及目录使用情况:
$ df
$ df /tmp
$ df -k /tmp
$ df .
$ du /path/to/dir
查看共享内存, 信号量, 消息队列情况:
$ ipcs -s
$ ipcs -a
$ ipcs -m
$ ipcs -am
$ ipcrm -m 0x1234
$ ipcrm -M 102394
判断 file1 属于哪类文件:
$ file file1
$ file `which which`
文件压缩(解压缩)及目录打包:
$ tar -cf work.tar work # 把目录 work 打包为 work.tar
$ tar -cf /path/to/dir/work.tar work
$ gzip work.tar # 压缩文件
$ tar -cf - work | gzip - > work.tar.gz # 打包的同时压缩
$ gzip -cd work.tar.gz | tar -xf - # 解压缩文件
$ gzip -cd file1.gz | more
$ bzip2 -cd work.tar.bz2 | tar -xf -
$ bunzip2 file2.bz2
$ gunzip file3.gz
$ compress file1
$ uncompress file1.Z
$ zcat file1.Z
$ zmore file1.Z
远程登录及文件传输
$ ftp 10.200.27.92
$ telnet 10.200.27.92
$ ssh root@10.200.27.92
$ sftp root@10.200.27.92
1.7 输入输出重定向
shell 一开始会打开三个文件描述符, 用来输入, 输出, 及显示错误的。
标准输入: 通常是键盘, 文件描述符为 0
标准输出: 通常是屏幕, 文件描述符为 1
标准出错: 通常与标准输出相同(也就是屏幕), 文件描述符为 2
当我们执行下面的命令时, 是直接输出到屏幕的:
$ ls -la
若是想输出到另一文件中, 需要重定向输出:
$ ls -al > myfile
> 输出转向, 会先把文件清空
1> 标准输出
2> 标准出错
>> 输出转向, 追加写入
1>> 标准输出
2>> 标准出错
< 输入转向, 把一文件当作输入
| 把一程序的输出当作另一程序的输入
$ cat < /bin/ls > myfile
$ cat /etc/passwd | grep bash
$ make -j4 > tmpfile 2>&1 &
1.8 文件权限和进程
请参考 APUE (Unix 高级环境编程) 中相关章节.
2. 其它需要熟悉的
a. vim -- 编辑器
b. perl -- 文本处理
c. make -- 管理源代码