文件归档
tar
(1) 创建归档
tar -c -f / PATH/TO/SOMEFILE .tar FILE…
tar cf / PATH/TO/SOMEFILE .tar FILE…
(2) 查看归档文件中的文件列表
tar -t -f /PATH/TO/SOMEFILE .tar
(3) 展开归档
tar -x -f /PATH/TO/SOMEFILE .tar
tar -x -f /PATH/TO/SOMEFILE .tar -C /PATH/
结合压缩工具实现:归档并压缩
-j: bzip2, -z: gzip, -J: xz
实现了归档压缩,但是结合使用时,注意文件名后缀,不同的压缩使用的后缀有差异,
cpio
复制 从或到文件
cpio 命令是通过重定向的方式将文件进行打包备份,还原恢复
的工具,它可以解压以“.cpio” 或者“.tar” 结尾的文件。
cpio [ 选项] > 文件名或者设备名
cpio [ 选项] < 文件名或者设备名
选项
-o 将文件拷贝打包成文件或者将文件输出到设备上
-i 解包,将打包文件解压或将设备上的备份还原到系统
-t 预览,查看文件内容或者输出到设备上的文件内容
-v 显示打包过程中的文件名称。
-d 解包生成目录,在cpio 还原时,自动的建立目录
-c 一种较新的存储方式
使用实例
将etc 目录备份:
find ./etc -print |cpio -ov >etc.cpio
内容预览
cpio –tv < etc.cpio
解包文件
cpio –iv <etc.cpio
cpio –idv < etc.cpio
shell脚本编程—–循环
for循环
for 变量名 in 列表 ;do
循环体
done
执行机制:
依次将列表中的元素赋值给”变量名“;每次赋值后即执行一次
循环体;知道列表中的元素耗尽,循环结束
列表生成方式
1.直接给出列表
2.整数列表:
a.{start..end}
b.${seq [start [step] end]}
3.返回列表的命令
$(command)
4.使用glob,如:*.sh
5.变量引用
$@, $*
for练习:
1 、判断/var/ 目录下所有文件的类型
脚本:
1 #!/bin/bash 2 #qiuwei 3 #2016-8-17 4 #filetype 5 for a in /var/*;do 6 if [[ -h $a ]];then 7 echo "the file $a is a sysmbol file" 8 elif [[ -b $a ]];then 9 echo "the file $a is a block file" 10 elif [[ -d $a ]];then 11 echo "the file $a is a directory" 12 elif [[ -f $a ]];then 13 echo "the file $a is a common file" 14 else 15 echo "the file $a is a other file" 16 fi 17 done ~
2、 、 添加10个 个 用户user1-user10 ,密码 同 用户名
1 #!/bin/bash 2 #qiuwei 3 #2016-8-17 4 #useradd 5 6 for a in user{1..10};do 7 if id $a&>/dev/null;then ====>判断uesr是否存在 8 echo "the user $a exist" &&echo $a |passwd --stdin $a ====>存在则显示用户存在,并修改密码 9 else 10 useradd $a &&echo $a |passwd --stdin $a&&echo "the user $a create sucess" ==>不成功就创建用户,并修改密码,显示创建成功 11 fi 12 done ~
3 、/etc/rc.d/rc3.d 目录下分别有多个以K 开头和以S 开头的
文件 ;分别 读取每个文件,以K 开头的文件输出为文件加stop
,以S 开头的文件输出为文件名加start; ;
“ “K34filename stop”
“S66filename start”
脚本:
1 #!/bin/bash 2 #qiuwei 3 #2016-8-17 4 #--------- 5 6 for a in `ls /etc/rc.d/rc3.d`;do 7 if echo "$a"|grep -q "\<K.*";then 8 echo -e "$a\tstop" 9 elif echo $a |grep -q "\<S*";then 10 echo -e "$a\tstart" 11 fi 12 done
4 、写 一个脚本 ,提示输入正整数n 的值,计算1+2+3+…n的 的
总和
1 #!/bin/bash 2 read -p "please input a number:" c 3 if echo $c|grep -q "^[0-9]\+$"&&[[ $c -ne 0 ]];then 4 echo right number 5 else 6 echo "wrong number"&&exit 7 fi 8 b=0 9 for a in `seq 1 $c`;do 10 b=$[$a+$b] 11 done 12 echo $b ============================================================ 1 #!/bin/bash 2 read -p "please input a number:" c 3 if echo $c|grep -q "^[0-9]\+$"&&[[ $c -ne 0 ]];then 4 5 b=0 6 for a in `seq 1 $c`;do 7 b=$[$a+$b] 8 done 9 else 10 echo "wrong number"&&exit 11 fi 12 echo $b
5、 、 写一个脚本 ,提示请输入网络地址,如192.168.0.0 ,判
断输入的网段中主机在线状态
脚本:
1 #!/bin/bash 2 #qiuwei 3 #ip test 4 5 read -p "please input a ip :" a 6 if echo $a|egrep "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[ 0-4][0-9]|25[0-5])$";then 7 c=`echo $a|cut -d. -f4` 8 b=`echo $a|cut -d. -f1-3` 9 for i in `seq 1 $c`;do 10 if ping -c1 -w1 $b.$i &>/dev/null;then 11 echo -e "\033[32mthe host $b.$i is onlin\033[0m" 12 else 13 echo -e "\033[31mthe host $b.$i is offline\033[0m" 14 fi 15 done 16 else 17 echo "please input correct ip" 18 fi
6、 、 打印九九乘法表
脚本
1 #!/bin/bash 2 #qiuwei 3 #9*9 4 5 for i in `seq 1 9`;do 6 for j in `seq 1 9`;do 7 if [[ $i -ge $j ]];then 8 sum=$[$i*$j] 9 echo -ne "$j*$i=$sum \t" 10 11 fi 12 done 13 echo 14 done
while循环
while condition;do
循环体
done
condition:循环控制条件;进入循环之前,先做一次判断,每一次循环之后会再次做判断;
条件为true,则执行一次循环
条件为false,则终止循环
因此:condition一般应该有循环制变量;且此变量的值会在循环体不断的被修正
进入条件:condition为true
退出条件:condition为false
whlie循环练习
1 、求100 以内所有正整数之和
1 #!/bin/bash 2 #qiuwei 3 #sum100 4 i=1 j=0 5 while [[ $i -le 100 ]] ;do 6 j=$[$i+$j] 7 let i++ 8 done 9 echo "the sum is $j"
2 、通过ping 命令探测172.16.250.1-254 范围内的所有主机
的在线状态,统计在线主机和离线主机各多少。
脚本:
1 #!/bin/bash
2 #qiuwei
3 #host online or not
4 ip=10.1.252.
5 i=1
6 a=0
7 b=0
8 while [[ $i -le 254 ]];do
9 if ping -c1 -w1 $ip$i &>/dev/null;then
10 echo -e "\033[32mthe host $ip$i online\033[0m"
11 let a++
12 else
13 echo -e "\033[31mthe host $ip$i offline\033[0m"
14 let b++
15 fi
16 let i++
17 done
18 echo "the online host number is: $a"
19 echo "the offline host number is: $b"
3 、打印九九乘法表
脚本
1 #!/bin/bash 2 #qiuwei 3 #9*9 4 i=1 5 while [[ $i -le 9 ]];do 6 j=1 7 while [[ $j -le $i ]];do 8 sum=$[$j*$i] 9 echo -en "$j*$i=$sum \t" 10 let j++ 11 done 12 echo 13 let i++ 14 done
4 、利用变量RANDOM 生成10 个随机数字,输出这个10 数字
,并显示其中的最大者和最小者
1 #!/bin/bash 2 #qiuwei 3 #random 4 i=1 5 a=$RANDOM 6 max=$a 7 min=$a 8 while [[ $i -le 10 ]];do 9 if [[ $max -lt $a ]];then 10 max=$a 11 elif [[ $min -gt $a ]];then 12 min=$a 13 fi 14 echo $a 15 a=$RANDOM 16 let i++ 17 done 18 echo "the max number is $max" 19 echo "the min number is $min"
5 、打印国际象棋棋盘
1 #!/bin/bash 2 #qiuwei 3 #chess 4 i=1 5 while [[ $i -le 8 ]];do 6 j=1 7 while [[ $j -le 8 ]];do 8 a=$[$i+$j] 9 b=$[$a%2] 10 if [[ $b -eq 0 ]];then 11 echo -ne "\033[41;1m \033[0m" 12 else 13 echo -ne "\033[42;1m \033[0m" 14 fi 15 let j++ 16 done 17 echo 18 let i++ 19 done
until循环 ===>和while相反
until condition;do
循环体
done
进入条件:condition 为false
退出条件:condition 为true
continue N:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
continue ==>结束本轮循环,开始进行下轮判断,false为进入,true为退出
fi
CMDn
…
done
break N:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
break ==>直接结束整层循环,
fi
CMDn
…
done
无限循环
while true;do
循环体
done
until false;do
循环体
done
until练习
1 、每隔3 秒钟到系统上获取已经登录的用户的信息;如果发
现用户hacker 登录,则将登录时间和主机记录于日志
/var/log/login.log 中, 并提示该用户退出系统。
1 #!/bin/bash 2 #qiuwei 3 #host 4 5 until `who|grep -q "^hacker\>"`;do 6 sleep 3 7 echo "finding...." 8 done 9 10 11 who|grep "^hacker\>"|tr -s " "|cut -d" " -f1,3,4 >>/var/log/login.log 12 echo "please logout system"|mail hacker 13 echo "reminded and login record in /var/log/login.log"
2 、随机生成10 以内的数字,实现猜字游戏,提示比较大或小
,相等则退出
1 #!/bin/bash 2 #qiuwei 3 #guess 4 5 a=$[$RANDOM%10+1] 6 7 read -p "input a number:" b 8 until [[ $a -eq $b ]];do 9 10 if [[ $a -gt $b ]];then 11 echo "intput a big number" 12 else 13 echo "input a small number" 14 fi 15 read -p "input a number:" b 16 done 17 echo "the number is right"
3.用循环完成如下
*
***
*****
1 #!/bin/bash 2 #qiuwei 3 #sangjiaoxing 4 #规律为:第n行的空行个数为总行数-n,星星个数为2n-1, 5 #所以我们在每一行打印对应的空格和星星数, 6 read -p "please input a number:" a 7 8 [[ $a =~ ^[0-9]+$ ]]&&[[ $a -ge 2 ]] 9 [[ $? -ne 0 ]]&&echo "wrong number"&&exit 10 #判断输入的数字,如果不是数字且大于等于2,就提示错误退出 11 for line in `seq 1 $a`;do 12 for (( sapce=a-line;sapce>0;sapce-- ));do 13 echo -n " " 14 #打印空行 15 done 16 for (( xing=1;xing<=(line*2-1);xing++ ));do 17 echo -n "*" 18 #打印星星 19 done 20 echo 21 done
2、用until循环实现国际象棋棋盘
1 #/bin/bash 2 #qiuwei 3 #用until循环实现国际象棋 4 i=1 5 until [[ $i -gt 8 ]];do 6 7 j=1 8 until [[ $j -gt 8 ]];do 9 a=$[$[$i+$j]%2] 10 if [[ $a -ne 1 ]];then 11 echo -ne "\033[43;1m \033[0m" 12 else 13 echo -ne "\033[42;1m \033[0m" 14 15 fi 16 let j++ 17 done 18 echo 19 let i++ 20 done
特殊用法
while 循环的特殊用法(遍历文件的每一行)
while read line ;do
循环体
do < /path/from/somefile
依次读取/path/from/somefile文件中的每一行,且将行赋值给变量line
练习
扫描/etc/passwd 文件每一行,如发现GECOS 字段为空,则填
充用户名和单位电话为62985600 ,并提示该用户的GECOS信 信
息修改成功
[root@localhost bin]# vim while6.sh 1 #!/bin/bash 2 #qiuwei 3 #gecos 4 while read line ;do 5 a=`echo $line|cut -d: -f5` 6 if [[ -z $a ]];then 7 b=`echo $line|cut -d: -f1` 8 chfn -f $b $b &>/dev/null 9 chfn -p 62985600 $b &>/dev/null 10 echo "sucess" 11 fi 12 done </etc/passwd
双小括号方法,即((…)),也可用于算术运算
双小括号也可以使bash sehll 实现C语言风格的变量操作
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
1 #/bin/bash 2 #qiuwei 3 for((a=1; a<10;a++));do 6 #初始变量a,a小于10,则判断成功,循环执行,a++为修正变量 7 echo $a 8 done ~
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算
,而后再做条件判断
select
select variable in list
do
循环体
done
select循环主要用于创建菜单,按数字顺序排列的示 菜单项将显示在标准错误上,
并显示 PS3 提示符,等待用户输入
select是个无限循环,所有如果不用break命令退出循环或exit退出脚本,循环无限执行
select经常和case一起使用
1 #/bin/bash 2 #qiuwei 3 4 PS3="what do you want to eat:" 5 6 select menu in ban you flash monkey ;do 7 case $menu in 8 ban) 9 echo "this is ban" 10 ;; 11 you) 12 echo "this is you" 13 ;; 14 flash) 15 echo "I am the flash" 16 ;; 17 monkey) 18 echo "this is a monkey" 19 ;; 20 *) 21 echo "you are a hehe" 22 break 23 ;; 24 esac 25 done
函数
函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
函数和shell程序相似,但是不能独立运行,必须要调用才能运行,函数是在当前
shell中运行的,shell程序测试在子shell中运行的,因此在当前shell中,函数可以对
shell中变量进行修改
函数语法
-
function f-name{
…函数体…
}
-
f-name(){
…函数体…
}
函数使用
函数的定义和使用:
可在交互式环境下定义函数
可将函数放在脚本文件中作为它的一部分
可放在只包含函数的单独文件中
调用:函数只有被调用才会执行,给点函数名即可
函数名出现的地方,会被自带替换为函数代码
函数的生命周期:被调用时创建,返回时终止
函数和一般命令一样,执行后有两种返回值
结果返回值
1.使用echo 或printf命令进行输出
2.函数体中调用命令的输出结果
退出状态码
1.取决于函数中执行的最后一条命令的退出状态码
2.自定义
return 默认为最后一条命令的状态返回值
return 0 无错误返回
return 1-255 错误返回
注意:函数名不要和系统命令同名
简单函数实例
1 #/bin/bash 2 #qiuwei 3 #test 4 5 fun(){ 6 echo "hello everyone ,I am the flash" 7 } 8 echo "I am the Iron Man" 9 fun 10 echo "You are stupid " 11
函数文件
可以将经常使用的函数存入函数文件,然后将函数文件载入shell,
一旦函数文件载入shell,就可以在命令行或脚本中调用函数
可以使用set命令查看所有定义的函数,可以看到所有已经载入shell的函数
若要改动函数,首先用unset命令从shell中删除函数,改动完毕后,在从新载入此文件
实例
1.创建函数文件
1 #/bin/bash 2 #funfile 3 #qiuwei 4 5 funfile(){ 6 7 if [[ $# -lt 1 ]];then 8 echo "please at least input a agr" 9 return 1 10 else 11 echo $1 12 fi 13 14 }
2.载入shell
. funfile
source funfile 路径要正确
然后用set检查是否载入
3.执行函数
删除shell函数
现在对函数做一些改动。首先删除函数,使其对shell 不可用,使用unset 命令完成此功能
unset funfile
在使用set,函数不在显示
函数参数
函数可以接受参数:
传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可
在函数体中,可使用$1,$2…调用这些参数,还可以使用$@,#*.$#等等
函数变量
环境变量:当前shell和子shell有效
本地变量:只对当前shell进程有效。为执行脚本会启动专用子shell进程;因此
本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
局部变量:函数的生命周期;函数结束时变量被自动失效
定义局部变量 local name=value
实例
1 #/bin/bash 2 a=qiuwei 3 fun(){ 4 a=pingxiong 5 echo $a 6 } 7 8 fun 9 echo $a ~
结果为
1 #/bin/bash 2 a=qiuwei 3 fun(){ 4 local a=pingxiong 5 echo $a 6 } 7 8 fun 9 echo $a
理解:函数和当前shell是在同一等级,如果直接变量赋值,就会覆盖前面的变量赋值,
,如果想两个变量同时生效,互不干扰,就必须使用局部变量了 ,如上,局部变量
只用于函数中
函数递归
函数直接或间接调用自身,注意递归层数
递归实例:
阶乘是基斯顿·于 卡曼于 1808 年发明的运算符号,是数学术语
一个正整数的阶乘(factorial )是所有小于及等于该数的正整
数的积,并且有0 的阶乘为1 。自然数n 的阶乘写作n!。 。
n!=1 ×2 ×3 ×… ×n。 。
阶乘亦可以递归方式定义:0!=1 ,n!=(n-1)! ×n。 。
n!=n(n-1)(n-2)…1
n(n-1)! = n(n-1)(n-2)!
1 #/bin/bash 2 #qiuwei 3 #递归函数 4 fun(){ 5 6 if [ $1 -eq 0 -o $1 -eq 1 ];then 7 echo 1 8 #0和1的阶乘为1 9 else 10 11 echo "$[$1*$(fun $[$1-1])]" 12 #$1的阶乘为$1*($1-1)阶乘 13 #注意以上格式 14 fi 15 } 16 17 fun 7
练习
1 、写 一 个服务脚本/root/bin/testsrv.sh ,完成如下要求
(1) 脚本可接受参数:start, stop, restart, status
(2) 如果参数非此四者之一,提示使用格式后报错 退出
(3) 如是start:则 则 创建/var/lock/subsys/ SCRIPT_NAME , 并显示“启动成功”
考虑:如果事先已经启动过一次,该如何处理?
(4) 如是stop:则 则 删除/var/lock/subsys/ SCRIPT_NAME , 并显示“停止完成”
考虑:如果事先已然停止过了,该如何处理?
(5) 如是restart ,则先stop, 再start
考虑:如果本来没有start ,如何处理?
(6) 如是status, 则如果/var/lock/subsys/ SCRIPT_NAME 文件存在,则显示
“ SCRIPT_NAME is running…”
如果/var/lock/subsys/ SCRIPT_NAME 文件不存在,则显示“ SCRIPT_NAME
is stopped…”
其中: SCRIPT_NAME 为当前脚 本名
脚本:
1 #bin/bash 2 #qiuwei 3 #1 、写 一 个服务脚本/root/bin/testsrv.sh ,完成如下要求 4 #(1) 脚本可接受参数:start, stop, restart, status 5 #(2) 如果参数非此四者之一,提示使用格式后报错 退出 6 #(3) 如是start:则创建/var/lock/subsys/ SCRIPT_NAME , 并显示“启动成功” 7 #考虑:如果事先已经启动过一次,该如何处理? 8 #(4) 如是stop:则删除/var/lock/subsys/ SCRIPT_NAME , 并显示“停止完成” 9 #考虑:如果事先已然停止过了,该如何处理? 10 #(5) 如是restart ,则先stop, 再start 11 #考虑:如果本来没有start ,如何处理? 12 #(6) 如是status, 则如果/var/lock/subsys/ SCRIPT_NAME 文件存在,则显示 13 #“ SCRIPT_NAME is running...” 14 #如果/var/lock/subsys/ SCRIPT_NAME 文件不存在,则显示“ SCRIPT_NAME 15 #is stopped...” 16 #其中: SCRIPT_NAME 为当前脚本名 17 file=/var/lock/subsys/testscv 18 start(){ 19 20 if [[ -f $file ]];then 21 echo "$file is exsit" 22 else 23 touch $file && echo "start finshed" 24 25 fi 26 } 27 28 stop(){ 29 30 if [[ -f $file ]];then 31 rm -f $file && echo "stop finshed" 32 else 33 echo "No such file " 34 fi 35 } 36 37 restart(){ 38 39 if [[ -f $file ]];then 40 rm -f $file 41 touch $file&&echo "start finshed" =============>这个其实不需要,用stop和start组合下就好了 42 else 43 touch $file&&echo "start finshed" 44 fi 45 } 46 47 status(){ 48 49 if [[ -f $file ]];then 50 echo "$file is running...." 51 else 52 echo "$file is stoped...." 53 fi 54 } 55 56 57 read -p "input a arg:" i 58 59 case $i in 60 start) 61 start 62 ;; 63 stop) 64 stop 65 ;; 66 restart) 67 stop 68 start 69 ;; 70 status) 71 status 72 ;; 73 *) 74 echo "you should input {start|stop|restart|status}" 75 ;; 76 esac
2 、编写一个脚本/root/bin/copycmd.sh
(1) 提示用户输入一个可执行命令名称;
(2) 获取此命令所依赖到的所有库文件列表
(3) 复制命令至某目标目录( 例如/mnt/sysroot) 下的对应路径下;
如:/bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:
如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-
linux-x86-64.so.2
(5) 每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命
令,并重复完成上述功能;直到用户输入quit
1 #!/bin/bash 2 #qiuwei 3 # 2 、编写一个脚本/root/bin/copycmd.sh 4 #(1) 提示用户输入一个可执行命令名称; 5 #(2) 获取此命令所依赖到的所有库文件列表 6 #(3) 复制命令至某目标目录( 例如/mnt/sysroot) 下的对应路径下; 7 #如:/bin/bash ==> /mnt/sysroot/bin/bash 8 #/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd 9 #(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下: 10 #如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld- 11 #linux-x86-64.so.2 12 #(5) 每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命 13 #令,并重复完成上述功能;直到用户输入quit 14 #2为至少输入一个命令 15 #3为输入正确的命令 16 copycmd(){ 17 18 if [[ -z $i ]];then 19 echo "please at least input a command"&&exit 20 elif ! type $i &>/dev/null;then 21 echo "$i is not a command,please input a right number"&&exit 22 #判断是否为命令 23 else 24 cmd=`whereis -b $i|cut -d" " -f2` 25 #取命令文件路径,设变量 26 dir=`whereis -b $i|cut -d" " -f2|grep -o "/.*/"` 27 #取名文件路径 28 #echo $cmd 29 libfile=`ldd $cmd |egrep -o "/[^[:space:]]+"` 30 #echo $libfile 31 #取命令所依赖的库文件列表 32 mkdir -p /mnt/sysroot$dir 33 cp $cmd /mnt/sysroot$dir&& echo -e "\033[32mthe command $cmd mv sucess\033[0m" 34 #复制命令 35 36 for file in $libfile;do 37 dir1=`echo $file|grep -o "/.*/"` 38 #取库文件路径 39 mkdir -p /mnt/sysroot$dir1 40 cp $file /mnt/sysroot$dir1 &&echo -e "\033[34mthe libfile $file mv sucess\033[0m" 41 #赋值库文件 42 done 43 fi 44 read -p "please input a new command:" i 45 } 46 47 48 read -p "please input a command:" i 49 while true ;do 50 51 if [[ $i == quit ]];then 52 exit 53 54 else 55 copycmd 56 fi 57 done
!!!!以上脚本还不完善,待补充(没输入命令或者错误命令时要完善)
原创文章,作者:qiuwei,如若转载,请注明出处:http://www.178linux.com/36986
评论列表(2条)
文章对shell脚本的基础语法总结的很详细,shell脚本的学习没有特别的捷径,熟悉了基本语法之后剩下的就是多写多练,可以去网上找一些相对实用的脚本来学习哦。
@马哥教育:恩,好的