查询当前终端属性:
$ stty -a
显示本地所有shell变量:
$ set
测试变量是否已设置:
$ echo ${VAR:-value} % 显示$VAR, 若未设置, 则显示value[注: $VAR的值不会变]
$ echo ${VAR:=value} % 显示$VAR, 若未设置, 则将$VAR设置为value
脚本中测试变量是否已设置并返回错误信息:
$ echo "The file is ${FILES:?" sorry cannot locate the variable file"}"
测试变量是否取值, 如果未取值则返回空串:
$ echo ${VAR:+value}
设置变量为只读:
$ readonly VAR
显示所有只读变量:
$ readonly
查看所有环境变量:
$ env
清除环境变量:
$ unset VAR
两个脚本间传递环境变量需导出(export)
脚本中引用命令行传来的参数:
$0 : 脚本名
$1 : 第一个命令行参数
$2 : 第二个....
$# : 传递给脚本的参数的个数
$* : 显示所有向脚本传递的参数
$$ : 脚本运行的当前进程的id号
$! : 后台运行的最后一共进程的PID
$@ : 同$#, 但使用时加引号, 并在引号中返回每个参数
$- : 显示shell使用的当前选项(同set)
$? : 显示最后退出的命令的状态, 0表示无错误, 其他值表明有错误
检测一条命令是否执行成功:
$ cp ok.txt /not/exist/dir >/dev/null 2>&1; echo $?
返回非0值表明有错.
文件状态测试:
[ condition ] % 注意条件两边要加空格
文件状态测试
-d 目录
-s 文件长度大于0、非空
-f 正规文件
-w 可写
-L 符号连接
-u 文件有suid位设置
-r 可读
-x 可执行
多个条件逻辑组合:
[ cond1 -a cond2 ] % 与
[ cond1 -o cond2 ] % 或
[ ! cond ] % 非
字符串测试:
[ "string1" !=/= "string2" ] % 测串是否相等
[ -z "string" ] % 空串
[ -n "string" ] % 非空串
在进行字符串比较时必须加引号, 即使是在比较环境变量也要加.
数值测试:
[ "num1" OP "num2" ]
其中OP可以为:
-eq 数值相等。
-ne 数值不相等。
-gt 第一个数大于第二个数。
-lt 第一个数小于第二个数。
-le 第一个数小于等于第二个数。
-ge 第一个数大于等于第二个数。
expr作为计算器:
$ expr 1 + 2 % - / 均可
$ expr 2 \* 2 % 乘法的*号要加\
增量计数:
$ LOOP=0
$ LOOP=`expr $LOOP + 1`
退出脚本:
exit n % n为返回数值
流控制:
if cond1
then
command1
elif cond2
then
command2
else
command3
if
#!/bin/sh
if grep 'tfj' file > /dev/null 2>&1
then
echo "good, tfj found!"
else
echo "damn, he's not here!"
fi
空命令":"
case语法:
case VALUE in
pattern1)
commands
;;
pattern2)
commands
;;
*) % 类似C中的default
commands
;;
esac
pattern中也可以使用多个pattern相或, 如:
case N in
1|2) echo "less than 3"
;;
esac
for循环:
for 变量名 in 列表
do
command1
command2
done
[*注意*]: for循环对命令只执行1次!
$ for loop in "1 2 3"; do echo "I'm $loop"; done
I'm 1 2 3
而不是输出
I'm 1
I'm 2
I'm 3
这是与C等语言不同的地方!!
当for语句中省略in 列表时, 将使用命令行参数
until循环: 执行命令直到条件为真时停止
until condition
do
commands
done
#!/bin/sh
a=5
until [ "$a" -eq "0" ]
do
echo "$a"
a=`expr $a - 1`
done
5
4
3
2
1
$ more until_lck.sh
#!/bin/sh
LOCK_FILE=/tmp/process.lck
until [ ! -f $LOCK_FILE ]
do
sleep 1
done
echo "file deleted"
上述例子是使脚本与其他处理过程协调工作的一种方法。还有另外一种方法使脚本间互
相通信。假定有另一段脚本p r o c e s s . m a i n用于搜集本地网络所有机器的信息并将之放入一个报
表文件。
当脚本p r o c e s s . m a i n运行时,创建了一个L C K文件(锁文件),上面脚本必须接收
p r o c e s s . m a i n搜集的信息,但是如果p r o c e s s仍然在修改报表文件时试图处理该文件就不太好
了。
为克服这些问题,脚本p r o c e s s . m a i n创建了一个L C K文件,当它完成时,就删除此文件。
上述脚本将挂起,等待L C K文件被删除,一旦L C K文件删除,上述脚本即可处理报表文
件。
while循环:
while condition
do
commands
done
从文件中读取:
while read lines
do
echo "$lines"
done < file.txt
break: 退出循环
continue: 继续下一个循环
shell中定义函数:
foo ()
{
body...
}
函数调用时直接使用函数名, 不需加括号
函数返回:
return N
在脚本中定义一个函数foo()
导入函数:
$ . ./func.sh
查看是否导入成功:
$ set
使用函数:
$ foo
撤销函数导入:
$ unset foo
cat << WORD
从stdin读取输入, 直到遇到WORD为止.
[*注意*]在脚本中使用时, 要注意匹配的WORD要从新行的首字符开始, 前面不能有空格!
osol:
$ echo -e "no new line attached. \c"
$ echo -n "test"
敲击单个键无需回车:
用dd读取键盘输入, 输入前要将用stty命令将终端设置成raw模式:
read_a_char ()
{
SAVEDSTTY=`stty -g`
stty raw
dd if=/dev/tty bs=1 count=1 2> /dev/null
stty -raw
stty $SAVEDSTTY
}
#!/bin/sh
echo "press any key to continue"
char=`read_a_char`
echo "you input $char"
shift: 向左移动命令行参数1个位置
显示所有命令行参数: (大于9个[$10认为是$1+0])
#!/bin/sh
loop=0
while [ $# -ne 0 ]
do
echo $1
shift
done
脚本一次处理多个文件时, 可利用shift将命令行传来的多个文件依次处理
显示命令行最后一个参数:
eval echo \$$#
getopts: 处理命令行多项参数
#!/bin/sh
ALL=false
HELP=false
FILE=false
VERBOSE=false
while getopts ahfv OPTION %这里, getopts把以-开头的参数认为是选项[对于不在ahfv中的参数, getopts会自己返回错误信息]
do
case $OPTION in
a) ALL=true
echo "ALL is $ALL"
;;
h) HELP=true
echo "HELP is $HELP"
;;
f) FILE=true
echo "FILE is $FILE"
;;
v) VERBOSE=true
echo "VERBOSE is $VERBOSE"
;;
esac
done
$ ./getopt1.sh -a -f
ALL is true
FILE is true
$ ./getopt1.sh -vg
VERBOSE is true
./getopt1.sh: -g: unknown option
如果某个参数后面需要加value, 例如getopt1.sh -a value, 则在a后面加:即可:
while getopts a:hfv OPTION
如果命令行未提供, 会提示:
./getopt1.sh: -a: argument expected
在整个选项前面加:可以屏蔽这条提示信息:
while getopts :a:hfv OPTION
$ ./getopt1.sh -a
$
没有提示信息, 此时可以在case中加入?项来提供自定义的提示信息:
case $OPTION in
...
?) echo "usage `basename $0` -a value [fhv] file"
;;
esac
...
$ ./getopt1.sh -a
usage getopt1.sh -a value [fhv] file
一般选项及对应的含义:
选项含义
- a 扩展
- c 计数、拷贝
- d 目录、设备
- e 执行
- f 文件名、强制
- h 帮助
- i 忽略状态
- l 注册文件
- o 完整输出
- q 退出
- p 路径
-v 显示方式或版本
tput:控制屏幕输出
常用选项:
bel 警铃
blink 闪烁模式
bold 粗体
civis 隐藏光标
clear 清屏
cnorm 不隐藏光标
cup x y移动光标到屏幕位置(x,y)
el 清除到行尾
ell 清除到行首
smso 启动突出模式
rmso 停止突出模式
smul 开始下划线模式
rmul 结束下划线模式
sc 保存当前光标位置
rc 恢复光标到最后保存位置
sgr0 正常屏幕
rev 逆转视图(反色)
cols 列数目
ittab设置宽度
lines 屏幕行数
chts 光标不可见
hs 具有状态行
set -n 读命令但并不执行。
set -v 显示读取的所有行。
set -x 显示所有命令及其参数。
times命令给出用户脚本或任何系统命令的运行时间。第一行给出shell消耗时间,第二行给出运行命令消耗的时间
type查询命令是否仍驻留系统及命令类型。type打印命令名是否有效及该命令在系统的位置。
$ type time
time is a shell keyword
$ type times
times is a shell builtin
$ type testt
bash: type: testt: not found
$ type cp
cp is /usr/bin/cp
wait命令等待直到一个用户子进程完成,可以在wait命令中指定进程ID号。如果并未指定,则等待直到所有子进程完成。
当shell看到<<的时候,它就会知道下一个词是一个分界符。在该分界符以后的内容都被当作输入,直到shell又看到该分界符(位于单独的一行)。这个分界符可以是你所定义的任何字符串。
# date +%A" "%e" "%B" "%Y
Friday 12 December 2008
# date +%R%p
14:16PM
tfengjun@shaseng:~# date +%T
14:16:38
信号信号名含义
0 EXIT 退出shell(ctrl-d)
1 SIGHUP 挂起或父进程被杀死
2 SIGINT 来自键盘的中断信号,通常是
3 SIGQUIT 从键盘退出
9 SIGKILL 无条件终止
11 SIGSEGV 段(内存)冲突
15 SIGTERM 软件终止(缺省杀进程信号)
查看信号:
$ kill -l
给进程发送信号:
$ kill -n PID % n为数字
$ kill -s SIGxxx PID
脚本中捕获信号:
trap "func" signal(s)
如:
trap "" 2 3 忽略信号2和3, 用户不能终止该脚本
trap "command" 2 3 如果捕捉到信号2和3, 就执行command命令
trap 2 3 复位信号2和3, 用户可以终止该脚本
eval:扫描文本并执行
$ STRING=date
$ eval $STRING
Friday, December 12, 2008 2:30:40 PM CST
向系统日志中写入信息:
$ logger -p notice|warning "string"
阅读(2471) | 评论(0) | 转发(0) |