1. shell基础 #

1.1 echo #

echo hello
echo -e "a\tb"

1.2 编写执行shell #

hello.sh

#!/bin/bash
echo hello
//通过Bash调用执行脚本
sh hello.sh
//赋予执行权限,直接运行
chmod 755 hello.sh
chmod u+x hello.sh
./hello.sh

1.3 别名 #

1.4 命令的生效顺序 #

1.5 命令快捷键 #

命令 含义
ctrl+c 强制终止当前命令
ctrl+l 清屏
ctrl+a 光标移动到命令行首
ctrl+e 光标移动到命令行尾
ctrl+u 从光标所在的位置删除到行首

1.6 历史命令 #

1.7 调用 #

history -c
1  echo 1
2  echo 2
3  echo 3
!2
!!
!echo

1.8 输出重定向 #

1.8.1 标准输入输出 #

设备 设备文件名 文件描述符 类型
键盘 /dev/stdin 0 标准输入
显示器 /dev/stdout 1 标准输出
显示器 /dev/stderr 2 标准错误输出
类型 符号 作用
标准输出重定向 命令 > 文件 以覆盖的方式,把命令的正确输出输出到指定的文件或设备当中
标准输出重定向 命令 >> 文件 以追加的方式,把命令的正确输出输出到指定的文件或设备当中
错误输出重定向 命令>文件 以覆盖的方式,把命令的错误输出输出到指定的文件或设备当中
错误输出重定向 命令>>文件 以追加的方式,把命令的错误输出输出到指定的文件或设备当中
正确输出和错误输出同时保存 命令>文件 2>&1 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中
正确输出和错误输出同时保存 命令>文件 2>>&1 以追加的方式,把正确输出和错误输出都保存到同一个文件当中
正确输出和错误输出同时保存 命令&>文件 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中
正确输出和错误输出同时保存 命令&>>文件 以追加的方式,把正确输出和错误输出都保存到同一个文件当中
正确输出和错误输出同时保存 命令>>文件1 2>文件2 以覆盖的方式,正确的输出追加到文件1中,把错误输出追加到文件2中

1.8.2 输入重定向 #

wc < a.txt

1.9 管道符号 #

1.9.1 多命令顺序执行 #

多命令执行符 格式 作用 案例
; 命令1;命令2 多个命令执行,命令之间没有任何逻辑联系 echo 1;echo 2;
&& 命令1&&命令2 逻辑与 当命令1正确执行,则命令2才会执行 当命令1执行不正确,则命令2不会执行 echo 1&&echo 2;
\\ 命令1\\ 命令2 逻辑或 当命令1执行不正确,则命令2才会执行 当命令1正确执行,则命令2不会执行 echo 1\\echo 2;
echo 1;echo 2;
echo 1&&echo 2;
echo 1||echo 2;

1.9.2 管道符号 #

ls /etc/ | more
netstat -an | grep ESTABLISHED | wc -l

1.9.3 通配符 #

通配符 作用
? 匹配一个任意字符
* 匹配0个或任意字符,也就是可以匹配任意内容
[] 匹配中括号中任意一个字符
[-] 匹配中括号中任意一个字符,-代表范围
[^] 匹配不是中括号中的一个字符

1.9.4 其它符号 #

符号 作用
'' 单引号。在单引号中所有的特殊符号,如$和`都没有特殊含义
"" 双引号,在双引号里特殊符号都没有特殊含义,但是 $ ` \ 例外,拥有调用变量值,引用命令和转义的含义
反引号,扩起来的是系统命令
$() 和反引号一样
# 在shell脚本中,#开头的行代表注释
$ 用于调用变量的值
\ 转义符号
echo '$PATH'
echo "$PATH"
echo `ls`
echo $(ls)
echo -e "a\tb"

2. 变量 #

2.1 什么是变量 #

2.2 变量的分类 #

2.3 用户自定义变量 #

2.3.1 定义变量 #

name="zhufeng"
age=10

2.3.2 输出变量值 #

echo $变量名

2.3.3 值默认都是字符串 #

$ x=1
$ y=2
$ z=3
$ k=$x+$y+$z
$ echo $k
1+2+3

2.3.4 在赋值的时候引用变量 #

m="$x"2
n=${x}2
echo $m $n

2.3.5 set #

set | grep zhufeng

2.3.6 unset #

unset a

2.4 环境变量 #

2.4.1 自定义环境变量 #

export 变量名=变量值
export envName=prod

2.4.2 env #

2.4.3 常用环境变量 #

