Shell
#!/usr/bin/bash
ping -c1 10.18.43.123 &>/dev/null && echo "10.18.43.123 is up" || echo "10.18.43.123 is down"
# &> 混合输出,错误输出和标准输出全部重定向
# && 表示如果前面的执行成功后面才执行,|| 表示如果前面执行失败后面才执行,因此这里如果10.18.43.123是有效地址则会执行up否则执行down
# 只有第一行的/usr/bin/bash才是解释器后面的是注释
echo "hello bash"
!/usr/bin/bash
ping -c1 10.18.43.123 &>/dev/null && echo “10.18.43.123 is up” || echo “10.18.43.123 is down”
/usr/bin/python <<-EOF
print “hello world|”
print “hello world|”
EOF
echo “hello bash”
重定向由python执行,由python来执行,-表示最后的EOF表示可以缩进,如果没有-则表示最后一行不能缩进,EOF只是一个标识可以替换成任意合法字符,建议使用EOF
#!/usr/bin/bash
cd /home/
ls
# 执行时如果是./test.sh或者bash test.sh执行,目录不会发生变化,因为它是新开了一个shell来执行,子shell执行,不是在此shell来执行的,bash执行不需要执行权限,但是./执行需要权限
# 执行时如果是. test.sh或者source test.sh执行,目录会发生变化,因为在此shell执行,如果你修改的脚本中的东西能影响到当前shell,例如变量声明等等,就使用.或者source执行
# 查看shell
cat /etc/shells
# 启动的时候执行
/etc/bashrc 系统级
/etc/profile
# 启动的时候执行
~/.bashrc 用户级
~/.bash_profile
# 离开的时候执行.bash_logout
~/.bash_logout
# 离开的时候将命令写入.bash_history
~/.bash_history
# shell环境会发生改变,因为它切换时会执行~/.bashrc、~/profile、/etc/profile、/etc/bashrc,建议加入-
su - dyl
# shell环境不会发生改变,因为它切换时只会执行/etc/profile、/etc/bashrc
su dyl
# 命令历史补齐,!!上一个命令,!dat执行以dat开头的命令
上下键、!number、!string、!$、!!、^R
# 别名功能
alias、unalias cp
source ~/bashrc
# 搜索历史命令
^R
# 光标移动到最前(Ahead)
^A
# 光标移动到最后(End)
^E
# 暂停任务放到前台,可以将vim放到后面再通过fg调出任务
^Z
# 查看任务
jobs
# 调出后台任务
fg
# 弹出光驱
eject
# 不具备逻辑判断的命令排序;
ls ; cd
# 命令往前删除
^U
# 命令往后删除
^K
# 锁屏
^S
# 解屏
^Q
# 后台运行
sleep 300 &
# 将后台的输出定向到文件中
nohup sleep 300 &
# 安装screen,保存终端信息,就算退出终端了也能进来
apt-get install screen
# 新开一个终端,并且保存着终端信息
screen -S install_lnmp
# 列出当前有所有的终端屏幕
screen -list
# 进入终端屏幕
screen -r 618
# 拷贝
cat </etc/hosts >/etc/host1


