Linux系统管理与服务器配置这本书上,在228页第17章。。。 我是这么做的,大家可以参考参考。。?在网上搜索Linux的Shell相关知识简要描述几种主流的shell及特点;答:Linux是由UNIX演化而来的,从而也继承了UNIX的sell,在大部分的UNIX系统。三种著名且广被支持的Shell是:Bourne shell(AT&T shell,在Linux下是BASH),C shell(Berkeley shell,在Linux下是TCSH),Korn shell(Bourne shell的超集)。三种shell各有优缺点Bourne shell是标准的UNIIX shell,是UNIX最初使用的shell,并且在每种UNIX上都可以使用,常被用来作为管理系统之用,它简洁,快速,多用于shell编程方面,但与用户的交互性较差C shell是一种比Bourne shell更适于编程的shell,它的语法与C语言很相似。 Linux为喜欢使用C shell的人提供了Tcsh。Tcsh是C shell的一个扩展版本,Linux下的C shell则更多的考虑到了用户界面的而友好性,它支持不少新功能。例如:提供了一个命令列(command line)编辑程序,提供了命令列不全功能,提供了拼写更正功能。它能自动检测并更正在命令列拼错的命令或单字;危险命令侦测并提醒的功能,避免用户小心执行rm*这种杀伤力极大的命令;提供常用命令的快捷方式BASH shell是Linux下对Bourne shell向下兼容的一种shell,并融入许多C shell与Korn shell的功能
最常见的有:Born shell: 最早,所有的Unix和Linux上肯定都能用csh: 与C语言有些像,如果会C, 这个肯定觉得很容易ksh: Korn shell, 比上两种要好。特别是可以修改指令行(command line editing), 真是不可少。bash: Born again shell, 改进版的Born shell。大概是Linux上最常用的个人认为从ksh或bash中选一即可。
什么是shell script 将OS命令堆积到可执行的文件里,由上至下的顺序执行文本里的OS命令 就是脚本了. 再加上些智能(条件/流控)控制,就变成了智能化脚本了.变量 变量声明 bash中的变量无须声明,拿来就用.类型会根据赋予的值来决定 a=abc b=123 c=(123) d=$(uname -r) unset a declare -p var_name 可以查看 引用变量 在变量名前加上 $ 符号 echo $a 作用范围 全局 export var=abc . 或 source 局部 子进程中 函数中操作符 算术操作 + - * / % 关系操作 < > <= >= == != && || 测试操作 测试命令 test [ ] [[ ]] (( )) 1、测试文件状态 -d 目录 -s 文件长度 > 0、非空 -f 正规文件 -w 可写 -L 符号连接 -u 文件有 suid 位设置 -r 可读 -x 可执行$ [ -w tmp.txt ] $ echo $? 02、字符串测试 = 两个字符串相等 != 两个字符串不相等 -z 空串 -n 非空串$ VAR1='abc' $ VAR2='123' $ [ '$VAR1' = '$VAR2' ] $ echo $? 13、测试数值 -eq 等于 -ne 不等于 -gt 大于 -lt 小于 -ge 大于等于 -le 小于等于4. 拓展测试符号 [[ ]] (()) 数字测试符号 # [ 10 < 2 ] # 语法错误 -bash: 2: 没有那个文件或目录 # # [[ 2 > 10 ]] # 结果错误 # echo $? 0 # [[ 20 > 10 ]] # 正确 # echo $? 0 # (( 10 < 20 )) # echo $? 0字符测试 # [ "aa" = "aa" ] # echo $? 0 # [[ "aa" = "aa" ]] # echo $? 0 # (( "aa" = "aa" )) #结果错误 # echo $? 1 混合测试 # [ a = a -a 10 < 20 ] -bash: 20: 没有那个文件或目录结论: 比较数字,使用(( )) 其他测试使用 [[ ]] 包含数字比较的混合测试,使用标准语法流控结构 if 分支结构 # cat my.sh #!/bin/bashvar=/etc/init.d if [[ -d $var ]] then echo "$var is directory." elif [[ -b $var ]] then echo "$var is block device." elif [[ -f $var ]] then echo "$var is a regular file." else echo "unknow." fi # 除了 -L -h 等于的文件测试遇到软连接都会用原文件测试 if 测试中还可以执行命令 根据命令的返回值做判断 # if cd / ;then echo Y ;fi # if grep -q root /etc/passwd ;then echo Y ;fi 向脚本传递参数 # vim 2.sh #!/bin/bashecho '$0' $0 echo '$1' $1 echo '$2' $2 echo '$3' $3 echo '${10}' ${10} echo '${11}' ${11} echo '${12}' ${12} echo '$$' $$ echo '$*' $* echo '$@' $@ echo '$#' $# echo '$?' $? # $@ $* 在双引号(软引用)参数中有差异,$@会将引号内的多个参数当成一个参数,这会影响到$#的数量修改脚本从参数中传递测试文件 # cat 1.sh #!/bin/bashif [[ -d $1 ]] then echo "$1 is directory." elif [[ -b $1 ]] then echo "$1 is block device." elif [[ -f $1 ]] then echo "$1 is a regular file." else echo "unknow." fi#讲讲for i in 语法 检查内网存活的IP #!/bin/bashfor i in {1..254} do (ping -W 1 -c 1 192.168.1.$i &> /dev/null && echo 192.168.1.$i) & done让文件测试脚本支持多个参数 # vim 1.sh #!/bin/bashfor i in $@ do if [[ -d $i ]] then echo "$i is directory." elif [[ -b $i ]] then echo "$i is block device." elif [[ -f $i ]] then echo "$i is a regular file." else echo "unknow." fi done修改脚本使脚本最多支持3个参数,多个参数或0个参数报错,并退出脚本. [[ $# > 3 || $# = 0 ]] && echo "USAGE: $0 ERROR" && exit 1使用测试修改脚本告诉用户错误原因.case 结构语法 用户登录欢迎 # cat 4.sh #!/bin/bashcase $1 in root) echo "welcome $1" ;; seker) echo "welcome $1" ;; *) echo "no user $1" esac添加上与用户交互的功能 read -p "username: " uname如果等待时间内用户没输入 则采用默认值 read -p "username: " -t 5 uname echo if [[ -z $uname ]] then uname=default ficase $uname in root) echo "welcome $uname" ;; seker) echo "welcome $uname" ;; default) echo "welcome $uname" ;; *) echo "no user $uname" esac再修改脚本 让用户输入密码 然后比对密码是否一致,如果不一致,则不显示欢迎信息 #cat 4.sh # read -p "username: " -t 5 uname echo stty -echo read -sp "password: " paswd stty echo echoif [[ -z $uname ]] then uname=default ficase $uname$paswd in 'root111') echo "welcome $uname" ;; 'seker222') echo "welcome $uname" ;; 'default333') echo "welcome $uname" ;; *) echo "no user $uname" esac # case的字符测试还可以使用 | 结构 例如: a|b) 启动脚本循环结构 while 语法 while (条件) do 动作 done需要无限循环时我们会选择while : 写个脚本 让用户输入,输入数字通过,输出错误重新输入 #!/bin/bashretry=0 while [ $retry -eq 0 ] do read -p "enter a num : " aa if expr $aa + 0 &> /dev/null then echo OK.. retry=1 else echo "enter error.retry.." fi done# cat 5.sh #!/bin/bashi=1 while (( $i < 10 )) do echo $i ((i++)) done #until 循环# cat 6.sh #!/bin/bashi=1 until ! (( $i < 10 )) do echo $i ((i++)) done # until是条件为假时进入循环 # while是条件为真时进入循环 # 对until条件取反 则等同于 whileC语言格式的for for ((i=1;i<=10;i++)) do echo $i done shell格式的for for i in {1..10} do echo $i done循环控制 # for i in {1..10};do [ $i -eq 5 ] && continue || echo $i;done # for i in {1..10};do [ $i -eq 5 ] && break || echo $i;doneshift命令 # cat 8.sh #!/bin/bashwhile (($# != 0)) do echo $1 shift done统计/dev下每种类型文件的数量 向脚本传递一个用户名,验证这个用户是否存在. 添加30个用户,再将它们删除 将$PATH中的找出所有加了SUID位的文件 FTP自动下载脚本自定义函数1.函数定义 shell允许将一组命令集或语句形成一个可用块,这些块称为shell函数 定义函数的格式:function-name (){ command1 ........ } 或 function function-name(){ #函数名前面多了个function关键字 command1 ........ }2.函数调用 以下是一个函数的脚本实例: #!/bin/bash #hello function hello(){ #声明函数 echo "Hello!" #函数的主体,输出"Hello!" } #函数结束 hello #调用函数3.参数传递 向函数传递参数就像在脚本是使用变量位置$1,$2,$3...$9 以下是一个传递参数的实例: #!/bin/bash #hellofun function hello(){ echo "Hello! The first parameter is '$1'." } hello good #该脚本执行的结果是: Hello! The first parameter is 'good'.4.函数文件 保存函数的文件,用以上的例子写成一个函数文件如下: #!/bin/bash #hellofunction function hello(){ echo "Hello!" return 1 } 上面的hellofunction文件就是一个函数文件,可通过另一个脚本来调用 #!/bin/bash #hellof . hellofunction #注意点和hellofunction之间有个空格 hello5.载入和删除 用set查看已载入的函数 用unset function-name 取消载入 举例如下:#!/bin/bash #hellof . hellofunction unset hello hello #因为已经取消载入。。所以会出错6.函数返回状态 #!/bin/bash #hellofun function hello(){ echo "Hello! The first parameter is '$1'." return 1 } hello echo $? #输出返回的状态值(一般成功是返回0,其它值为失败)回收站 删[root@stu254 dir]# cat /bin/del #!/bin/bashmkdir -p ~/.trashfor i in $*do $echo $i mv -f $i ~/.trash done &> /dev/null[root@stu254 dir]# 回收站 恢复[root@stu254 dir]# cat /bin/undel #!/bin/bashfor i in $*do find ~/.trash -maxdepth 1 -name "$i" -exec mv {} . \;done[root@stu254 dir]# 数组数组就是若干个变量组合在一起 每个变量的值都是数组的元素 元素都在数组中有一个下标 下标从0开始数组赋值:[root@stu254 dir]# ary=(root seker zorro blues pg)取值方法: 第一个元素[root@stu254 dir]# echo ${ary[0]}root[root@stu254 dir]# 第三个元素[root@stu254 dir]# echo ${ary[2]}zorro[root@stu254 dir]# 所有元素[root@stu254 dir]# echo ${ary[*]} ; echo ${ary[@]}root seker zorro blues pgroot seker zorro blues pg[root@stu254 dir]# [root@stu254 dir]# 第二个到第四个元素[root@stu254 dir]# echo ${ary[*]:1:3}seker zorro blues[root@stu254 dir]# 下标大于等于2的所有元素[root@stu254 dir]# echo ${ary[*]:2}seker zorro blues pg[root@stu254 dir]# 下标小于2的所有元素[root@stu254 dir]# echo ${ary[*]::2}root seker[root@stu254 dir]# 元素个数[root@stu254 dir]# echo ${#ary[*]}5最后一个元素[root@stu254 dir]# echo ${ary[$((${#ary[*]}-1))]}4pg倒数第2个元素[root@stu254 dir]# echo ${ary[$((${#ary[*]}-2))]}3blues[root@stu254 dir]# for批量对数组赋值[root@stu254 dir]# ary=($(for i in {0..99};do echo $RANDOM;done))[root@stu254 dir]# echo ${#ary[*]}100打印数组中所有的奇数和偶数用数组个数中的奇数值覆盖偶数值,例如第1个元素覆盖第2个 第3个元素覆盖第4个元素从文件中读取每行赋予一个数组的方法生成随机数 赋予数组 进行排序找出/etc/下最新的文件和最旧的文件 modify time变量测试 ${var-value} 和 ${var:-value} - 号 如果变量设置为空则返回空值 :-号 如果变量设置为空则返回临时值 变量没声明 则临时赋值,否则使用原值[root@stu254 ~]# [root@stu254 ~]# unset var[root@stu254 ~]# echo ${var-value}value[root@stu254 ~]# echo ${var:-value}value[root@stu254 ~]# var=123[root@stu254 ~]# echo ${var-value}123[root@stu254 ~]# echo ${var:-value}123[root@stu254 ~]# var=""[root@stu254 ~]# echo ${var-value}[root@stu254 ~]# echo ${var:-value}value[root@stu254 ~]# + 号 如果变量[root@stu254 ~]# unset var[root@stu254 ~]# echo ${var+value}[root@stu254 ~]# echo ${var:+value}[root@stu254 ~]# var=123[root@stu254 ~]# echo ${var+value}value[root@stu254 ~]# echo ${var:+value}value[root@stu254 ~]# var=""[root@stu254 ~]# echo ${var+value}value[root@stu254 ~]# echo ${var:+value}[root@stu254 ~]#