变量名 含义 示例
HOSTNAME 主机名 HOSTNAME=localhost
SHELL 当前的shell SHELL=/bin/bash
HISTSIZE 历史命令条数 HISTSIZE=1000
SSH_CLIENT 当前操作环境如果是用SSH连接的话,这里会记录客户端IP SSH_CLIENT=192.168.1.100 57596 22
USER 当前登录的用户 USER=root
echo $HOSTNAME
echo $SHELL
echo $HISTSIZE
echo $SSH_CLIENT
echo $USER

2.4.4 path #

# echo $PATH
/usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

如果想把一个自定义的脚本直接可以执行,或者把这个文件拷贝到目标目录下,或者把脚本所在目录添加到环境变量中的PATH路径中

/root/shells/hello.sh

#!/bin/bash
echo hello
export PATH="$PATH":/root/shells
hello.sh

2.4.5 语系环境变量 #

locale
LANG=zh_CN.UTF-8

echo $LANG

2.4.6 中文支持 #

2.5 位置参数变量 #

位置参数变量 作用
$n n为数字,$0代表命令本身,$1-$9代表第1到第9个参数,10以上的参数需要用大括号包含,如${10}
$* 这个变量代表命令中所有的参数,$*把所有的变看数看成一个整体
$@ 这个变量也代表命令行中所有的参数,不过$@把每个参数进行区分
$# 这个变量代表命令行中所有参数的个数

sum.sh

#!/bin/bash
num1=$1
num2=$2
sum=$((num1+num2))
echo $sum
sh sum.sh 3 4

vi for.sh

#!/bin/bash
for i in "$@"
 do
   echo "i=$i"
 done
sh for.sh 1 2 3
i=1
i=2
i=3

vi for2.sh

#!/bin/bash
for i in "$#"
 do
   echo "i=$i"
 done
sh for2.sh 1 2 3
i=1 2 3

vi for3.sh

#!/bin/bash
echo "$#"
sh for3.sh 1 2 3
3

2.6 预定义变量 #

位置参数变量 作用
$? 最后一次执行的命令的返回状态。0表示正确执行,非0表示不正确执行
$$ 当前进程的进程号(PID)
echo $?
echo $$

2.7 read #

read [选项] [变量名]

选项 含义
-p 提示信息,在等待read输入时,输出提示信息
-t 秒数: read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数,read命令只接受指定的字符数,就会执行
-s 隐藏输入的数据,适用于机密信息的输入
#!/bin/bash
read -p 'please input your name:' -t 5 name
echo -e "\n"
read -p 'please input you gender[m/f]:' -n 1 gender
echo -e "\n"
read -p 'please input your password:' -s password
echo -e "\n"
echo $name,$gender,$password
sh read.sh

3. 运算符 #

3.1 declare命令 #

3.1.1 declare命令 #

选项 含义
- 给变量设定类型属性
+ 取消变量的类型属性
-a 将变量声明为数组类型
-i 将变量声明为整数型
-x 将变量声明为环境变量
-r 将变量声明为只读变量
-p 显示指定变量的被声明的类型
a=1
b=2
c=$a+$b
echo $c
1+2
declare -i c=$a+$b //声明成整型
echo $c
3
declare +i c //取消变量的类型属性
c=$a+$b
echo $c
1+2
declare -i c="3" //给变量设定类型属性
declare -p c //显示指定变量的被声明的类型
//declare -i c="3"

//声明环境变量
declare -x kk=1
set | grep kk      //查看所有变量
env | grep kk      //只查看系统变量

declare -r x //只读
x=2  //bash: x: readonly variable

3.1.2 数组 #


//声明为数组类型
declare -a names;

names[0]=zhangsan
names[1]=lisi

//默认只打印第一个元素
echo ${names}
zhangsan
//打印第2个元素
echo ${names[1]}
lisi
//打印全部
echo ${names[*]}
zhangsan lisi

3.1.3 声明环境变量 #

export NAME=zhufeng
declare -x NAME=zhufeng

3.1.4 只读属性 #

declare -r gender=m
gender=f
-bash: gender: readonly variable

3.1.5 查询变量属性 #

3.2 数值运算的方法 #

3.2.1 expr或let #

num1=2
num2=3
sum=$(expr $num1 + $num2)
echo $sum
5
sum2=$(($num1+$num2))
echo $sum2
5
sum3=$[$num1+$num2]
echo $sum3
5

d=$(date)
echo $d

3.2.2 优先级 #

priority

result=$(((1+2)*4/2))
echo $result
6