# 管道
ip addr | grep 'inet' | grep eth0
ip addr | grep 'inet' | tee test | grep eth0
ip addr | grep 'inet' | tee -a test | grep eth0
# |tee管道将输出加到其它地方,但是不会截流,还是会进入| grep eth0,-a 表示追加
shell元字符
- * 匹配任意多个字符 ls in* rm -rf * rm -rf *.pdf find / -name “*-eth0”
- ? 匹配任意一个字符 touch lov loove live l7ve;ll l?ve
- [] 匹配括号中任意一个字符,^表示取反 [abc] [a-z] [0-9] [a-zA-Z0-9] 例如 ll l[io]ve ll l[^a-z]ve ll /dev/sd[a-z]
- () 在子shell中执行(cd /boot;ls) (umask 077;touch file1000)
- \ 转义符,让元符号回归本意
- {} 集合touch file{1..9}
# 打印当前目录所有的文件名
$ ehco *
$ mkdir /home/{111,222}
$ mkdir -pv /home/{333/{aaa,bbb},444}
$ cp -rv /etc/sysconfig/network-script/ifcfg-eth0 /etc/sysconfig/network-script/ifcfg-eth0.old
$ cp -rv /etc/sysconfig/network-script/{ifcfig-eth0,ifcfg-eth0.old}
$ cp -rv /etc/sysconfig/network-script/ifcfg-eth0{,old}
$ echo *
$ echo \*
$ touch yang\ sheng
mkdir \\
echo -e "atb"
echo -e "a\tb"
echo -e "anb"
echo -e "a\nb"
# ()在子shell中执行不会改变当前shell的变量
echo带颜色输出
echo -e 能解释后面加的特殊符号
$ echo -e "a\tb"
# 修改前景色,也就是文本颜色
$ echo -e "\e[1;31mHello World"
# 后面加\e[0m重置成原来的颜色
$ echo -e "\e[1;31mHello World\e[0m"
# 修改背景色
$ echo -e "\e[1;41mHello World\e[0m"
$ echo -e ""
shell变量
变量的意义
# 如果没有使用脚本,那么脚本的可扩展性会变得很差
#!/usr/bin/bash
ping -c1 10.10.10.10 &>/dev/null && echo "10.10.10.10 is up" || echo "10.10.10.10 is down!
#!/usr/bin/bash
ip=10.10.10.10
ping -c1 $ip &>/dev/null && echo "$ip is up" || echo "$ip is down!
# 变量名必须以字母或者下划线开头,区分大小写
# 查看是什么类型
$ type -a if
#!/usr/bin/bash
ip=10.10.10.10
if ping -c1 $ip &>/dev/null; then
echo "$ip is up"
else
echo "$ip is down"
fi
# 如果在一行上要放两个关键字要用分号分隔
#!/usr/bin/bash
ip=10.10.10.10
ping -c1 $ip &>/dev/null
if [ $? -eq 0 ]; then
echo "$ip is up"
else
echo "$ip is down"
fi
# [是命令,可以通过type -a [ 查看,[是用来做条件测试,[ 后面必须加空格,] 前面也必须加空格
#!/usr/bin/bash
read -p "Please input a ip: " ip
ping -c1 $ip &>/dev/null
if [ $? -eq 0 ]; then
echo "$ip is up"
else
echo "$ip is down"
fi
变量类型
#!/usr/bin/bash
ping -c1 $1 &>/dev/null
if [ $? -eq 0 ]; then
echo "$1 is up"
else
echo "$1 is down"
fi
./ping.sh 10.10.10.10 12.12.12.12
$1 $2
# 位置变量$1、$2、$3,$指的是引用变量的值,根据变量所处的位置来进行赋值
# 目前的三种赋值方式
ip=10.10.10.10
read ip
./ping.sh 10.10.10.10 12.12.12.12
# 1、自定义变量,仅仅在当前shell有效
ip=10.10.10.10
unset 变量名
# 2、环境变量,在当前shell和子shell有效
方法一:export ip=10.10.10.10
方法二:export ip # 将自定义变量转换为环境变量
unset 变量名
# 注意脚本执行的时候是在子shell执行还是在当前shell中执行
# 变量名必须以字母或下划线开头,区分大小写除了系统自定义的位置变量
# public.sh
ip=10.10.10.10
# 1.sh
. public.sh # 在当前shell中可以访问
echo $ip # 输出10.10.10.10
# 2.sh
. public.sh # 在当前shell中可以访问
echo $ip # 输出10.10.10.10
# 修改环境变量,修改/etc/profile文件最后一行加入
PATH=$PATH:/my/bin
export PATH
# 查看邮箱地址
echo $MAIL
# 查看shell地址
echo $SHELL
# 查看家目录
echo $HOME
# 显示所有的环境变量
env
# 显示历史记录的条数
env | grep HISTSIZE
# 也可以使用${}来引用变量
ping -c1 ${ip} &>/dev/null
if [ $? -eq 0 ]; then
echo "${ip}hello world is up"
else
echo "${ip}hello world is down"
fi
# 使用${}可以防止歧义
# ${}还有其它效果例如echo ${#ip} 显示变量的长度等等,会在以后讲解
# 位置变量
$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
# 预定义变量
# 脚本名
$0
# 所有参数
$*
# 所有参数
$@
# 参数个数
$#
# 当前进程PID
$$
# 上一个后台进程的PID
$!
# 上一个命令的返回值,0表示成功
$?
# text.txt
10.10.10.10
11.11.11.11
12.12.12.12
# ip.sh
/usr/bin/bash
if [ $# -eq 0 ];then
echo "usage: `basename $0` file"
exit
fi
if [ ! -f $1 ];then
echo "error file!"
exit
fi
for ip in `cat $1`
do
ping -c1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo "$ip is up."
else
echo "$ip is down."
fi
done
# ./ip.sh test.txt
# basename 显示文件名,dirname 显示目录
变量的赋值方式
# 显示赋值
ip=10.10.10.10
address="abc def"
today=$(date +%F)
today1=`date +%F`
# read从键盘读入变量值
read 变量名
read -p "提示信息:" 变量名
read -t 5 -p "提示信息:" 变量名
read -n 2 变量名
# $()和``都是命令替换,相互等价
# 变量强引用和弱引用,强引用'',弱引用""
强引用中的变量不会解析
shell中变量的运算
# 方法一:expr
$ expr 1+2
$ expr $num1+$num2
$ sum=`expr $num1+$num2`
# 方法二:$(())
$ echo $(($num1+$num2))
$ echo $((num1+num2))
$ echo $((5-3*2))
$ echo $(((5-3)*2))
$ sum=$((1+2));echo $sum
# 方法三:$[]
$ echo $[5+2]
$ echo $[5**2] # 5的二次方
$ echo $[2#10+12] # 二进制的10加上十进制的12等于14
$ sum=$[2+3];echo $sum
# 方法四:let
$ let sum=2+3;echo $sum
$ let i++;echo $i
# 展示当前内存使用百分比
#!/usr/bin/bash
mem_used=`free -m | grep '^Mem:' | awk '{print $3}'`
mem_total=`free -m | grep '^Mem:' | awk '{print $2}'`
mem_percent=$((mem_used*100/mem_total))
echo "当前内存使用百分比:$mem_percent"
bash -vx text.sh # 以调试的方式运行脚本
#!/usr/bin/bash
ip=10.10.10.10
i=1
while [ $i -le 5 ]
do
ping -c1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo "$ip is up..."
fi
let i++
done
# 小数运算
echo "2*4" |bc
echo "2^4" |bc
echo "scale=2;6/4" |bc
awk 'BEGIN{print 1/2}'
echo "print 5.0/2" |python
# bc 进入交互计算器模式
变量内容的删除和替换
$ url=www.baidu.com
$ echo ${#url} # 输出url有多少字符
$ echo ${url#*.}
$ echo ${url#www} # 从前往后,最短匹配
$ echo ${url##*.} # 从前往后,最长匹配,贪婪匹配
$ echo ${url%.*} #从后往前,最短匹配
$ echo ${url%%.*} #从后往前,最长匹配
# 索引以及切片
$ echo ${url:0:5} # 0是索引开始数五个
$ echo ${url:5:5} # 5是索引开始数五个
$ echo ${url:5}
# 内容替换
$ url=www.baidu.com
$ echo ${url/baidu/studylove}
$ echo ${url/w/W}
$ echo ${url//w/W} # 贪婪匹配
# 变量选择赋值
# 如果变量没有定义则将则进行赋值,否则不赋值
$ unset var1
$ echo ${var1}
$ echo ${var-studylove}
# 变量没有被赋值(包括空值):使用新值赋值
# 变量有被赋值:不会被替换
$ unset var1
$ echo ${var1:-abc}
$ echo ${var1-abc}
$ var1=
$ echo ${var1:-abc}
$ echo ${var1-abc}
# :-和-区别在于,:-当变量已经存在但是值为空值也会进行赋值
# :-是变量未赋值或者未定义则进行赋值
# -是变量未定义才会赋值
条件测试
# 条件测试三种方法
# test条件表达式
back_dir=/var/mydata
if ! test -d $back_dir;then
mkdir -p $back_dir
fi
echo "开始备份..."
bash -vx test_mydataback.sh # 以调试的方式执行脚本
# [条件表达式]
[ -d /home ] # [ 是命令,-d 是参数,/home 是参数,]也是参数,
# 所以必须加在必须加上空格,注意]只是一个参数
#/usr/bin/bash
back_dir=/var/mydata
if [ ! -d $back_dir ];then
mkdir -p $back_dir
fi
echo "开始备份..."
type -a [ # [查看类型
#/usr/bin/bash
if [ $USER != "root" ];then
echo "没有权限!"
exit
fi
yum -y install httpd
# 条件测试判断是否是root用户
# [[条件表达式]]
文件测试
# 条件测试[ 操作符 文件或目录 ]
[ -e dir|file ] # 判断是否存在
[ -d file ]
[ -f file ] # 是否是普通文件
[ -r file ] # 判断当前用户是否有读权限
[ -x file ]
[ -w file ]
[ -L file ] # 判断是否是符号链接
[ -b file ]
[ -c file ]
# 实例
[ ! -d /ccc ]&&mkdir /ccc # /ccc目录不存在则创建
[ -d /ccc ]||mkdir /ccc
grep 'cat $1' * # 从当前所有文件中过滤
# 数值比较
[ 1 -ge 10 ] # 大于等于
[ 1 -gt 10 ] # 大于
[ 1 -lt 10 ] # 小于
[ 1 -ne 10 ] # 不等于
[ 1 -le 10 ] # 小于等于
[ 1 -eq 10 ] # 等于
# 实例
#!/usr/bin/bash
read -p "Please input a username: " user
if id $user &>/dev/null; then
echo "user $user already exists"
else
useradd $user
if [ $? -eq 0 ]; then
echo "$user is created"
fi
fi
# 也可以将上述代码改成如下代码
#!/usr/bin/bash
read -p "Please input a username: " user
id $user &>/dev/null # 如果用户存在则会返回0,
# 但是用户不存在则会返回1
if [ $? -eq 0 ]; then
echo "user $user already exists"
else
useradd $user
if [ $? -eq 0 ]; then
echo "$user is created"
fi
fi
# 如果输出硬盘使用百分比
#/usr/bin/bash
disk_use=`df -Th | grep '/$' | \
awk '{print $(NF-1)}' | awk -F"%" '{print $1}'
mail_user=alice
# grep '/$' 过滤出以/结尾的那一行
# awk '{print $(NF-1)}' 选出最后一列
# awk -F"%" '{print $1}' 以%作为分割去掉%,方便后面的计算
if [ $disk_use -ge 10 ];then
echo "`data +%F-%H` disk: ${disk_use}" |mail -s \
"disk war..." $mail_user
# 发送邮件给$mail_user,主题是disk war...
fi
# bash -vx disk_use.sh
# C语言风格数值比较
((1<2));echo $?
((1==2));echo $?
((1>=2));echo $?
((`id -u`>0));echo $?
(($UID==0));echo $?
# 内存报警
#!/usr/bin/bash
mem_used=`free -m |grep '^Mem:' |awk '{print $3}'`
mem_total=`free -m |grep '^Mem:' |awk '{print $2}'`
mem_percent=$((mem_used*100/mem_total))
war_file=/tmp/mem_war.txt
rm -rf $war_file
if [ $mem_percent -ge 80 ];then
echo "`date +%F-%H` memory:\
${mem_percent}%" > $war_file
fi
if [ -f $war_file ];then
mail -s "mem war..." alice < $war_file
rm -rf $war_file
fi
# 字符串比较
# 提示:字符串比较必须加上双引号
[ "$USER"="root" ];echo $?
[ "$USER"=="root" ];echo $?
# =和==效果差不多的
[ -z "$abc" ] # 如果abc字符串是零则返回0否则返回1
[ -n "$abc" ] # 与上面的正好相反

```shell
unset var1
[ -z "$var1" ]
[ -n "$var1" ]
var2=
[ -z "$var2" ]
[ -n "$var2" ]
# 当变量为空或者未定义时,长度都为0
[ 1 -lt 2 -a 5 -gt 10 ];echo $?
[ 1 -lt 2 -o 5 -gt 10 ];echo $?
# -a表示都成立才成立
# -o表示只要一个成立就成立
[[ 1 -lt 2 && 5 -gt 10 ]]
[[ 1 -lt 2 || 5 -gt 10 ]]
# 只有[[]]中才能使用&&和||
# 创建用户
#!/usr/bin/bash
read -p "Please input number: " num
read -p "Please input prefix: " prefix
for i in `seq $num`
do
user=$prefix$i
useradd $user
echo "123" |passwd --stdin $user
if [ $? -eq 0 ];then
echo "$user is created"
fi
done
bash -n useradd01.sh # 检查是否存在语法错误
# 创建用户02
#!/usr/bin/bash
read -p "Please input number: " num
if [[ ! "$num" =~ ^[0-9]+$ || "$num" =~ ^0+$]];then
echo "error number"
exit
fi
read -p "Please input prefix: " prefix
if [ -z "$prefix" ];then
echo "error prefix"
fi
for i in `seq $num`
do
user=$prefix$i
useradd $user
echo "123" |passwd --stdin $user &>/dev/null
if [ $? -eq 0 ];then
echo "$user is created"
fi
done
# 只有[[]]中才能使用正则表达式,[]中不可以使用正则表达式
if 流程控制
#!/usr/bin/bash
#install apace
#v1.0 by dyl 2021/8/12
if ! ping -c1 www.baidu.com &>/dev/null;then
echo "connect: unreadchable"
exit
fi
yum -y install httpd
systemctl start httpd
systemctl enable httpd
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
setenforce 0
# 可以将上面改成
#!/usr/bin/bash
#install apace
#v1.0 by dyl 2021/8/12
ping -c1 www.baidu.com &>/dev/null
if [ $? -ne 0 ];then
echo "connect: unreadchable"
exit
fi
yum -y install httpd
systemctl start httpd
systemctl enable httpd
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
setenforce 0
# if可以判断任何一个返回真假的命令
#!/usr/bin/bash
#install apace
#v1.0 by dyl 2021/8/12
ping -c1 www.baidu.com &>/dev/null
if [ $? -ne 0 ];then
yum -y install httpd
systemctl start httpd
systemctl enable httpd
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
setenforce 0
curl http://127.0.0.1 &>/dev/null
if [ $? -eq 0 ];then
echo "apache ok"
fi
elif ping -c1 $gateway &>/dev/null;then
echo "check dns..."
else
echo "check ip address!"
fi
read -p "确认开始安装KVM[y]:" kvm_install
if [ ! "${kvm_install}"="y" ];then
echo -e "输入不正确"
exit
fi