CentOS6.x以前版本的系统服务启动接口在/etc/init.d/目录下,存放了脚本。
Shell脚本因调用外部命令和bash 的一些默认工具,速度较慢,不适合处理大量运算。
执行方式有:直接命令执行、绝对路径/相对路径执行、PATH执行、bash程序执行。
PATH中含有家目录的bin路径,可以在bin下写的脚本直接执行。
sh file
#!/bin/bash加载环境相关的配置文件,一般指代非登录的~/.bashrc
输入姓名并输出:
1 read -p "Please input your first name: " firstname # 提示使用者输入 2 read -p "Please input your last name: " lastname # 提示使用者输入 3 echo -e " Your full name is: $firstname $lastname" # 结果由萤幕输出
建立以前天,昨天,今天有关的文件名:
1 echo -e "I will use 'touch' command to create 3 files." # 纯粹显示资讯 2 read -p "Please input your filename: " fileuser # 提示使用者输入 3 4 # 2. 为了避免使用者随意按 Enter ,利用变量功能分析档名是否有配置? 5 filename=${fileuser:-"filename"} # 开始判断有否配置档名 6 7 # 3. 开始利用 date 命令来取得所需要的档名了; 8 date1=$(date --date='2 days ago' +%Y%m%d) # 前两天的日期 9 date2=$(date --date='1 days ago' +%Y%m%d) # 前一天的日期 10 date3=$(date +%Y%m%d) # 今天的日期 11 file1=${filename}${date1} # 底下三行在配置档名 12 file2=${filename}${date2} 13 file3=${filename}${date3} 14 15 # 4. 将档名创建吧! 16 touch "$file1" # 底下三行在创建文件 17 touch "$file2" 18 touch "$file3"
简单加减乘除:
1 echo -e "You SHOULD input 2 numbers, I will cross them! " 2 read -p "first number: " firstnu 3 read -p "second number: " secnu 4 total=$(($firstnu*$secnu)) 5 echo -e " The result of $firstnu x $secnu is ==> $total"
求余运算示例:echo $(( 13 % 3 ))
乘法运算的另一种方式:declare -i total=$firstnu*$secnu
计算含小数点的数据:echo "123.123*55.9" | bc
计算π值:echo "scale=10; 4*a(1)" | bc -lq#调用了4*a(1)函数,计算π并取小数点后10位。
直接执行的bash(绝对路径相对路径或PATH等),执行中的赋予新的子进程bash,使用子进程的bash配置,变量为局部变量。
利用source 来执行的脚本,变量成为全局变量。
test命令的测试功能:
如 test -e /home && echo "ok" || echo "no"检查目录是否存在
1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否
http://cn.linux.vbird.org/linux_basic/0340bashshell-scripts_3.php
判断文件类型和权限:
1 echo -e "Please input a filename, I will check the filename's type and 2 permission. " 3 read -p "Input a filename : " filename 4 test -z $filename && echo "You MUST input a filename." && exit 0 5 # 2. 判断文件是否存在?若不存在则显示信息并结束脚本 6 test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0 7 # 3. 开始判断文件类型与属性 8 test -f $filename && filetype="regulare file" 9 test -d $filename && filetype="directory" 10 test -r $filename && perm="readable" 11 test -w $filename && perm="$perm writable" 12 test -x $filename && perm="$perm executable" 13 # 4. 开始输出资讯! 14 echo "The filename: $filename is a $filetype" 15 echo "And the permissions are : $perm"
[ ] 判断符号
[ ]两端需要空格分隔,每个组件空格分隔,变量双引号,常数,单引号或双引号,参数基本同test命令。=和==相同
如检查变量是否为空:[ -z "$HOME" ] ; echo $?
使用中括号进行的判定示例:
1 read -p "Please input (Y/N): " yn 2 [ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0 3 [ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0 4 echo "I don't know what your choice is" && exit 0
shell脚本使用的默认变量:
$0表示该脚本名,$1-$.......表示执行该脚本接入的命令参数
$#接入的参数个数(除$0) $@所有变量,$* 带分隔符的所有变量。
示例:输入参数即可测试。
1 echo "The script name is ==> $0" 2 echo "Total parameter number is ==> $#" 3 [ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." 4 && exit 0 5 echo "Your whole parameter is ==> '$@'" 6 echo "The 1st parameter ==> $1" 7 echo "The 2nd parameter ==> $2"
shift:参数左偏移减少。示例如下:
1 echo "Total parameter number is ==> $#" 2 echo "Your whole parameter is ==> '$@'" 3 shift # 进行第一次『一个变量的 shift 』 4 echo "Total parameter number is ==> $#" 5 echo "Your whole parameter is ==> '$@'" 6 shift 3 # 进行第二次『三个变量的 shift 』 7 echo "Total parameter number is ==> $#" 8 echo "Your whole parameter is ==> '$@'"
使用if [];then xxx fi 语句示例:
&& 等同 -a || 等同 -o
1 read -p "Please input (Y/N): " yn 2 3 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then 4 echo "OK, continue" 5 exit 0 6 fi 7 if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then 8 echo "Oh, interrupt!" 9 exit 0 10 fi 11 echo "I don't know what your choice is" && exit 0
1 read -p "Please input (Y/N): " yn 2 3 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then 4 echo "OK, continue" 5 elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then 6 echo "Oh, interrupt!" 7 else 8 echo "I don't know what your choice is" 9 fi
查看端口是否打开:•80: WWW •22: ssh •21: ftp •25: mail
1 testing=$(netstat -tuln | grep ":80 ") # 侦测看 port 80 在否? 2 if [ "$testing" != "" ]; then 3 echo "WWW is running in your system." 4 fi 5 testing=$(netstat -tuln | grep ":22 ") # 侦测看 port 22 在否? 6 if [ "$testing" != "" ]; then 7 echo "SSH is running in your system." 8 fi 9 testing=$(netstat -tuln | grep ":21 ") # 侦测看 port 21 在否? 10 if [ "$testing" != "" ]; then 11 echo "FTP is running in your system." 12 fi 13 testing=$(netstat -tuln | grep ":25 ") # 侦测看 port 25 在否? 14 if [ "$testing" != "" ]; then 15 echo "Mail is running in your system." 16 fi
判断输入是否8个数字,并计算时间差的天数:
1 echo "This program will try to calculate :" 2 echo "How many days before your demobilization date..." 3 read -p "Please input your demobilization date (YYYYMMDD ex>20090401): " date2 4 5 # 2. 测试一下,这个输入的内容是否正确?利用正规表示法罗~ 6 date_d=$(echo $date2 |grep '[0-9]{8}') # 看看是否有八个数字 7 if [ "$date_d" == "" ]; then 8 echo "You input the wrong date format...." 9 exit 1 10 fi 11 12 # 3. 开始计算日期罗~ 13 declare -i date_dem=`date --date="$date2" +%s` # 退伍日期秒数 14 declare -i date_now=`date +%s` # 现在日期秒数 15 declare -i date_total_s=$(($date_dem-$date_now)) # 剩余秒数统计 16 declare -i date_d=$(($date_total_s/60/60/24)) # 转为日数 17 if [ "$date_total_s" -lt "0" ]; then # 判断是否已退伍 18 echo "You had been demobilization before: " $((-1*$date_d)) " ago" 19 else 20 declare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60)) 21 echo "You will demobilize after $date_d days and $date_h hours." 22 fi
利用case...esac的语句进行选择判断:
结构:尾部分号为两个
1 case $变量名称 in <==关键字为 case ,还有变量前有钱字号 2 "第一个变量内容") <==每个变量内容建议用双引号括起来,关键字则为小括号 ) 3 程序段 4 ;; <==每个类别结尾使用两个连续的分号来处理! 5 "第二个变量内容") 6 程序段 7 ;; 8 *) <==最后一个变量内容都会用 * 来代表所有其他值 9 不包含第一个变量内容与第二个变量内容的其他程序运行段 10 exit 1 11 ;;
示例:
1 case $1 in 2 "hello") 3 echo "Hello, how are you ?" 4 ;; 5 "") 6 echo "You MUST input parameters, ex> {$0 someword}" 7 ;; 8 *) # 其实就相当於万用字节,0~无穷多个任意字节之意! 9 echo "Usage $0 {hello}" 10 ;; 11 esac
示例2:
1 echo "This program will print your selection !" 2 # read -p "Input your choice: " choice # 暂时取消,可以替换! 3 # case $choice in # 暂时取消,可以替换! 4 case $1 in # 现在使用,可以用上面两行替换! 5 "one") 6 echo "Your choice is ONE" 7 ;; 8 "two") 9 echo "Your choice is TWO" 10 ;; 11 "three") 12 echo "Your choice is THREE" 13 ;; 14 *) 15 echo "Usage $0 {one|two|three}" 16 ;; 17 esac
函数设计与调用
其内置变量和shell名称相似,$0 -- $n,为函数的局部变量
示例:
1 function printit(){ 2 echo -n "Your choice is " # 加上 -n 可以不断行继续在同一行显示 3 } 4 5 echo "This program will print your selection !" 6 case $1 in 7 "one") 8 printit; echo $1 | tr 'a-z' 'A-Z' # 将参数做大小写转换! 9 ;; 10 "two") 11 printit; echo $1 | tr 'a-z' 'A-Z' 12 ;; 13 "three") 14 printit; echo $1 | tr 'a-z' 'A-Z' 15 ;; 16 *) 17 echo "Usage $0 {one|two|three}" 18 ;; 19 esac
带函数参数的示例:
1 function printit(){ 2 echo "Your choice is $1" # 这个 $1 必须要参考底下命令的下达 3 } 4 5 echo "This program will print your selection !" 6 case $1 in 7 "one") 8 printit 1 # 请注意, printit 命令后面还有接参数! 9 ;; 10 "two") 11 printit 2 12 ;; 13 "three") 14 printit 3 15 ;; 16 *) 17 echo "Usage $0 {one|two|three}" 18 ;; 19 esac
循环:
while []do done 循环 条件成立执行循环
until []do done 循环 条件不成立执行循环
示例1-n!!!!:真繁琐
1 while [ "$yn" != "yes" -a "$yn" != "YES" ] 2 do 3 read -p "Please input yes/YES to stop this program: " yn 4 done 5 echo "OK! you input the correct answer."
1 until [ "$yn" == "yes" -o "$yn" == "YES" ] 2 do 3 read -p "Please input yes/YES to stop this program: " yn 4 done 5 echo "OK! you input the correct answer."
100内的累加:
1 s=0 # 这是加总的数值变量 2 i=0 # 这是累计的数值,亦即是 1, 2, 3.... 3 while [ "$i" != "100" ] 4 do 5 i=$(($i+1)) # 每次 i 都会添加 1 6 s=$(($s+$i)) # 每次都会加总一次! 7 done 8 echo "The result of '1+2+3+...+100' is ==> $s"
for var in xxx do done 循环,xxx内轮询一遍就结束。
示例:
1 for animal in dog cat elephant 2 do 3 echo "There are ${animal}s.... " 4 done
显示用户,和对应的号:
1 users=$(cut -d ':' -f1 /etc/passwd) # 撷取帐号名称 2 for username in $users # 开始回圈进行! 3 do 4 id $username 5 finger $username 6 done
批量ping ip地址:使用seq 1 100取值,也可以使用{1..100}取值 和{a..g}类似
1 network="192.168.1" # 先定义一个网域的前面部分! 2 for sitenu in $(seq 1 100) # seq 为 sequence(连续) 的缩写之意 3 do 4 # 底下的程序在取得 ping 的回传值是正确的还是失败的! 5 ping -c 1 -w 1 ${network}.${sitenu} &> /dev/null && result=0 || result=1 6 # 开始显示结果是正确的启动 (UP) 还是错误的没有连通 (DOWN) 7 if [ "$result" == 0 ]; then 8 echo "Server ${network}.${sitenu} is UP." 9 else 10 echo "Server ${network}.${sitenu} is DOWN." 11 fi 12 done
获取目录下文件的权限:
1 read -p "Please input a directory: " dir 2 if [ "$dir" == "" -o ! -d "$dir" ]; then 3 echo "The $dir is NOT exist in your system." 4 exit 1 5 fi 6 7 # 2. 开始测试文件罗~ 8 filelist=$(ls $dir) # 列出所有在该目录下的文件名称 9 for filename in $filelist 10 do 11 perm="" 12 test -r "$dir/$filename" && perm="$perm readable" 13 test -w "$dir/$filename" && perm="$perm writable" 14 test -x "$dir/$filename" && perm="$perm executable" 15 echo "The file $dir/$filename's permission is $perm " 16 done
for ((初始值;限制值;赋值运算)) do... done 循环:
示例:1到x的累加:
1 read -p "Please input a number, I will count for 1+2+...+your_input: " nu 2 3 s=0 4 for (( i=1; i<=$nu; i=i+1 )) 5 do 6 s=$(($s+$i)) 7 done 8 echo "The result of '1+2+3+...+$nu' is ==> $s"
随机数和数组示例:
a[1]="a"
a[2]="b"
a[3]="c"
check=$(( ${RANDOM}*3/32767+1))
echo "ans:${a[${check}]}"
shell脚本跟踪与调试
-n不执行脚本只查询语法,-v执行脚本前输出内容 -x使用到的脚本显示到屏幕上(跟踪)
例如:sh -x file