输出重定向
【>】 # 先创建文件再导出,多次定向会覆盖内容
[root@localhost ~]# ls
1.txt
[root@localhost ~]# ls > 2.txt # 过程:创建2.txt-----显示1.txt和2.txt-----把1.txt和2.txt作为内容导给2.txt这个文件
[root@localhost ~]# ls
1.txt 2.txt
[root@localhost ~]# cat 2.txt
1.txt
2.txt
【>>】 # 先创建文件再导出,多次定向会追加内容
[root@localhost ~]# ls
1.txt
[root@localhost ~]# ls >> 2.txt # 过程:创建2.txt-----显示1.txt和2.txt-----把1.txt和2.txt作为内容导给2.txt这个文件
[root@localhost ~]# ls
1.txt 2.txt
[root@localhost ~]# cat 2.txt
1.txt 2.txt
[root@localhost ~]# ls >> 2.txt # 再次定向会追加内容,而不是覆盖内容
[root@localhost ~]# cat 2.txt
1.txt
2.txt
1.txt
2.txt
【2>】 【2>>】 #错误输出重定向
[root@localhost ~]# ls wmc.txt
ls: 无法访问wmc.txt: 没有那个文件或目录
[root@localhost ~]# ls wmc.txt > b.txt
ls: 无法访问wmc.txt: 没有那个文件或目录
[root@localhost ~]# ls wmc.txt 2> b.txt
[root@localhost ~]# cat b.txt #b.txt文件的内容中有报错输出
ls: 无法访问wmc.txt: 没有那个文件或目录
【&>】 【&>>】 #正确输出和错误输出一起重定向
[root@localhost ~]# ls 1.txt wmc.txt
ls: 无法访问wmc.txt: 没有那个文件或目录
1.txt
[root@localhost ~]# ls 1.txt wmc.txt > b.txt #正确输出导入b.txt,错误输出留下
ls: 无法访问wmc.txt: 没有那个文件或目录
[root@localhost ~]# ls 1.txt wmc.txt 2> b.txt #错误输出导入b.txt,正确输出留下
1.txt
[root@localhost ~]# ls 1.txt wmc.txt &> b.txt #正确输出和错误输出一起重定向 [root@localhost ~]# cat b.txt
ls: 无法访问wmc.txt: 没有那个文件或目录
1.txt
一个合格规范的脚本应该包含以下这些内容
①#!脚本声明(使用哪种解释器解释代码)
②注释信息(步骤、思路、用途等),以#开始的为注释信息
③可执行的语句
[root@localhost ~]# vim first.sh
#!/bin/bash
#A test program for Shell.
echo "Hello World"
[root@localhost ~]# chmod +x first.sh
[root@localhost ~]#/root/first.sh
执行脚本的多种方式
方法一,需要为文件赋予可执行的权限
#[root@localhost ~]# chmod +x first.sh
-绝对路径执行
-相对路径执行
方法二,不需要文件有可执行的权限
sh/bash 脚本文件名
source 脚本文件名 #不会启动子进程,通过pstree查看进程树
变量
定义变量
以固定的名称,存放可以能有变化的
定义变量的格式: 变量名=变量值
取消变量的格式: unset 变量名
注意事项 =两边不能有空格,不要使用关键字做变量名,如Is、cd等
如果变量名已经存在则覆盖之前的变量值
变量名称有:字母/数字/下划线组成,不能以数字开始
[root@localhost ~]# a=11
[root@localhost ~]# echo $a
11
[root@localhost ~]# echo $a33 #用{}包裹变量,后面可加其他,否则可能引起识别错误
[root@localhost ~]# echo ${a}33
1133
变量类型
环境变量 (变量名通常大写,有操作系统维护)
位置变量 (bash内置变量,存储脚本执行时的参数)
预定义变量(bash内置变量,可以调用但是不能赋值或修改)
自定义变量 (用户自主设置)
环境变量
-存储在/etc/profile或~/.bash_profile
-命令env可以列出所有环境变量
-常见环境变量: PATH、PWD、USER、UID、HOME、SHELL
[root@localhost~]#echo $PATH
[root@localhost~]# echo $UID
位置变量 -存储脚本执行时的参数
使用$n表示,n为数字序列号
$1、$2、...、${10}、${11}、...
[root@localhost ~]# vim useradd.sh
#!/bin/bash
useradd "$1" echo "$2" | passwd --stdin "$1"
[root@localhost ~]# sh useradd.sh lisi 123123
更改用户 lisi 的密码。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# tail -1 /etc/passwd
lisi❌1001:1001::/home/lisi:/bin/bash
预定义变量
用来保存脚本程序的执行信息
-直接使用这些变量
-不能直接为这些变量赋值
$0 当前所在的进程或脚本名
$$ 当前运行进程的PID号
$? 命令执行后的返回状态,0表示正常,1或其他值表示异常
$# 已加载的位置变量的个数
$* 所有位置变量的值
多种引号的区别
区分三种定界符
-双引号””:允许扩展,以$引用其他变量
-单引号'':禁用扩展,即便$也视为普通字符
-反引号:将命令的执行输出作为变量值,$()与反引号等效
[root@localhost ~]# aa=`tail -1 /etc/passwd`
#输出作为变量
[root@localhost ~]# echo $aa
lisi❌1001:1001::/home/lisi:/bin/bash
read标准输入取值
read 从键盘读入变量值完成赋值
格式:read [-p”提示信息”] 变量名
-p可选,-t可指定超时秒数,-s设置是否在终端显示输入的内容
[root@localhost ~]# read -p "请输入姓名:" name
请输入姓名:lisi
[root@localhost ~]# echo $name
lisi
[root@localhost ~]# vim read.sh
#!/bin/bash
read -p"请输入用户名:" name
read -p"请输入密码:" pass #-s不在终端显示输入的内容
useradd "$name" echo "$pass" | passwd --stdin $name
[root@localhost ~]# sh read.sh
请输入用户名:zhangsan
请输入密码:123123
更改用户 zhangsan 的密码 。
passwd:所有的身份验证令牌已经成功更新。
-局部变量 #如x=11 新定义的变量默认只在当前Shell环境中有效,无法在子Shell环境中使用全局
-全局变量 #如export x=11 全局变量在当前Shell及子Shell环境中均有效
shell中的运算
基本运算法则
-加法:num1 + num2
-减法:num1- num2
-乘法:num1 * num2
-整除:num1 / num2
-取余:num1% num2
简写表达式 完整表达式
i++ i=i+1
i-- i=i-1
i+=2 i=i+2
i-=2 i=i-2
j=2 i=i2
i/=2 i=i/2
i%=2 i=i%2
$[]算式替换
使用$[]或$(())表达式 let不显示结果 expr \
-格式:$[整数1 运算符 整数2....]
-计算结果替换表达式本身,可结合echo命令输出
[root@localhost ~]# echo $[1+2]
3
[root@localhost ~]# echo $[5%3]
2
[root@localhost ~]# echo $[5/3]
1
[root@localhost ~]# x=1 y=2
[root@localhost ~]# echo $[x+y]
3
小数运算
echo "scale=n(几位小数) ;浮点运算" |bc scale=n(几位小数)
awk ' BEGIN{print 浮点运算} '
条件测试操作
test 【选项】【参数】 / [ 选项 参数 ]
字符测试
-z 是否为空
= 等于
!= 不等于
-n 是否有字符串存在
文件状态测试
[操作符 文件或目录]
-e 判断对象是否存在(Exist),若存在则结果为真
-d 判断对象是否为目录(Directory),是则为真
-f 判断对象是否为一般文件(File),是则为真
-r 判断对象是否有可读(Read)权限,是则为真
-w判断对象是否有可写(Write)权限,是则为真
-x对象是否有可执行(Xcute)权限,是则为真
整数值比较
[整数值1 操作符 整数值2] / (( ))
-eq 等于(Equal)
-ne 不等于(Not Equal)
-ge 大于或等于(Greater or Equal)
-le 小于或等于(Less or Equal)
-gt大于(Greater Than)
-It 小于(Less Than)
控制符:组合命令
; 命令1 ;命令2 ;命令n... #顺序执行,命令间无逻辑关系。
-a或&& 命令1 && 命令2 && 命令n... #顺序执行,命令间有逻辑关系,仅当前一条命令执行成功,后续才会执行,否则停止执行。
-o或|| 命令1 || 命令2 || 命令n... #顺序执行,命令间无逻辑关系,前一条命令执行失败,后续执行。前一条命令执行成功,后续不执行。
if 语句
-if 单分支
if 条件测试 / 【表达式】 && a
then
命令序列
fi
[root@localhost ~]# vim read.sh
#!/bin/bash
read -p"请输入用户名:" name
read -p"请输入密码:" pass
if [ ! -z "$name" ] && [ ! -z "$pass" ]
then
useradd "$name" echo "$pass" | passwd --stdin $name
fi
echo #输入的用户或密码任一为空时,创建用户不成功
-if 双分支
if 条件测试 【表达式】 && a || b
then
命令序列1
else
命令序列2
fi
[root@localhost ~]#vim ping.sh
#!/bin/bash if [ -z "$1" ]
then
echo -n "用法:脚本 "
echo -e "\033[32m域名或IP\033[0m"
exit
fi
ping -c2 -i0.1 -W1 "$1" &>/dev/null
if [ $? -eq 0 ]
then
echo "$1 is up"
else
echo "$1 is down"
fi
-if 多分支
if 条件测试 1
then
命令序列1
elif
条件测试2
then
命令序列2
.... ........
else
命令序列n
fi
for 循环
-根据变量的不同取值,重复执行命令序列
for 变量 in 值列表
do
命令序列
done
#!/bin/bash #批量创建用户
for i in {1..10} #$(cat user.txt)把用户名写入文件中调用
do
useradd test$i echo "995620" | passwd --stdin tast$1
done
for((初值;条件;步长))
do
命令序列
done
[root@localhost ~]# vim 99.sh # 打印99乘法表
#!/bin/bash
for ((i=1;i<=9;i++))
do
for ((j=1;j<=i;j++))
do
echo -en "$j$i=$[ij]\t"
done
echo
done
while 循环
while 条件测试
do
命令序列
done
[root@localhost ~]# vim while.sh #打印1-5
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo $i
let i++
done
[root@localhost ~]# vim while2.sh #创建用户
#!/bin/bash
a=user ; i=1
while [ $i -le 5 ]
do
useradd ${a}$i echo "995620" | passwd --stdin ${a}$i
let i++
done 、
case语句
case 变量 in
模式1)
命令序列1 ;;
模式2)
命令模式2 ;;
...... *)
默认命令序列
esac
数组
数组也是变量,是存储多个数据的集合。
[root@localhost ~]# test=(aa bb cc)
[root@localhost ~]# echo ${test[1]}
bb
shell函数
在shell环境中,将一些需要重复使用的操作,定义为公共的语句块,即可称为函数。
function 函数名 { 函数名 (){
命令序列 命令序列
} }
中断与退出
exit 退出shell脚本进程,exit执行后,脚本后面所有的语句都不会执行
break 跳出单层循环,break 2 跳出2层循环,循环内break后面的语句不会执行,但是循环外的语句仍然会执行
continue 终止某次循环的执行,但不会完全终止整个循环 ,while until 循环中使用需要慎重!因为如果continue放在变量迭代语句前面会造成死循环