4. 环境变量配置文件 #

4.1 source 命令 #

4.2 环境变量配置文件简介 #

路径 说明
/etc/profile
/etc/bashrc
~/.bash_profile 只会对当前用户生效
~/.bashrc 只会对当前用户生效

f49353175c1062b807c03b03bd9b5817

4.3 环境变量配置文件的功能 #

4.3.1 /etc/profile #

cat  /etc/profile | grep USER
变量名 含义
USER 用户名
LOGNAME 登录名
MAIL 邮箱地址
PATH 查找路径
HOSTNAME 主机名
umask 权限掩码
/etc/profile.d/星.sh

4.3.2 ~/.bash_profile #

4.3.3 ~/.bashrc #

4.3.4 /etc/bashrc #

4.3.5. 其它配置文件 #

4.3.5.1 注销时生效的环境变量配置文件 #
4.3.5.2 脚本历史 #
4.3.5.3 Shell登录信息 #
参数 含义
\d 当前系统日期
\s 显示操作系统名称
\l 显示登录的终端号
\m 显示硬件体系结构,如i386等
\n 显示主机名
\o 显示域名
\r 显示内核版本
\t 显示当前系统时间
\u 显示当前登录用户的序列号
vi /etc/ssh/sshd_config
Banner /etc/issue.net
service sshd restart

4.正则表达式 #

4.1 概念 #

4.2 通配符 #

符号 含义
? 匹配任意一个字符
* 匹配任意多个字符
[] 匹配中括号中范围内的一个字符

4.3 正则表达式 #

4.4 元字符 #

alias grep='grep --color=auto'

元字符 作用 示例
* 前一个字符匹配 0 次或任意多次 grep 1* reg.txt
. 匹配除换行符外的任意一个字符 grep . reg.txt
^ 匹配行首。例如,^hello 会匹配以 hello 开头的行 grep ^a reg.txt
$ 匹配行尾。例如,hello& 会匹配以 hello 结尾的行 grep a$ reg.txt
[] 匹配屮柄号屮指定的任意一个字符,而且只匹配一个字符。
例如.[aoeiu]匹配任意一个元音字母, [0-9] 匹配任意一位数字,
[a-z][0-9] 匹配由小写字母和一位数字构成的两位字符
grep ab[bc]c reg.txt
[^] 匹配除中括号中的字符以外的任意一个字符。例如,[^0-9] 匹配任意一位非数字字符,
[^a-z] 匹配任意一位非小写字母
grep a[^fg]c reg.txt
\ 转义符,用于取消特殊符号的含义 grep \.$ reg.txt
{n} 表示其前面的字符恰好出现 n 次。例如,[0-9]{4} 匹配4位数字,[1][3-8][0-9]{9} 匹配手机号码 grep "a{1}" reg.txt
(n,} 表示其前面的字符出现不少于 n 次。例如,[0-9]{2,} 匹配两位及以上的数字 grep "a{1,}" reg.txt
{n,m} 表示其前面的字符至少出现 n 次,最多出现 m 次。例如,[a-z]{6,8} 匹配 6〜8 位的小写字母 grep "a{2,3}" reg.txt

4.5 cut #

提取用户名和它使用的shell

cat /etc/passwd | cut -f 1,7 -d :

4.6 printf #

参数 含义
%ns 输出字符串,n是数字指代输出几个字符
%ni 输出整数,n是指输出几个数字
%m.nf 输出浮点数,m和n是数字,指代输出的整数位数和小数位数,如%6.2f代表输出6位位,2位小数,4位整数
printf "%s\t%s\t%s\t%s\t%s\t\%s\n" $(df -h | grep /dev/vda1) | cut -f 1,5

4.7 awk #

df -h | grep /dev/vda1 |awk '{print $5}'| cut -d '%' -f 1

4.7.1 begin end #

echo "" > numbers.txt
awk 'BEGIN{print "开始"}END{print "结束"}' numbers.txt 

4.7.2 FS #

awk 'BEGIN{FS=":"}{print $1"\t"$2}' /etc/passwd

4.7.3 声明变量 #

numbers.txt

1
2
3
awk 'BEGIN{sum=0}{sum=sum+$1}END{print sum}' numbers.txt 
6

4.7.4 多条件 #

score.txt

zhangsan 91
li 81
wangwu 71
awk '$2>90{print $1"\t优秀"}$2>80{print $2"\t良好"}' score.txt

4.7.5 NR #

awk '{print NR,$0}' score.txt

4.7.6 OFS #

