一 什么是kernel , shell ,shell script
Kernel是linux管理整个电脑硬件系统,并向上层应用提供接口来调用硬件。
shell是用户和linux交互来控制kenel的一种应用程序。
系统中的shell类型有
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh
查看当前使用的shell
[root@localhost ~]# echo $SHELL /bin/bash
shell script 是把命令堆砌在一起,来实现特定功能的程序化脚本。
二 变量:可变化的量,命名内存空间
bash环境:
本地变量:当前shell进程;
环境变量:当前shell进程及其子进程;
局部变量:某个函数执行过程;
位置参数变量:在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;
特殊变量:$?, $*, $@, $#, $$
定义变量
name=value
name: 变量名
=:赋值符号
value:值
变量名:只能包含数字、字母和下划线;且不能以数字开头;
引用变量:${name}, $name
[root@localhost ~]# x=myx #设置x的值为myx [root@localhost ~]# echo $x #显示x的值,使用$引用 myx 10x=myx #以数字开头命名变量,显示错误 bash: 10x=myx: 未找到命令...
引用:
弱引用: "", 其内部的变量引用会被替换为变量值;
强引用:'',其变量的变量引用会保持原有字符;
命令引用:`COMMAND`, $(COMMAND),引用命令的执行结果;
[root@localhost ~]# x=myx [root@localhost ~]# echo "x is $x" #弱引用,$x替换 x is myx [root@localhost ~]# echo 'x is $x' #强引用,$x不替换 x is $x [root@localhost ~]# uname -r 3.10.0-229.el7.x86_64 [root@localhost ~]# cd /lib/modules/`uname -r`/kernel #命令替换 `uname -r`/ 替换为3.10.0-229.el7.x86_64 [root@localhost kernel]# pwd /lib/modules/3.10.0-229.el7.x86_64/kernel
声明为整型:
declare -i name[=value]
let name=value
生命周期:
创建
销毁:
自动销毁:shell进程终止;
手动销毁:unset name
[root@localhost ~]# test=mytest #设置变量 [root@localhost ~]# echo $test #变量可以显示 mytest [root@localhost ~]# unset test #销毁变量 [root@localhost ~]# echo $test #在次echo,显示为空
环境变量:
被“导出”的本地变量
export name[=value]
declare -x name[=value]
累加变量 『PATH="$PATH":/home/bin』或『PATH=${PATH}:/home/bin』
查看所有环境变量:env, printenv, export
三 命令状态结果:
bash进程用于追踪执行的命令成功与否的状态:
0: 成功
1-255:失败
特殊变量:
$?:上一条命令的执行状态结果;
布尔型:
“真”:成功
“假”:失败
自定义脚本的状态结果:
exit [n]
注意:脚本中任何位置执行了exit命令即会终止当前shell进程;
[root@localhost ~]# cat /etc/passwd [root@localhost ~]# echo $? 0 [root@localhost ~]# vim test.sh #!/bin/bash cat /etc/passwd exit 3 [root@localhost ~]# bash test.sh [root@localhost ~]# echo $? 3
四 条件测试:
界定程序执行环境;
(1) 根据运行的命令的状态结果;
(2) 测试表达式
test EXPRESSION
[ EXPRESSION ]
` EXPRESSION `
整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;
$A -gt $B:是否大于;是则为“真”,否则为“假”;
$A -ge $B: 是否大于等于;
$A -lt $B:是否小于;
$A -le $B: 是否小于等于;
$A -eq $B: 是否等于;
$A -ne $B:是否不等于;
[root@localhost ~]# A=10 [root@localhost ~]# B=20 [root@localhost ~]# C=10 [root@localhost ~]# test $A -gt $B #A 大于B [root@localhost ~]# echo $? #假 1 [root@localhost ~]# test $A -lt $B #A小于B [root@localhost ~]# echo $? #真 0 [root@localhost ~]# [ $A -lt $B ] #用中括号测试 [root@localhost ~]# echo $? 0 [root@localhost ~]# [[ $A -lt $B ]] #双中知号同样可以测试 [root@localhost ~]# echo $? 0 [root@localhost ~]# test $A -lt $C #A小于C [root@localhost ~]# echo $? #假 1 [root@localhost ~]# test $A -ge $C #A大于等于C [root@localhost ~]# echo $? #真 0 [root@localhost ~]# test $A -le $C #A小于等于C [root@localhost ~]# echo $? #真 0 [root@localhost ~]# test $A -eq $C #A等于C [root@localhost ~]# echo $? #真 0 [root@localhost ~]# test $A -ne $C # A不等于C [root@localhost ~]# echo $? #假 1 [root@localhost ~]# test $A -ne $B #A不等于B [root@localhost ~]# echo $? #真 0
字符串测试:ASCII数值越大,字符比较时其值越大;
"$A" > "$B":是否大于;
"$A" < "$B":是否小于;
"$A" == "$B":是否等于;
"$A" != "$B":是否不等于;
-z "$A":是否为空;空则为“真”,否则为“假”
-n "$A":是否不空;不空则“真”,空则为“假”
注意: 字符串测试应该使用双中括号 ` EXPRESSION `
[root@localhost ~]# A=pass [root@localhost ~]# B=pbaa [root@localhost ~]# C=pass [root@localhost ~]# test "$A">"$B" #pa 在pb前面 ,所以A大于B [root@localhost ~]# echo $? 0 [root@localhost ~]# test "$A"=="$C" [root@localhost ~]# echo $? 0
文件测试:测试文件的存在性以及属性;
-e $file: 是否存在;存在则为“真”,否则为“假”;
-a $file: 同上;
-f $file:文件是否存在且为普通文件;
-d $file:文件是否存在且为目录;
-h $file:是否存在且为符号链接文件;
-L $file: 同上
-b $file:是否存在且为块设备文件;
-c $file:是否存在且为字符设备文件;
-S $file:是否存在且为套接字文件;
-p $file: 是否存在且为管道文件;
-r $file: 当前用户对文件是否拥有读权限;
-w $file:当前用户对文件是否拥有写权限;
-x $file:当前用户对文件是否拥有执行权限;
-u $file:文件是否拥有SUID权限;
-g $file:文件是否拥有SGID权限;
-k $file:文件是否拥有sticky权限;
-O $file: 当前用户是否为指定文件的属主;
-G $file: 当前用户是否为指定文件的属组;
双目操作符:
$file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2的;
$file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2的;
$file1 -ef $file2:file1与file2是否指向了同一个inode;测试二者是否为同一个文件的硬链接;
[root@localhost ~]# mkdir /test [root@localhost ~]# cd /test [root@localhost test]# touch test1.txt [root@localhost test]# test -e test1.txt #测试是否存在文件test1.txt [root@localhost test]# echo $? #真 0 [root@localhost test]# test -e test2.txt #测试是否存在文件test2.txt [root@localhost test]# echo $? #假 1 [root@localhost test]# test -a test1.txt #测试是否存在文件test1.txt [root@localhost test]# echo $? #真 0 [root@localhost test]# test -f test1.txt #测试test1.txt是否为普通文件 [root@localhost test]# echo $? 0 [root@localhost test]# test -O test1.txt #测试test1.txt的属主是否和当前用户一至 [root@localhost test]# echo $? #真 0 [root@localhost test]# test -G test1.txt #测试test1.txt的属主是否和当前用户一至 [root@localhost test]# echo $? #真 0 [root@localhost test]# useradd cenos [root@localhost test]# [root@localhost test]# su - cenos [cenos@localhost ~]$ cd /test [cenos@localhost test]$ test -O test1.txt #测试test1.txt的属主是否和当前用户一至 [cenos@localhost test]$ echo $? #假 1 [cenos@localhost test]$ test -G test1.txt #测试test1.txt的属主是否和当前用户一至 [cenos@localhost test]$ echo $? #假 1 [root@localhost test]# touch test2.txt [root@localhost test]# test test2.txt -nt test1.txt #测试test2.txt修改时间是否晚于text1.txt [root@localhost test]# echo $? #真 0 [root@localhost test]# test test2.txt -ot test1.txt #测试test2.txt修改时间是否早于text1.txt [root@localhost test]# echo $? #假 1 [root@localhost test]# ln test1.txt test3.txt [root@localhost test]# test test3.txt -ef test1.txt #测试test3.txt test1.txt是否为同一文件硬链接 [root@localhost test]# echo $? #真 0
五 选择执行 if else fi
if condition
then
condition 判断状态为直,$?值为0
执行 commands
else
condition 判断状态为假,$?值为1-255
执行 commands
fi
或者
if condition
then
condition 判断状态为直,$?值为0
执行 commands
elif condition1
then
condition1 判断状态为直,$?值为0
执行 commands
elif condition2
then
condition2 判断状态为直,$?值为0
执行 commands
else
condition 判断状态为假,$?值为1-255
执行 commands
fi
例如
[root@localhost test]# vim test.sh echo "Please choose one" echo "1.show test1" echo "2.show test2" echo -n "Select your os choice [1 or 2]? " read test if [ $test -eq 1 ] ; then echo "choose (test1)" else if [ $test -eq 2 ] ; then echo "choose (test2)" else echo "choose else " fi fi [root@localhost test]# bash test.sh Please choose one 1.show test1 2.show test2 Select your os choice [1 or 2]? 1 choose (test1) [root@localhost test]# bash test.sh Please choose one 1.show test1 2.show test2 Select your os choice [1 or 2]? 2 choose (test2) [root@localhost test]# bash test.sh Please choose one 1.show test1 2.show test2 Select your os choice [1 or 2]? 3 choose else [root@localhost test]# bash test.sh Please choose one 1.show test1 2.show test2 Select your os choice [1 or 2]? test.sh: line 7: [: -eq: unary operator expected test.sh: line 13: [: -eq: unary operator expected choose else
六 脚本参数(位置参数变量):
# ./script.sh /etc/fstab /etc/grub2.cfg
$0 $1 $2
位置参数变量:$1, $2, ...
${10}
特殊变量:
$?: 命令的状态结果;
$#: 传递给脚本或函数的参数的个数;
$*和$@: 引用传递给脚本或函数的参数列表;
shift [n]:轮替
[root@localhost test]# vim scrip.sh #!/bin/bash echo "Total number of command line argument are $#" echo "$0 is script name" echo "$1 is first argument" echo "$2 is second argument" echo "All of them are :- $* or $@" [root@localhost test]# bash scrip.sh test1 test2 test3 test4 Total number of command line argument are 4 scrip.sh is script name test1 is first argument test2 is second argument All of them are :- test1 test2 test3 test4 or test1 test2 test3 test4
[root@localhost test]# vim scrip2.sh echo "$1 is first argument" shift echo "$1 is second argument" shift echo "$1 is third argument" [root@localhost test]# bash scrip2.sh test1 test2 test3 test4 test1 is first argument test2 is second argument test3 is third argument
七 循环
循环 for
for { variable } in { list }
do
执行命令,直到list到最后一个
done
LIST的生成方法:
(1) 整数列表
(a) {start..end} {1..10}
(b) $(seq [start `step` end) seq 0 2 10 (0 2 4 6 8 10)
(2) 直接给出列表 user1 user2 user3 user4 user5
(3) glob /var/log/*
(4) 命令生成 $(cut -d: -f1 /etc/passwd)
[root@localhost test]# vim for1.sh for i in 1 2 3 4 5 do echo "Welcome $i times" done [root@localhost test]# bash for1.sh Welcome 1 times Welcome 2 times Welcome 3 times Welcome 4 times Welcome 5 times
循环 while, until
while [ condition ]
do
command1
command2
....
done
while循环
进入条件:当CONDITION为“真”;
退出条件:当CONDITION为“假”;
until [ condition ]
do
command1
command2
....
done
unitl循环
进入条件:当CONDITION为“假”时
退出条件:当CONDITION为“真”时
[root@localhost test]# vim testwhile.sh #!/bin/bash if [ $# -eq 0 ] then echo "Error - please input like bash testwhile.sh no." exit 1 fi n=$1 i=1 while [ $i -le 10 ] do echo "$n * $i = `expr $i \* $n`" i=`expr $i + 1` done [root@localhost test]# bash testwhile.sh Error - please input like bash testwhile.sh no. [root@localhost test]# bash testwhile.sh 5 5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25 5 * 6 = 30 5 * 7 = 35 5 * 8 = 40 5 * 9 = 45 5 * 10 = 50
循环 case
case $variable in
pattern1) command
...
command;;
pattern2) command
...
command;;
patternN) command
...
command;;
*) command
...
command;;
esac
八 函数
定义方法:
(1) function f_name
{
函数体
}
(2) f_name()
{
函数体
}
调用函数:
f_name [argu1, argu2, ...]
九 sed & awk
正在总结 跳转
练习:
5、写一个脚本:如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;(不要怀疑,就是这么简单)
mkdir /test [root@localhost test]# vim /test/homework1.sh #!/bin/bash if [ $# -lt 1 ] then echo "usage: command file" exit 1 fi if [ -e $1 ] then echo "file exist" file $1 else echo " create fold $1" mkdir -p $1 fi [root@localhost test]# cd /test/ [root@localhost test]# bash homework1.sh /test/test create fold /test/test [root@localhost test]# bash homework1.sh /test/test file exist /test/test: directory [root@localhost test]# touch /test/test/test.txt [root@localhost test]# bash homework1.sh /test/test/test.txt file exist /test/test/test.txt: empty
6、写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:脚本参数,命令交互;(使用read,依然如此简单)
a脚本参数
[root@localhost test]# vim homework2.sh else echo "$1 is equal $2" #!/bin/bash if [ $# -lt 2 ] then echo "usage: command data1 data2" exit 1 fi if [ $1 -gt $2 ] then echo "$1 is big than $2" else if [ $1 -eq $2 ] then echo "$1 is equal $2" else echo "$1 is small than $2" fi fi [root@localhost test]# bash homework2.sh 10 20 10 is small than 20 [root@localhost test]# bash homework2.sh 20 10 20 is big than 10 [root@localhost test]# bash homework2.sh 20 usage: command data1 data2
b命令交互 read
[root@localhost test]# vim homework3.sh #!/bin/bash read -p "Plz enter two integer: " -t 20 num1 num2 if [ $num1 -gt $num2 ] then echo "$num1 is big than $num2" else if [ $num1 -eq $num2 ] then echo "$num1 is equal $num2" else echo "$num1 is small than $num2" fi fi [root@localhost test]# bash homework3.sh Plz enter two integer: 10 20 10 is small than 20 [root@localhost test]# bash homework3.sh Plz enter two integer: 20 10 20 is big than 10 [root@localhost test]# bash homework3.sh Plz enter two integer: 10 10 10 is equal 10
7、求100以内所有奇数之和(至少用3种方法。是的这是我们的作业^_^)
方法a for 判断 [root@localhost test]# vim sum100.1.sh #!/bin/bash declare -i sum=0 for i in {1..100} do if [ $[$i%2] -eq 1 ] then sum=$[$sum+$i] fi done echo "Sum is : $sum" [root@localhost test]# bash sum100.1.sh Sum is : 2500
方法b for list步进 [root@localhost test]# vim sum100.2.sh #!/bin/bash declare -i sum=0 for i in $(seq 1 2 100) do sum=$(($sum+$i)) done echo "Sum is : $sum" [root@localhost test]# bash sum100.2.sh Sum is : 2500
方法c while 判断 [root@localhost test]# vim sum100.3.sh declare -i sum=0 declare -i i=0 while [ $i -le 100 ] do if [ $[$i%2] -eq 1 ] then let sum+=$i fi let i++ done echo "sum is : $sum" [root@localhost test]# bash sum100.3.sh sum is : 2500
8、写一个脚本实现如下功能:
(1) 传递两个文本文件路径给脚本;
(2) 显示两个文件中空白行数较多的文件及其空白行的个数;
(3) 显示两个文件中总行数较多的文件及其总行数;
[root@localhost test]# vim countspace.sh if [ ! -f $1 ] then echo "$1 is not a common file " exit 1 fi if [ ! -f $2 ] then echo "$2 is not a common file" exit 1 fi file1_line=`cat $1 | wc -l` echo $file1_line file2_line=`cat $2 | wc -l` echo $file2_line if [ $file1_line -eq $file2_line ] then echo "both file have $file1_line lines" elif [ $file1_line -gt $file2_line ] then echo " $1 have $file1_line lines more than $2 have $file2_line" else echo " $2 have $file2_line lines more than $1 have $file1_line" fi file1_spaceline=`grep "^$" $1 | wc -l` echo $file1_spaceline file2_spaceline=`grep "^$" $2 | wc -l` echo $file2_spaceline if [ $file1_spaceline -eq $file2_spaceline ] then echo "both file have $file1_spaceline lines" elif [ $file1_spaceline -gt $file2_spaceline ] then echo " $1 have $file1_spaceline space lines more than $2 have $file2_spaceline" else echo " $2 have $file2_spaceline space lines more than $1 have $file1_spaceline" fi [root@localhost test]# bash countspace.sh /test/countspace.sh /etc/fstab 51 16 /test/countspace.sh have 51 lines more than /etc/fstab have 16 9 1 /test/countspace.sh have 9 space lines more than /etc/fstab have 1 [root@localhost test]# bash countspace.sh /test/countspace.sh useage: scrip filepath1 filepath2 [root@localhost test]# bash countspace.sh /test/countspace.sh /etc /etc is not a common file [root@localhost test]# bash countspace.sh useage: scrip filepath1 filepath2
9、写一个脚本
(1) 提示用户输入一个字符串;
(2) 判断:
如果输入的是quit,则退出脚本;
否则,则显示其输入的字符串内容;
[root@localhost test]# vim quitscript.sh #!/bin/bash read -p "please input a string:" -t 10 str1 if [[ -z "$str1" ]] then echo "please input something" elif [[ "$str1" == "quit" ]] then exit 0 else echo "you inupt is $str1" fi [root@localhost test]# bash quitscript.sh please input a string: please input something [root@localhost test]# bash quitscript.sh please input a string:test you inupt is test [root@localhost test]# bash quitscript.sh please input a string:quit
10、写一个脚本,打印2^n表;n等于一个用户输入的值;(不好意思,我调皮了)
[root@localhost test]# vim power2.sh #!/bin/bash if [ $# -lt 1 ] then echo "usage: command number" exit 1 fi if [ $1 -le 0 ] then echo "please input a number big the 0" elif [ $1 -eq 1 ] then echo "2x1=2" else sum=2 echo -n "2" for i in `seq 2 $1` do let sum*=2 echo -n "X2" done echo "=$sum" fi [root@localhost test]# bash power2.sh usage: command number [root@localhost test]# bash power2.sh 0 please input a number big the 0 [root@localhost test]# bash power2.sh 1 2x1=2 [root@localhost test]# bash power2.sh 2 2X2=4 [root@localhost test]# bash power2.sh 3 2X2X2=8 [root@localhost test]# bash power2.sh 4 2X2X2X2=16 [root@localhost test]# bash power2.sh 8 2X2X2X2X2X2X2X2=256 [root@localhost test]# bash power2.sh 32 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2=4294967296
11、写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、取给定两个数值的最大公约数;函数3、取给定两个数值的最小公倍数;关于函数的选定、两个数值的大小都将通过交互式输入来提供。
[root@localhost test]# vim testfun.sh #!/bin/bash while [ ture ] do echo "calcule usage is script operater number1 number2" echo "operater have 3 methord:" echo -e "1.summary usage example: \033[31msum number1 number2\033[0m" echo -e "2.Least Common Multiple (LCM) usage example: \033[31mlcm number1 number2\033[0m" echo -e "3.Greatest Common Divisor(GCD) usage example: \033[31mgcd number1 number2\033[0m" echo -e "inupt \033[31mquit\033[0m this script will exit" read -p "please input select: " op num1 num2 function testsum() { clear echo "=================================================" echo -e "\033[31msum is `expr $num1 \* $num2` \033[0m" echo "=================================================" } function gongyue() { a=$num1 local b=$num2 local tmp=0 if [ $a -lt $b ] then tmp=$a a=$b b=$tmp fi while [ $b -ne 0 ] do tmp=$(($a%$b)) a=$b b=$tmp done clear echo "=================================================" echo -e "\033[31mgongyue is $a\033[0m" echo "=================================================" } function gongbei() { clear echo "=================================================" echo -e "\033[31mgongbei is $(($num1*$num2/$a))\033[0m" echo "=================================================" } if [[ "$op" == "quit" ]] then break exit 0 elif [[ "$op" == "sum" ]] then testsum num1 num2 elif [[ "$op" == "lcm" ]] then gongyue num1 num2 elif [[ "$op" == "gcd" ]] then gongbei num1 num2 else echo "input error" fi done [root@localhost test]# bash testfun.sh calcule usage is script operater number1 number2 operater have 3 methord: 1.summary usage example: sum number1 number2 2.Least Common Multiple (LCM) usage example: lcm number1 number2 3.Greatest Common Divisor(GCD) usage example: gcd number1 number2 inupt quit this script will exit please input select: sum 1397 2413 ================================================= sum is 3370961 ================================================= calcule usage is script operater number1 number2 operater have 3 methord: 1.summary usage example: sum number1 number2 2.Least Common Multiple (LCM) usage example: lcm number1 number2 3.Greatest Common Divisor(GCD) usage example: gcd number1 number2 inupt quit this script will exit please input select: quit please input select: lcm 1397 2413 ================================================= gongyue is 127 ================================================= calcule usage is script operater number1 number2 operater have 3 methord: 1.summary usage example: sum number1 number2 2.Least Common Multiple (LCM) usage example: lcm number1 number2 3.Greatest Common Divisor(GCD) usage example: gcd number1 number2 inupt quit this script will exit please input select: gcd 1397 2413 ================================================= gongbei is 26543 ================================================= calcule usage is script operater number1 number2 operater have 3 methord: 1.summary usage example: sum number1 number2 2.Least Common Multiple (LCM) usage example: lcm number1 number2 3.Greatest Common Divisor(GCD) usage example: gcd number1 number2 inupt quit this script will exit please input select: quit