shell编程-基础
1.linux 下 Bash 程序开
1.1 怎样写 shell 脚本
1.使用编辑工具编辑shell 脚本,例如 vim,脚本名字一般用.sh 为后缀,不用.sh 为后缀 时编辑的内容为全黑,不会有高亮突显命令与变量。
2.写完后设置脚本的执行权3.执行脚本,做测试,执行方式:./shell-name;bash shell-name ;sh shell-name
1.2 彩色 shell 的输出
1.echo -e 可以在控制台输出彩色字符
2.色彩:
前背景:30-37
后背景:40-47
0:黑 1:红 2:绿 3:黄 4:蓝 5:洋红 6:青 7:白
3.使用格式:
\033[3X;4ym 同时修改前景和背景颜色
\033[3Xm 只更改前景颜色
\033[4Xm 只更改背景颜色
\033[0m 还原前景和背景颜色,一定要记得还原哦!
1.3shell 中的变量
1.变量类型:
系统变量:由系统本身维护,通常为大写
自定义变量(UDV):用户创建和维护,通常小写
2.使用 set 来查看系统变量,$来调用变量
[root@desktop29 ~]# set
BASH=/bin/bash
BASH_ARGC=()
BASH_ARGV=() …… ……
3.自定义变量:
通过“变量名=值”来定义,等号之间没有空格,将右边的值赋给左边的变量,可以定义
空值,如:mony= ,等号右边没有任何值;mon="" ,引号中没有任何空格
命名规则:必须以字符或者_开头,不要使用?和*,区分大小写
4.实例:
[root@desktop29 ~]# UNAME=liudehua 定义变量
[root@desktop29 ~]# echo $UNAME 调用变量
liudehua
[root@desktop29 ~]# read UNAME 定义变量
liming
[root@desktop29 ~]# echo $UNAME
liming
1.4echo 命令
1.使用 echo 命令可以显示文本或变量的值:echo [选项] [字符、变量……]
2.选项:
-n 不换行输出,默认就是 echo 一次换一行,用在持续的打印输出
-e 启用转义字符解析
\a 响铃 \b 退格 \c 去除尾部的新行
\n 换行 \r回车 \t 水平制表符 \\斜杠
3.实例:
[root@desktop29 ~]# echo -e "HOST\t\tUSER\n172.24.24.23\t$UNAME"
HOST USER
172.24.24.23 liming
1.5shell 中数学计算
1.语法:expr 操作数 1 运算符 操作数 2(注意中间是要空格的!!)
2.运算符:+ 加;/除;%取余;\* 乘(需要转义)
3.实例:
[root@desktop29 ~]# expr 2 + 4
6
[root@desktop29 ~]# expr 2 / 4
0
[root@desktop29 ~]# UU=$(expr 2 \* 100)
[root@desktop29 ~]# expr $UU / 4
50
[root@desktop29 ~]# echo $UU
200
1.6 引号的使用
1.引号:
"" :双引号,对\做转义,对$的变量作解析
' ' :单引号,不做任何修
`` :斜点,用来执行命令
[root@desktop29 ~]# echo "$UU and date" #不能解读 date 命令,需要$来调用 200 and date [root@desktop29 ~]# echo "$UU and $(date)" 200 and Wed Oct 5 08:28:42 CST 2011 [root@desktop29 ~]# echo "$UU and \$(date)" #\转义了 200 and $(date) [root@desktop29 ~]# echo `$UU and date` bash: 200: command not found ``斜点不能对$作解析,里面只能使用命令 [root@desktop29 ~]# echo "$UU and `date`" 200 and Wed Oct 5 08:29:20 CST 2011 [root@desktop29 ~]# echo '$UU and date' #不做任何修改 $UU and date [root@desktop29 ~]# echo `date` Wed Oct 5 08:30:09 CST 2011 [root@desktop29 ~]# echo "expr 3 + 4 " expr 3 + 4 [root@desktop29 ~]# echo `expr 3 + 4 ` #先执行 bash 7 [root@desktop29 ~]# echo "$(expr 3 + 4 )" 7
1.7 退出和退出状态
1.在 linux 执行指令后,将返回 0:成功 非 0:不成功或有错
2.通过 echo $?来查看退出状态
[root@desktop29 ~]# ls /boot/grub/grub.conf /boot/grub/grub.conf [root@desktop29 ~]# echo $? #命令执行正确,返回 0 0 [root@desktop29 ~]# ls /boot/grub/grub.con ls: /boot/grub/grub.con: No such file or directory [root@desktop29 ~]# echo $? 命令执行不正确,返回非 0 2
1.8read 语法
1.read 作用:获得用户通过键盘输入的数据并保存到变量中
2.语法:read 变量 1 变量 2 ……
[root@desktop29 ~]# read TT HH tt hh [root@desktop29 ~]# echo $TT tt [root@desktop29 ~]# echo $HH hh [root@desktop29 ~]# echo "rr ff ss" |while read HH GG II > do > echo $HH > echo $GG $II > done rr ff ss [root@desktop29 ~]# echo $GG #显示是空 [root@desktop29 ~]#
1.9 通配符的使用
1.通配符的意义:
* :任何的字符出现 0 到多
? :任何一个字符
[]:括号内提供的字符选一个
[ - ]:括号内一段字符
[^ ]:括号内的都排除掉
[root@desktop29 ~]# ls /lib/libn*.so /lib/libnsl-2.5.so /lib/libnss_hesiod-2.5.so /lib/libnss_compat-2.5.so /lib/libnss_ldap-2.5.so …… …… [root@desktop29 ~]# ls /lib/lib?[abef]*.so /lib/libdb-4.3.so /lib/libdevmapper.so /lib/libdevmapper-event-lvm2mirror.so /lib/libkeyutils-1.2.so /lib/libdevmapper-event-lvm2snapshot.so /lib/libresolv-2.5.so /lib/libdevmapper-event.so /lib/libSegFault.so [root@desktop29 ~]# ls /lib/lib[^abefnd]*.so /lib/libBrokenLocale-2.5.so /lib/libm-2.5.so /lib/libSegFault.so /lib/libc-2.5.so /lib/libproc-3.2.7.so /lib/libthread_db-1.0.so /lib/libcidn-2.5.so /lib/libpthread-2.5.so /lib/libutil-2.5.so /lib/libcrypt-2.5.so /lib/libresolv-2.5.s
1.10 一行内执行多条命令
1.语法:命令 1;命令 2;命令 3;……
[root@desktop29 ~]# echo "ee" >> ff.txt;cp ff.txt d.t;rm ff.txt -f;echo $? 0 [root@desktop29 ~]# cat d.t ee [root@desktop29 ~]# cat ff.txt #被删了 cat: ff.txt: No such file or directory
1.11 命令行参数
参数可以有多个或者没有,如:
[root@desktop29 ~]# rm d.t -fv #2 个参数 removed `d.t' [root@desktop29 ~]# date #0 个参数 Wed Oct 5 09:20:15 CST 2011
特殊的参数:
-$#保存着命令后面所带的参数的总数
-$*或-$@将命令后的所有参数作为一个字符串保存
位置参数:
$0:命令本身;$1:命令后面的第一个参数;$n:该命令后面的第 n 个参数
测试位置参数和特殊的参数 [root@desktop29 ~]# vim dd.sh #!/bin/bash echo "\$0 : $0" echo "\$1 : $1" echo "\$2 : $2" echo "\$# : $#" echo "\$* : $*" [root@desktop29 ~]# chmod u+x dd.sh [root@desktop29 ~]# ./dd.sh root redhat $0 : ./dd.sh $1 : root $2 : redhat $# : 2 $* : root redhat
1.12shell 脚本中条件判断
1.返回 shell中 0(ture)或 1(flase)结果
if/then 结构
2.test 或者[]执行 shell 测试,返回 shell 结果。[]中写入测试条件,注意[空格 测
试条件 空格]
3.测试条件:
字符的比较
|
数字的比较
|
代表的意思
|
==
|
-eq | 相等 |
>
|
-gt | 大于 |
<
|
-lt | 小于 |
!=
|
-ne | 不等于 |
<=
|
-le | 小于等于 |
>=
|
-ge | 大于等于 |
-a:逻辑与,并且;-o:或者,逻辑或
4.bash2.02 版本以上[[……]]
5.返回常规编程语言格式的结果
((……))和 let……还可以做数字的比较
[root@desktop29 ~]# [ "qq" != "cc" ];echo $? 0 [root@desktop29 ~]# [ 100 -eq 12 ];echo $? 1 [root@desktop29 ~]# echo "100 / ( 5 + 5)" | bc 10
1.13 测试文件或文件夹属性
1.常见判断
-a 文件是否存在
-b 文件是否为块设备
-d 文件是否为目录
-s 文件大小是否为 0
-r 文件是否可读
-w 文件是否可写
-x 文件是否可执行
#man bash 获得更多解释
[root@desktop29 /]# touch ff [root@desktop29 /]# chmod 111 ff [root@desktop29 /]# su - student root #用户则测不出文件的 r,w,x 属性 [student@desktop29 ~]$ [ -w /ff];echo $? 1 [student@desktop29 ~]$ [ -f /ff ];echo $? 0 [student@desktop29 ~]$ [ -x /ff ];echo $? 0 [student@desktop29 ~]$ [ -d /ff -a -x /ff ];echo $? #-a 是and,非目录,所以为 1 1
实例:写一个脚本判断目录下的文件和目录的属性,并打印:
[student@desktop29 ~]$ cat ds.sh #!/bin/bash echo -e "please input a doc\nexample /etc" read DD D=directory F=file for RR in $DD/* do if [ -d $RR ];then if[ -w $RR -a -r $RR -a -x $RR ];then echo -e "$RR\t\t$D-rwx" else if [ -w $RR -a -r $RR ] ;then echo -e "$RR\t\t$D-wr" else if [ -w $RR -a -x $RR ] ;then echo -e "$RR\t\t$D-wx" else if [ -x $RR -a -r $RR ] ;then echo -e "$RR\t\t$D-xr"else if[ -w $RR ] ;then echo -e "$RR\t\t$D-w" else if [ -r $RR ] ;then echo -e "$RR\t\t$D-r" else if[ -x $RR ] ;then echo -e "$RR\t\t$D-x" fi fi fi fi fi fi fi else if [ -f $RR ] ;then if [ -w $RR -a -r $RR -a -x $RR ];then echo -e "$RR\t\t$F-rwx" else if[ -w $RR -a -r $RR ] ;then echo -e "$RR\t\t$F-wr" else if [ -w $RR -a -x $RR ] ;then echo -e "$RR\t\t$F- wx" else if [ -x $RR -a -r $RR ] ;then echo -e "$RR\t\t$F- xr" else if[ -w $RR ] ;then echo -e "$RR\t\t$F- w" else if [ -r $RR ] ;then echo -e "$RR\t\t$F- r" else if[ -x $RR ] ;then echo -e "$RR\t\t$F- x" fi fi fi fi fi fi fi fi fi done
1.14if……else……fi
语法:
if[判断条件]
then
命令 1
命令 2
else
命令 3
命令 4
fi
实例:依据钱数决定吃快餐或吃 KFC之 if-else-fi 版 编辑脚本: [root@localhost ~]# vim eat.sh #!/bin/bash echo " money :" read FF if [ $FF -lt 5 ];then echo "fastfood" else echo "KFC" fi 修改权限 [root@localhost ~]# chmod u+x eat.sh 测试 [root@localhost ~]# ./eat.sh money : 4 fastfood [root@localhost ~]# ./eat.sh money : 6 KFC
1.15&&和||以及[[……]]
1.&&与运算,||或运算,不能使用在[……]之间,只能使用在[[……]]之间
2.单独使用,&&代表之前的条件 true 时,||代表之前的条件 false
3.[[……]]这是一个扩展测试命令,使用该命令可以防止在脚本中出现的逻辑错误信息,如
&&、||、<和>;在[[……]]可以自动计算十进制和 8/16 进制的值
1.&&在[]与[[]]之间的区别: [root@localhost ~]# [[ -d /tmp && -w /tmp ]];echo $? 0 [root@localhost ~]# [ -d /tmp && -w /tmp ];echo $? bash: [: missing `]' 2
2 依据钱数决定吃快餐或吃 KFC-逻辑符号版 #!/bin/bash echo " money :" read FF [ $FF -lt 5 ] && echo "fastfood" || echo "KFC" 测试: [root@localhost ~]# ./eat.sh money : 5 KFC [root@localhost ~]# ./eat.sh money : 1 fastfood
1.16if 语句的直接使用
if 语句可以直接接 shell语句,根据$?判断:
[root@localhost ~]# cat if_shell.sh #!/bin/bash D=/etc if cd $D &> /dev/null;then #直接接 shell 命令 echo "now in $D" else echo "can't change to $D" fi [root@localhost ~]# ./if_shell.sh now in /etc
1.17if 语句的嵌套
实例:菜单项的选择之 if 嵌套版,
选择1,2,3来显示进入的状态,如果没有输入则打印what do you like?,如果输入的不
是 1,2,3 中的一个,则打印 please choose:1,2,3 并退出
[root@localhost ~]# cat mu.sh #!/bin/bash echo "please choose:1,2,3" echo "1.linux" echo "2.win7" echo "3.quit" read CH if [ "$CH" != "" ];then if [ $CH -eq 1 ] ;then echo " wellcom to linux" else if [ $CH -eq 2 ];then echo "wellcom to win7" else if [ $CH -eq 3 ];then echo "quit" else echo "please choose 1,2,3" fi fi fi else echo "what do you like?" fi 测试: [root@localhost ~]# ./mu.sh please choose:1,2,3 1.linux 2.win7 3.quit what do you like? [root@localhost ~]# ./mu.sh please choose:1,2,3 1.linux 2.win7 3.quit 1 wellcom to linux
1.18if……then……elif
多级 if……then……else 可以替换 if 的嵌套使用,直接使用一个或多个测试条件
将菜单项的选择作修改: #!/bin/bash echo "please choose:1,2,3" echo "1.linux" echo "2.win7" echo "3.quit" read CH if [ "$CH" != "" ];then if [ $CH -eq 1 ] ;then echo " wellcom to linux" elif [ $CH -eq 2 ];then echo "wellcom to win7" elif [ $CH -eq 3 ];then echo "quit" else echo "please choose 1,2,3" fi else echo "what do you like?" fi
1.19exit 退出代码
shell脚本执行后如果不成功则会返回一个非0 的值,exit 可以实现脚本退出时返回值,我们可以根据不同的返回值看出是哪个脚本出现问题。
实例:如果用户输入的是目录,则返回值为 1,如果不是则返回 4 #!/bin/bash echo -e "input a dir\nexample /etc" read DD if [ -d $DD ];then echo " $DD is a directory" exit 1 else echo "$DD is not a directory or not exit" exit 4 fi 测试: [root@localhost ~]# ./exit.sh input a dir example /etc /etc /etc is a directory [root@localhost ~]# echo $? 1 [root@localhost ~]# ./exit.sh input a dir example /etc /dd /dd is not a directory or not exit [root@localhost ~]# echo $? 4
1.20 loop 循环
1.循环的定义:计算机可以重复的执行特定的指令,知道给定的条件满足为止。
2.bash 中的循环:for loop ;while loop
3.注意:
每个循环使用时,首先用在循环中的变量要在循环之前初始化,然后对每次循环都要对
条件测试,最后在循环体中执行一次需要对循环测试条件值修改
1.21 for loop
语法:
for 变量名 in 列表
do
循环体
done
列表时一个集合,集合由空格间隔,可以是以下几中:
数字/字符集合
1 2 3 6 7
{1..254}
文件集合
/etc/*.conf
指令结果集合
$(find /etc -perm -002)
实例: 1.数字集合 99 乘法表: #!/bin/bash for A in {1..9} do for B in {1..9} do RE=$( expr $A \* $B ) echo " $A * $B = $RE " done done 测试: [root@localhost ~]# ./9X9.sh 1 * 1 = 1 …… …… 3 * 1 = 3 …… …… 9 * 9 = 81
用脚本编辑 iptables 规则脚本:
#!/bin/bash echo "#!/bin/bash" >> /bin/setFilewall.sh for IP in {1..254} do echo "iptables -I INPUT -s 192.168.0.$IP -p tcp --dport 80 -j ACCEPT" >> /bin/setFilewall.sh echo "iptables is making..." done 测试: [root@localhost ~]# ./iptables.sh iptables is making... iptables is making... ………… [root@localhost ~]# tail /bin/setFilewall.sh -n 2 iptables -I INPUT -s 192.168.0.253 -p tcp --dport 80 -j ACCEPT iptables -I INPUT -s 192.168.0.254 -p tcp --dport 80 -j ACCEPT
2.文件集合
for FF in /root/cc/* do cp $FF $FF.bak -pv done 测试: [root@localhost ~]# ./chmod_cc.sh `/root/cc/1.cc' -> `/root/cc/1.cc.bak' `/root/cc/2.cc' -> `/root/cc/2.cc.bak' …… ……
3.指令集合的实验
#!/bin/bash for FF in $(find /root/cc -perm +002) do chmod o-w $FF echo "$FF :o-w" done
1.22 for 循环 c 语言格式
((……))不需要使用$来实现对 shell 变量名的调用。特别要注意的是此类语法的逻辑和
shell截然相反,在(())中,0 代表 false,所有非 0 代表 true 例如:
1.
for ((i = 0;i<= 5;i ++))
do
echo "welcome $i times "
done
建议不要使用在 if-then 中
2.if(( UID > 0 )) ; then ; echo " Welcome root " ; fI
例子:
国际象棋棋盘:算法(行和列号相加后的结果对 2 取余,为 0 的就是白色块,不为 0 的就
是黑色块。)
#!/bin/bash for ((A=1;A<=9;A++)) 等同于 for A in {1..9} do for ((B=1;B<=9;B++)) do C=$( expr $A + $B ) D=$( expr $C % 2 ) #取余运算 if [ $D -eq 0 ];then echo -en "\033[30;40m \033[0m" else echo -en "\033[37;47m \033[0m" fi done echo -e done
1.23for 循环的练习
练习:编辑一个监控服务器的脚本,将信息显示在屏幕上,错误信息记录在日志里:
for FF in $(cat /etc/ser.conf | grep -Ev "^(#|$)" ) do #if 后不能用[ping -c2 $FF &> /dev/nul],无论能否 ping 通,返回结果都是非 0 if ping -c2 $FF &> /dev/nul ;then echo "$FF is up..." else echo "$FF is down..." logger "$FF is down ..." fi done
1.24while 循环
语法:
while [ 条件测试 ]
do
命令
done
注意:要修改测试条件的值,防止死循环,可以与 if-then-fi嵌套使用,用 exit 函数退出
实例:
CHOOSE=0 while [[$CHOOSE != "Q"&& $CHOOSE != "q" ]] do if (( CHOOSE !="0" )) ; then echo -e "Please input \033[33mq \033[0m to quit" sleep 4 fi clear echo " 1 . Linux " echo " 2 . Uni x " echo " Q .Qui t " read CHOOSE echo "Please Input \033[ 33mq \033[0m to quit " done
练习:实现菜单选择,如果选择错误则重新显示菜单,直到选对。
#!/bin/bash IN=0 while [ "$IN" != "3" ] do echo "1.linux" echo "2.windows" echo "3.quit" read IN if [ $IN -eq 1 ];then echo "wellcom to linux" exit 1 elif [ $IN -eq 2 ];then echo "wellcom to windows" exit 2 elif [ $IN -eq 3 ];then exit 3 else #选错了就会清屏后提示 please input 1\2\3 并打印菜单 clear echo "please input 1\2\3" fi done
1.25case 语句
case 语句是 if-then-elfi的替代语句 语法:
case 变量名 in
匹配 1) 命令;;
匹配 2) 命令;;
匹配 3) 命令;; *) 命令;;
esac
实例:
PIDFIL E=/var/spool /test . pid case $1 in " start") if [ - e $PIDFILE ] ; then echo " the testcase has already run" else echo $$ > $PIDFILE ; echo " starting now. . . " fi ;; " stop") kill -9 $( cat $PIDFILE ) ; rm - f $PIDFILE ; ; " status") .... *) # 默认值, 匹配所有上面没有给定的值 echo " Usage : /etc/init.d/testcase (start|stop|status) ";; esac
练习:写一个自己的服务,能像其他服务一样用 chkconfig 开启:
#!/bin/bash #chkconfig: 345 45 67 #这 2 行必须要有才能被 chkconfig 解读 #description: this is myserver case $1 in start) echo "myserver is started...";; stop) echo "myserver is stoped...";; *) echo " $0 { start|stop}" esac 修改执行权限 [root@localhost ~]# chmod u+x myserver.sh 2.复制到/etc/init.d 下,并修改名字 [root@localhost ~]# cp myserver.sh /etc/init.d/myserver 测试: [root@localhost ~]# chkconfig myserver on [root@localhost ~]# chkconfig --list | grep myserver myserver 0:off 1:off 2:on 3:on 4:on 5:on 6:off [root@localhost ~]# /etc/init.d/myserver start myserver is started...
1.26 如何调试脚本
-v:打印 shell脚本执行的行号 [root@localhost ~]# bash -v testvx.sh #将整个脚本都展示出来,并执行 #!/bin/bash echo "plese input a number" plese input a number read N 3 R=$( expr $N \* $N ) expr $N \* $N echo "$N * $N = $R " 3 * 3 = 9 -x:对每一个指令作展开计算 [root@localhost ~]# bash -x testvx.sh #用++与+来区分计算和非计算 + echo 'plese input a number' plese input a number + read N 5 输入 ++ expr 5 '*' 5 + R=25 + echo '5 * 5 = 25 ' 5 * 5 = 25 脚本计算的结果
1.27 函数的使用
函数是一系列的指令或命令
本身不运行,可以多次调用,简化代码
语法:
函数名 ()
{
命令 1;命令 2
return #返回值
}
函数的参数:
函数也可以作为一个程序一样运行,接收参数
方式:函数名 参数 1 参数 2
在函数方法体中参数可以用$1、$2 来表示对应的参数 1、参数 2
实例:
max ( ) { if(( $1 > $2 )); then return $1 # 注意, 此时函数已经结束了 fi return $2 } max 10 100 echo $? # 通过 $ ? 取得函数的返回值
setPath ( ) { PAT H=/bin:/usr/bin if (( $UID == 0 )) ; then # 如果为 root PATH = $PATH:/usr/bin/sbin:/sbin # 路径追加 sbin 的目录 fi i f (( $2 == "after" )); then # 根据位置参数 2,决定如何添加新路径 PATH = $PATH:$1 # 在原 PATH 后面追加 else PATH=$1:$PATH # 在原 PATH 之前添加 fi }
练习 1:结合之前学的语言,使用函数的方式,编写一个菜单选项的脚本,能实现选择菜单
并执行该菜单的功能:
#!/bin/bash showmanu () #展示菜单的函数 { echo -e "1.linux\n2.windows\n3.quit" read IN } testchoose () #测试用户输入选项的函数 { if [ $IN -eq 1 ] ;then echo "wellcom to linux" exit 1 elif [ $IN -eq 2 ] ;then echo "wellcom to windows" exit 2 elif [ $IN -eq 3 ] ;then exit 3 else clear echo "please input 1\2\3" fi } main () #当选择错误时,需要循环的显示菜单和测试用户输入的选项 { IN=0 while [ "$IN" != "3" ] do showmanu #调用菜单函数 testchoose #调用测试选项函数 done } main #调用函数
练习 2:在一个脚本中调用其他脚本:
脚本 1:f.sh
#!/bin/bash echo "---脚本 1---" echo "test server..."
脚本 2:ff.sh
#!/bin/bash [ $# -eq 1 ] && ( for F in $1/* do [ -d $F ] && echo "$F is a directory" done ) || echo "please input a right directory"
调用测试脚本:
#!/bin/bash F=/root/f.sh FF=/root/ff.sh menu () { echo -e "1.testServer\n2.findDir\n3.quit" } main () { menu read INPUT case $INPUT in 1) bash $F ;; 2) bash $FF /etc #调用时,可以带参数 ;; 3) exit -1 ;; *) clear #清屏 main #调用 main 函数 esac } main
1.28I/O 重定向和文件描述
• Linux 经常使用到的 1>,>, &>重定向,各自代表着标准输出,标准错误,以及两者
都包括(1&&2)
• Linux 同时除以上的几个重定向外提供给我们0-10 的其他文件描述(File Description:
FD)
• 它可以用来对前者的信息做一备份 ,之后再重新调用其信息
1.29 重定向的高级应用
>&n 使用系统调用 dup(2)复制文件描述符 n 并把结果用作标准输出;
<&n 标准输入复制自文件描述符 n;
<&- 关闭标准输入(键盘);
>&- 关闭标准输出;
n<&- 表示将 n 号输入关闭;
n>&- 表示将 n 号输出关闭;
上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的
0 或 1。如:
. .. 2>file 运行一个命令并把错误输出(文件描述符 2)定向到 file。
. .. 2>&1 运行一个命令并把它的标准输出和输出合并。(通过复制文件描述符 1 来建立
文件描述符 2,合并了两个流。)
2>&1 也就是 FD2=FD1 ,把 FD2 的“数据输出通道” 改为 FD1 的“数据输出通道”。因
为 FD2 的默认输出和 FD1 的默认输出本来都是 monitor,一样的!
exec 1>outfilename # 打开文件 outfilename 作为 stdout。
exec 2>errfilename # 打开文件 errfilename 作为 stderr。
exec 0<&- # 关闭 FD0。
exec 1>&- # 关闭 FD1。
exec 5>&- # 关闭 FD5。
exec 3>&1; exec 4>&1 #建立FD3; 把 FD3看作最初始的 FD1 的硬盘备份
ss=$(((ls you no 2>&1 1>&3 3>&-; echo $?>&4)|egrep \ >file) 4>&1)*exec 3>&-; exec 4>&- #关闭 FD3、FD4。