echo "i love you" | awk 'BEGIN{ FS=" ";OFS="-" }{print $1,$2,$3}'

4.8 sed命令 #

4.8.1 动作 #

参数 含义 示例
a 追加,在每一行或者指定行下面添加一行或多行 sed '1a newline' score.txt
c 行替换,用c后面的字符串替换掉原始整个数据行 sed 'c newline' score.txt
s 字符串替换,用一个字符串替换另外一个字符串,格式为 "行范围s/旧字符串/新字符串/g" sed '3s/lisi/lisisi/g' score.txt
i 插入,在当前行插入一行或多行 sed '1i newline' score.txt
d 删除指定的行 sed '1,2d' score.txt
p 打印,输出指定的行 sed -n '2p' score.txt

4.8.2 选项 #

参数 含义 示例
-n 一般sed命令会把所有的数据都输出到屏幕上,如果加入此选项则只会把处理过的行输出到屏幕上 sed -n '2p' score.txt
-e 允许对输入数据应用多条sed编辑命令 sed -e 's/91/92/g;s/81/82/g' score.txt
-i 用sed的修改直接修改编辑的文件,而不是在屏幕上输出 sed -i '1i newline' score.txt

4.9 排序命令sort #

选项 含义
-f 忽略大小写 sort -f -t ":" -n -k 5,5 /etc/passwd
-n 以数值型进行排序,默认使用字符串顺序 sort -t ":" -n -k 3,3 /etc/passwd
-r 反向排序,默认从小到大 sort -r /etc/passwd
-t 指定分割符,默认分割符是制表符 sort -t ":" -k 3,3 /etc/passwd
-k n[,m] 按照指定的字段范围排序。从第n个字段开始,到第m个字段结束,默认是到行尾 sort -t ":" -k 3,3 /etc/passwd
sort /etc/passwd
sort -r /etc/passwd
sort -t ":" -k 3,3 /etc/passwd

4.10 wc #

选项 含义
-l 只统计行数
-w 只允许单词数
-m 只统计字符数
wc wc.txt 

5. 流程控制 #

5.1 条件判断 #

5.1.1 按照文件类型进行判断 #

选项 含义
-d 文件是否存在并且是目录
-e 文件是否存在
-f 文件是否存在并且是普通文件
-b 文件是否存在并且是块设备文件
-c 文件是否存在并且是字符设备文件
-L 文件是否存在并且是链接文件
-p 文件是否存在并且是管道文件
-s 文件是否存在并且是否为非空
-S 文件是否存在并且是套接字文件
touch 1.txt
test -e 1.txt
[-e 1.txt]
echo $?

exist.sh

[ -e 1.txt ]&&echo "yes"|| echo "no"
yes
[ -e 11.txt ]&&echo "yes"|| echo "no"
no

5.1.2 按照文件权限进行判断 #

选项 含义
-r 文件是否存在,并且是否拥有读权限
-w 文件是否存在,并且是否拥有写权限
-x 文件是否存在,并且是否拥有执行权限
echo read  > read.txt
echo write  > write.txt
echo execute  > execute.txt

chmod u+w write.txt 
chmod u+x execute.txt

[ -r read.txt ]&&echo "read yes"|| echo "no"
[ -w write.txt ]&&echo "write yes"|| echo "no"
[ -x execute.txt ]&&echo "execute yes"|| echo "no"

5.1.3 两个文件间的比较 #

选项 含义
文件1 -nt 文件2 判断文件1的修改时间是否比文件2的新
文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧
文件1 -ef 文件2 判断文件1和文件2的inode号是否一致,可用于判断硬链接
[ write.txt -nt read.txt ]&&echo "write is older than read"|| echo "no"
[ read.txt -ot write.txt ]&&echo "read is older than write"|| echo "no"
ln execute.txt execute2.txt
[ execute.txt -ef execute2.txt ]&&echo "execute and execute2.txt are the same"|| echo "no"

5.1.4 两个整数间的比较 #

选项 含义
整数1 -eq 整数2 判断整数1是否和整数2相等
整数1 -ne 整数2 判断整数1是否和整数2不相等
整数1 -gt 整数2 判断整数1是否大于整数2
整数1 -lt 整数2 判断整数1是否小于整数2
整数1 -ge 整数2 判断整数1是否大于等于整数2
整数1 -le 整数2 判断整数1是否小于等于整数2
[ 2 -eq 2 ]&&echo "2==2"|| echo "no"
[ 3 -ne 2 ]&&echo "2!=2"|| echo "no"
[ 3 -gt 2 ]&&echo "2>2"|| echo "no"
[ 1 -lt 2 ]&&echo "2<2"|| echo "no"
[ 2 -ge 2 ]&&echo "2>=2"|| echo "no"
[ 2 -le 2 ]&&echo "2<=2"|| echo "no"

