UNIX哲学
UNIX操作系统(包括Linux)鼓励一种特定的编程风格。下面列出了一些典型的UNIX程序和系统所具有的特点。
- 简单性 KISS keep it small and simple
- 集中性
- 可重用组件
- 过滤器
- 开放的文件格式
- 灵活性
为什么使用shell编程
- 使用shell进行程序设计的原因之一是,你可以快速、简单地完成编程。
- shell非常适合于编写一些执行相对简单的任务的小工具,因为它们更强调的是易于配置、易于维护和可移植性,而不是很看重执行的效率。
- 可以使用shell对进程控制进行组织,使命令按照预定顺序在前一阶段命令成功完成的前提下顺序执行。
- shell执行shell程序,这些程序通常被称为脚本,它们是在运行时解释执行的。这使得调试工作比较容易进行,因为你可以逐行地执行指令,而且节省了重新编译的时间。然而,这也使得shell不适合用来完成时间紧迫型和处理器忙碌型的任务。
什么是shell
shell是一个作为用户与Linux系统间接口的程序,它允许用户向操作系统输入需要执行的命令。
shell(实际上是两种shell:bash和csh)和其他程序环绕在Linux内核的四周。
常用的shell
- sh(Bourne) 源于UNIX早期版本的最初的shell
- csh、tcsh、zsh C shell及其变体,最初是由Bill Joy在Berkeley UNIX上创建的。它可能是继bash和Korn shell之后第三个最流行的shell
- ksh、pdksh korn shell和它的公共域pdksh(public domain korn shell)由David Korn编写,它是许多商业版本UNIX的默认shell
- bash 来自GNU项目的bash或Bourne Again Shell是Linux的主要shell。它的优点是可以免费获取其源代码,即使你的UNIX系统目前没有运行它,它也可能已经被移植到该系统中。bash与Korn shell有许多相似之处
除了C shell和少数变体以外,所有这些shell都很相似,并且都与X/Open 4.2和POSIX 1003.2规范中对于shell的规定非常一致。X/Open通常是一个提出更多要求的规范,但遵循它的系统也更加友好。
//顺手记录出现的一些命令
重定向输出
$ ls -l > lsoutput.txt
这条命令把ls命令的输出保存到文件中
重定向:
文件描述符0代表一个程序的标准输入
文件描述符1代表标准输出
文件描述符2代表标准错误输出
set -o noclobber
(或set -C)命令设置noclobber选项,阻止重定向操作对一个已有文件的覆盖。
set +o noclobber
取消该选项
$ ps >> lsoutput.txt
这条命令会将ps命令的输出附加到指定文件的尾部。
如果你想把两组输出都重定向到一个文件中,你可以用>&操作符来结合两个输出。
$ kill -1 1234 >killouterr.txt 2>&1
管道
在Linux下通过管道连接的进程可以同时运行,并且随着数据流在它们之间的传递可以自动地进行协调。
注意
如果你有一系列的命令需要执行,相应的输出文件是在这一组命令被创建的同时立刻被创建或写入的,所以决不要在命令流中重复使用相同的文件名。如果你尝试执行如下命令:
cat mydata.txt | sort | uniq > mydata.txt
你最终将得到一个空文件,因为你在读取文件mydata.txt之前就已经覆盖了这个文件的内容。
shell脚本
exit命令
exit命令的作用是确保脚本程序能够返回一个有意义的退出码。当程序以交互方式运行时,我们很少需要检查它的退出码,但如果你打算从另一个脚本程序里调用这个脚本程序并查看它是否执行成功,那么返回一个适当的退出码就很重要了。请相信自己的脚本程序是有用的,它总有一天会作为其他脚本程序的一部分而被重用。
shell的语法
变量:字符串、数字、环境和参数
- Linux是一个区分大小写的系统。
- 在shell中,你可以通过在变量名前加一个$符号来访问他的内容。无论何时你想要获取变量内容,你都必须在它前面加一个$符号。当你为变量赋值时,你只需要使用变量名,该变量会根据需要被自动创建。
- 如果字符串里包含空格,就必须用引号把它们括起来。此外,等号两边不不能有空格。e.g. salutation=7+5
- 可以使用
read
命令将用户的输入赋值给一个变量。 - 使用引号:双引号会把变量替换为它的值,单引号不会。
- test或[命令 注意,你必须在[符号和被检查的条件之间留出空格。
环境变量
- $HOME 当前用户的家目录
- $PATH 以冒号分隔的用来搜索命令的目录列表
- $PS1 一级命令提示符,通常是$字符
- $PS2 二级命令提示符,用来提示后续的输入,通常是>字符
- $IFS 输入域分隔符
- $0 shell脚本的名字
- $# 传递给脚本的参数个数
- $$ shell脚本的进程号,脚本通常会用它来生成一个唯一的临时文件
条件:shell中的布尔值
程序控制:if、elif、for、while、until、case
一般来说,如果需要循环至少执行一次,那么就使用while循环;如果可能根本都不需要执行循环,就使用until循环。
case结构
case “$timeofday” in
yes) echo “Good Morning”;;
no ) echo “Good Afternoon”;;
y ) echo “Good Morning”;;
n ) echo “Good Afternoon”;;- ) echo “Sorry,answer not recognized”;;
esac
- ) echo “Sorry,answer not recognized”;;
and列表和or列表
AND列表:只有在前面所有命令都执行成功的情况下才执行后一条命令。
OR列表:允许我们持续执行一系列命令直到有一条命令成功为止,其后的命令将不再被执行。
命令列表
命令 你可以在shell脚本程序内部执行两类命令。一类是可以在命令提示符中执行的“普通”命令,也称为外部命令(external command),一类是我们前面提到的“内置”命令,也称为内部命令(internal command)。内置命令是在shell内部实现的,它们不能作为外部程序被调用。然而,大多数的内部命令也提供了独立运行的程序版本——这一需求是POSIX规范的一部分。通常情况下,命令是内部的还是外部的并不重要,只是内部命令的执行效率更高。
- :命令
冒号(:)命令是一个空命令。它偶尔会被用于简化条件逻辑,相对于true的一个别名。由于它是内置命令,所以它运行得比true快,但它的输出可读性较差。
:结构也会被用在变量的条件设置中 - exit n(退出码)
* 126 文件不可执行 * 127 命令未找到 * 128 及以上 出现一个信号
- export命令
export没命令将作为它参数的变量导出到子shell中,并使之在子shell中有效。在默认情况下,在一个shell中被创建的变量在这个shell调用的下级(子)shell中是不可用的。export命令把自己的参数创建为一个环境变量,而这个环境变量可以被当前程序调用的其他脚本和程序看见。从更技术的角度来说,被导出的变量构成从该shell衍生的任何子进程的环境变量。
expr命令
expr命令将它的参数当作一个表达式来求值。在较新的脚本程序中,expr命令通常被替换为更有效的$((…))语法。
printf命令
printf “format string” parameter1 parameter2 …
格式字符串与C/C++中使用的非常相似,但有一些自己的限制。主要是不支持浮点数,因为shell中的有的算术运算都是按照整数来进行计算的。格式字符串由各种可打印字符、转义序列和字符转换限定符组成。格式字符串中除了%和\之外的所有字符都将按原样输出。
- set命令
set命令的作用是为shell甚至参数变量。许多命令的输出结果是以空格分隔的值,如果需要使用输出结果中的某个域,这个命令就非常有用。
- shift命令
shift命令把所有参数变量左移一个位置,使$2变成$1,$2变成$2,以此类推。原来$1的值将被丢弃,而$0仍将保持不变。$*、$@和$#等其他变量也将根据参数变量的新安排做相应的变动。
- trap命令
trap命令有两个参数,第一个参数是接收到指定信号时将要采取的行动,第二个参数是要处理的信号名。
trap command signal
如果要重置某个信号的处理方式到其默认值,只需将command
设置为-
。如果要忽略某个信号,就要把command
设置为空字符串``。一个不带参数的trap
命令将列出当前设置的信号及其行动的清单。
下面列出一些X/Open规范里面规定的能够被捕获的比较重要的一些信号(括号里面的数字是对应的信号编号)。更多参考man 7 signal
* HUP(1) 挂起,通常因终端掉线或用户退出而引发
* INT(2) 中断,通常因按下Ctrl+C组合键而引发
* QUIT(3) 退出,通常因按下Ctrl+\组合键而引发
* ABRT(6) 中止,通常因某些严重的执行错误而引发
* ALRM(14) 报警,通常用来处理超时
* TERM(15) 终止,通常在系统关机时发送
- unset命令 unset命令的作用是从环境中删除变量或函数。这个命令不能删除shell本身定义的只读变量(如IFS)。这个命令并不常用。
这里列举一些命令
- break命令
- :命令
- continue命令
- .命令
#
echo命令
eval命令
exec命令
exit n命令
export命令
expr命令
printf命令
return命令
set命令
shift命令
trap命令
unset命令
另外两个有用的命令和正则表达式
find
find
[path]
[options]
[tests]
[actions]
- grep命令
通用正则表达式解析器(General Regular Expression Parser,简写为grep)
函数
if elif的另一种写法:用命令列表OR或AND来实现
[ -f file_one ] && command for true || command for false
shell内置命令
获取命令的执行结果
here文档
在shell脚本程序中向一条命令传递输入的一种特殊方法是使用here文档。它允许一条命令在获得输入数据时就好像在读取一个文件或键盘一样,而实际上是从脚本程序中得到输入数据。
- 调试脚本程序
因为脚本程序是解释执行的,所以在脚本程序的修改和重试过程中没有编译方面的额外开支。跟踪脚本程序中复杂错误的主要方法是设置各种shell选项。
- dialog和gdialog命令
文件操作
- 文件和设备
- 系统调用
- 库函数
- 底层文件访问
- 管理文件
- 标准I/O库
- 格式化输入和输出
- 文件和目录的维护
- 扫描目录
- 错误及其处理
- /proc文件系统
- 高级主题:fcntl和mmap
目录
系统使用的是文件的inode编号,目录结构为文件命名仅仅是为了便于人们使用。
UNIX和Linux中比较重要的设备文件有3个:/dev/console
、/dev/tty
和/dev/null
。