shell


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
image-20210722222615506 image-20210722222640666
# 管道
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 表示追加

image-20210722223113824

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的变量

image-20210801220414869

image-20210801220638956

image-20210801220813531

image-20210801221013857

image-20210801221254822

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 ""

image-20210801222521675

image-20210801222629396

image-20210801222759494

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

image-20210801231206346

#!/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

image-20210801232530372

变量类型

#!/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 显示目录

image-20210802223940020

变量的赋值方式

# 显示赋值
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 变量名

# $()和``都是命令替换,相互等价

image-20210802230433771

image-20210802230547030

# 变量强引用和弱引用,强引用'',弱引用""
强引用中的变量不会解析

image-20210802230754850

image-20210802231016849

image-20210802231115673

image-20210802231353589

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

image-20210804222629184

# 展示当前内存使用百分比
#!/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 # 以调试的方式运行脚本

image-20210804223829479

#!/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 进入交互计算器模式

image-20210804224815089

变量内容的删除和替换

$ url=www.baidu.com
$ echo ${#url}	# 输出url有多少字符
$ echo ${url#*.}	
$ echo ${url#www}	# 从前往后,最短匹配

$ echo ${url##*.} # 从前往后,最长匹配,贪婪匹配

image-20210805222437452

$ echo ${url%.*}	#从后往前,最短匹配
$ echo ${url%%.*}	#从后往前,最长匹配

image-20210805222753716

# 索引以及切片
$ echo ${url:0:5}	# 0是索引开始数五个
$ echo ${url:5:5}	# 5是索引开始数五个
$ echo ${url:5}

image-20210805223537657

# 内容替换
$ url=www.baidu.com
$ echo ${url/baidu/studylove}
$ echo ${url/w/W}
$ echo ${url//w/W}	# 贪婪匹配

image-20210805224054202

# 变量选择赋值
# 如果变量没有定义则将则进行赋值,否则不赋值
$ unset var1
$ echo ${var1}
$ echo ${var-studylove}	

image-20210805224625345

# 变量没有被赋值(包括空值):使用新值赋值
# 变量有被赋值:不会被替换

$ unset var1
$ echo ${var1:-abc}
$ echo ${var1-abc}
$ var1=
$ echo ${var1:-abc}
$ echo ${var1-abc}

# :-和-区别在于,:-当变量已经存在但是值为空值也会进行赋值
# :-是变量未赋值或者未定义则进行赋值
# -是变量未定义才会赋值

image-20210805225145260

条件测试

# 条件测试三种方法
# 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

image-20210807215159426

# 字符串比较
# 提示:字符串比较必须加上双引号
[ "$USER"="root" ];echo $?
[ "$USER"=="root" ];echo $?
# =和==效果差不多的
[ -z "$abc" ]	# 如果abc字符串是零则返回0否则返回1
[ -n "$abc" ]	# 与上面的正好相反


![image-20210810220002780](C:/Users/%E5%9C%B0%E8%A1%A8%E6%9C%80%E8%8F%9C/AppData/Roaming/Typora/typora-user-images/image-20210810220002780.png)

​```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 ]]
# 只有[[]]中才能使用&&和||

image-20210810220810511

# 创建用户
#!/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

文章作者: dyl
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 dyl !
 上一篇
一致性算法原理 一致性算法原理
本文详细描述了一致性算法的实现与优缺点,该文章简单易懂,适合零基础的小白查阅,本文来自博主看B站教学视频总结,截图来自于B站视频
2023-12-10 dyl
下一篇 
Linux静态库和动态库 Linux静态库和动态库
该文总结了在Linux系统下如何进行静态库与动态库的生成与使用,简言总结了静态库与动态库的优缺点,该文来自博主看B站视频总结
2023-12-10 dyl
  目录