5.1.5 字符串的判断 #

选项 含义
-z 字符串 判断字否串是否为空
-n 字符中 判断字符串是否为非空
字符串1 == 字符串2 判断字符串1是否和字符串2相等
字符串1 != 字符串2 判断字符串1是否和字符串2不相等
name=zhufeng
[ -z "$name" ]&&echo "空"|| echo "非空"
[ -n "$name" ]&&echo "非空"|| echo "空"
name2=zhufeng
[ "$name" == "$name2" ]&&echo "相等"|| echo "不相等"
[ "$name" != "$name2" ]&&echo "不相等"|| echo "相等"

5.1.6 多重条件判断 #

选项 含义
判断1 -a 判断2 逻辑与
判断1 -o 判断2 逻辑或
!判断 逻辑非
[ 2 -gt 1 -a 3 -gt 2 ]&&echo "yes"|| echo "no"
[ 2 -gt 1 -a 3 -gt 4 ]&&echo "yes"|| echo "no"
[ 2 -gt 1 -o 3 -gt 4 ]&&echo "yes"|| echo "no"
[ ! 3 -gt 4 ]&&echo "yes"|| echo "no"

5.2 单分支if语句 #

5.2.1 语法 #

if [条件判断];then
 代码体
fi
if [条件判断]
then
 代码体
fi
if [ 2 -gt 1 ];then echo bigger; fi

if [ 2 -gt 1 ]
then
 echo bigger
fi

5.2.2 判断当前用户是否是root用户 #

isRoot.sh

#!/bin/bash
user=$(whoami)
user=`whoami`
if [ "$user" == root ]
then
echo "我是root用户"
fi

5.3 双分支if语句 #

5.3.1 语法 #

if [条件判断]
then
 代码体1
else
 代码体2 
fi

5.3.2 判断是否目录 #

isDir.sh

#!/bin/bash
read -t 10 -p "请输入一个路径" dir
if [ -d "$dir" ]
then
  echo "$dir是目录"
else 
  echo "$dir不是目录"
fi

5.4 多分支if语句 #

5.4.1 语法 #

if [条件判断1]
then
 代码体1
elif [条件判断2] 
 代码体2
else
 代码体3
fi

grade.sh

#!/bin/bash
read -p "请输入一个分数" grade
if [ "$grade" -gt 90 ]
 then
  echo 优秀
elif [ "$grade" -gt 80 ]
  then
   echo 良
else
   echo 差
fi

5.5 case 语句 #

case.sh

#!/bin/bash
read -p "yes or no?" -t 30 choose
case $choose in 
  "yes")
    echo '是'
    ;;
  "no")
    echo "否"
   ;;
  *)
    echo 其它
   ;;
esac

5.6 for循环 #

5.6.1 语法 #

for 变量 in123
do
代码块
done

for.sh

#!/bin/bash
for i in 1 2 3
do
 echo $i
done

5.6.2 语法 #

#!/bin/bash  
for((i=1;i<=10;i++));  
do   
 echo $(($i));
done 

5.7 while循环 #

while [条件判断式]
do
 代码块
done

while.sh

#!/bin/bash
i=1
result=0
while [ $i -le 100 ]
 do
   result=$(($result+i))
   i=$(($i+1))
 done
echo $result

5.8 until循环 #

until.sh

#!/bin/bash
i=1
result=0
until [ $i -gt 100 ]
 do
   result=$(($result+i))
   i=$(($i+1))
 done
echo $result

6. 函数 #

6.1 简单函数 #

[ function ] funcName [()]
{
    action;
    [return int;]
}
start(){
>  echo start
> }
 start
#!/bin/bash
start(){
 echo start
}
start

6.2 返回值 #

sum(){
>  result=$(($1+$2))
>  return $result
> }
sum4 2 3
echo $?
5

6.3 参数说明 #

参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数
$$ 脚本运行的当前进程ID号
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

7.shell实战 #

7.1 注意事项 #

7.2 检查主机存活状态 #

ip.sh

#!/bin/bash
for IP in $@; do
  if ping -c 1 $IP &>/dev/null; then
     echo "$IP is ok."
  else
     echo "$IP is wrong!"
  fi
done       
sh ip.sh 127.0.0.1