前言
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
查看IP
查看ip常用的命令为ifconfig和ip address (ip addr)。
ifconfig源于net-tools安装包,类似还有route,netstat等。
ip address源于iproute安装包,包括ss,ip route等。
net-tools与iproute2
两者区别为:
net-tools是老款网络查询工具。
iproute是新版网络查询与管理工具。
iproute管理资源多,命令更简洁,性能更优,功能更全。
下面的操作都基于iproute的ip addr命令。
查看所有IP:
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:41:60:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.140/24 brd 192.168.100.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe41:60d3/64 scope link
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:fb:71:17 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
link/ether 52:54:00:fb:71:17 brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ca:c4:90:a4 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
查看所有IP简介:
ip -biref addr
lo UNKNOWN 127.0.0.1/8 ::1/128
ens33 UP 192.168.100.140/24 fe80::20c:29ff:fe41:60d3/64
virbr0 DOWN 192.168.122.1/24
virbr0-nic DOWN
docker0 DOWN 172.17.0.1/16
查看所有分配有地址的IP简介:
ip -brief addr show up
lo UNKNOWN 127.0.0.1/8 ::1/128
ens33 UP 192.168.100.140/24 fe80::20c:29ff:fe41:60d3/64
virbr0 DOWN 192.168.122.1/24
docker0 DOWN 172.17.0.1/16
查看所有IPv4简介,IPv6和空地址不显示。
ip -brief -4 addr
lo UNKNOWN 127.0.0.1/8
ens33 UP 192.168.100.140/24
virbr0 DOWN 192.168.122.1/24
docker0 DOWN 172.17.0.1/16
同上,过滤出State为UP的网卡:
ip -brief -4 addr | grep UP
ens33 UP 192.168.100.140/24
全部已激活连接的IP
使用tr和cut,提取出ip地址:
# tr 压缩多个空格为1个
ip -brief -4 addr | grep UP | tr -s ' '
ens33 UP 192.168.100.140/24
# cut 以空格分隔,取出第3个
ip -brief -4 addr | grep UP | tr -s ' ' | cut -d ' ' -f 3
192.168.100.140/24
# cut 以/分隔,取出第1个
ip -brief -4 addr | grep UP | tr -s ' ' | cut -d ' ' -f 3 | cut -d'/' -f1
192.168.100.140
使用awk,提取出ip地址:
ip -brief -4 addr | grep UP | awk -F [" "/]+ '{print $3}'
192.168.100.140
Tip1:上述结果在多个网卡都激活连接的情况下,可以是多个。
Tip2:hostname -I 列出配有地址的所有非回环IP,但无法判断是否在使用。
查看连接互联网的IP
获取连接互联网的网卡IP地址,首先列出本机路由表:
ip route
default via 192.168.100.1 dev ens33
169.254.0.0/16 dev ens33 scope link metric 1002
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.100.0/24 dev ens33 proto kernel scope link src 192.168.100.140
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
连接互联网时(阿里公共DNS)使用的网卡信息(网关,IP地址)。
ip route get 223.5.5.5
223.5.5.5 via 192.168.100.1 dev ens33 src 192.168.100.140
cache
同上,取出第一行的第七列。
ip route get 223.5.5.5 | awk 'NR==1{print $7}'
192.168.100.140
Tips:上述结果大部分情况下只有一个,因为即使有双网卡默认网关(通向互联网)也只有1个。除非做了策略路由,负载均衡等特殊处理。
创建用户
接着上述例子,列出ip后,智能识别ip包含的数字。如果包含某个数,则执行相关操作,如打印内容,创建用户等。
如果ip含有4,则打印当前系统时间。
#!/bin/bash
# 获取IP
myip=`ip route get 223.5.5.5 | awk 'NR==1{print $7}'`
echo $myip
num=4
# 判断前字符是否包含后字符
if [[ $myip =~ $num ]]
then
# 日期格式
date +'%F %T'
else
echo "IP不包含4"
fi
chmod +x ip-date.sh
./ip-date.sh
192.168.100.140
2023-02-02 21:07:29
Tips:
使用Ubuntu执行if判断时显示"[[ : not found"警告,但不影响往下执行。
把sh ip-date.sh改成bash ip-date.sh或者./ip-date.sh可修复。
批量创建用户
如果ip不含4,则批量创建用户user_00,user01到user100,密码随机。
#!/bin/bash
# 创建用户列表文件,清空内容
user_list=/root/user_list.txt
cat /dev/null > $user_list
# 创建组
groupadd ops
# $i依次等于0,1,2,3...100
for (( i=0; i<=100; i++ ))
do
if [[ $i -lt 10 ]]
then
# 为了统一格式, 前十用户补0
name=user_0$i
else
name=user_$i
fi
# 创建由大小写数字组成的8位随机密码
pass=`tr -cd 'a-zA-Z0-9' < /dev/urandom | head -c8`
# 将信息写入txt文档
echo "$name:$pass::ops::/home/$name:/bin/bash" >> $user_list
done
# 通过文档列表,批量创建用户
newusers $user_list
生成的用户列表后十位:
tail user_list.txt
user_91:cz5QlpA4::ops::/home/user_91:/bin/bash
user_92:tNFEEcml::ops::/home/user_92:/bin/bash
user_93:o71kSyQZ::ops::/home/user_93:/bin/bash
user_94:DkeE1XTE::ops::/home/user_94:/bin/bash
user_95:4iKIFmiO::ops::/home/user_95:/bin/bash
user_96:jodNcmtW::ops::/home/user_96:/bin/bash
user_97:v9PdWFwN::ops::/home/user_97:/bin/bash
user_98:mglJSf0C::ops::/home/user_98:/bin/bash
user_99:YvuG9H0c::ops::/home/user_99:/bin/bash
user_100:7fsqagjV::ops::/home/user_100:/bin/bash
用户列表必须符合以下格式:
Username:Password:User ID:Group ID:User Info:Home Directory:Default Shell
UID省略会自增创建,用户信息可省略。
检查最后十位用户:
tail /etc/passwd
user_91:x:1094:1002::/home/user_91:/bin/bash
user_92:x:1095:1002::/home/user_92:/bin/bash
user_93:x:1096:1002::/home/user_93:/bin/bash
user_94:x:1097:1002::/home/user_94:/bin/bash
user_95:x:1098:1002::/home/user_95:/bin/bash
user_96:x:1099:1002::/home/user_96:/bin/bash
user_97:x:1100:1002::/home/user_97:/bin/bash
user_98:x:1101:1002::/home/user_98:/bin/bash
user_99:x:1102:1002::/home/user_99:/bin/bash
user_100:x:1103:1002::/home/user_100:/bin/bash
打印出/etc/passwd这个文件中可以登陆的用户
不可以登录的shell为
/sbin/nologin
/usr/sbin/nologin
/bin/false
可以登录的shell为
/bin/bash
/bin/csh
/bin/sh
grep -v -E "nologin|false" /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
jack:x:1000:1000:Jack:/home/jack:/bin/bash
安装应用
安装应用的挑战在于Debian系和RedHat系使用不同的包管理。
我们可以通过读取os-release文件,对于不同linux体系使用不同的安装方法。
使用RPM包的发行版:rhel, rocky, centos, fedora
使用DEB包的发行版:debian, ubuntu, kali
#!/bin/bash
# 将版本信息赋值给shell
source /etc/os-release
install_rpm() {
# $*为列出全部参数
yum -y install $*
}
install_deb() {
apt update
apt -y install $*
}
if [ $ID = "rhel" -o $ID = "rocky" -o $ID = "centos" -o $ID = "fedora" ] ; then
echo OS is rhel series, use RPM.
install_rpm nginx
systemctl enable --now nginx
elif [ $ID = "debian" -o $ID = "ubuntu" -o $ID = "kali" ] ; then
echo OS is debian series, use DEB.
# 调用函数,传参nginx
install_deb nginx
else
echo "不支持的OS"
exit
fi
Tips: 定义函数时如install_rpm(),其中()里面不加任何形参。我保留了()这一部分,是为了让你知道你写的是函数。
一个脚本搞定
当一个脚本需要运行很多步骤时,不是简单地拼凑。而是有序的组合,比如说使用函数封装等。
下面我们使用一个脚本将以上全部内容添加进来。
一键安装
#!/bin/bash
echo "================== 第一步: 显示当前主机IP地址 =================="
show_ip() {
myip=`ip route get 223.5.5.5 | awk 'NR==1{print $7}'`
# 不做特殊声明,Shell中变量都是全局变量
echo $myip
}
show_ip
echo
echo "================== 第二步: 定义批量创建用户函数 =================="
create_users() {
# 创建用户列表文件,清空内容
user_list=/root/user_list.txt
cat /dev/null > $user_list
# 创建组
groupadd ops
# $i依次等于0,1,2,3...100
for (( i=0; i<=100; i++ ))
do
if [[ $i -lt 10 ]]
then
# 为了统一格式, 前十用户补0
name=user_0$i
else
name=user_$i
fi
# 创建由大小写数字组成的8位随机密码
pass=`tr -cd 'a-zA-Z0-9' < /dev/urandom | head -c8`
# 将信息写入txt文档
echo "$name:$pass::ops::/home/$name:/bin/bash" >> $user_list
done
# 通过文档列表,批量创建用户
newusers $user_list
echo "创建101个用户成功"
}
# 自定义判断依据
num=3
echo "判断条件为ip中是否含有数字$num"
echo
echo "================== 第三步: 选择创建用户或者打印时间 =================="
# 判断前字符是否包含后字符
if [[ $myip =~ $num ]]
then
echo "ip包含$num,则打印日期"
date +'%F %T'
else
echo "ip不包含$num,则创建用户"
create_users
fi
echo
echo "================== 第四步: 打印出可以登陆的用户 =================="
show_login_user() {
# 反选不可登陆的用户,不推荐
# grep -v -E "nologin|false" /etc/passwd
# 选择有shell环境的用户,推荐
grep -E "/bin/(sh|csh|bash)" /etc/passwd
}
show_login_user
echo
echo "================== 第五步: 智能判断系统并安装nginx =================="
# 将版本信息赋值给shell
source /etc/os-release
install_rpm() {
# $*为列出全部参数
yum -y install $*
}
install_deb() {
apt update
apt -y install $*
}
if [ $ID = "rhel" -o $ID = "rocky" -o $ID = "centos" -o $ID = "fedora" ] ; then
echo OS is rhel series, use RPM.
install_rpm nginx
systemctl enable --now nginx
elif [ $ID = "debian" -o $ID = "ubuntu" -o $ID = "kali" ] ; then
echo OS is debian series, use DEB.
# 调用函数,传参nginx
install_deb nginx
else
echo "不支持的OS"
exit
fi
Tips:
红帽系运行脚本建议 sh foo.sh
德班系运行脚本建议 bash bar.sh
或者统一加上执行权限后 ./foobar.sh
一键还原
附送一个解除安装的脚本,即回滚以上的操作,便于调式测试。
#!/bin/bash
# 卸载程序
yum -y remove nginx
apt -y remove nginx
# 批量删除用户
for (( i=0; i<=100; i++ ))
do
if [[ $i -lt 10 ]]
then
# 为了统一格式, 前十用户补0
name=user_0$i
else
name=user_$i
fi
userdel -r $name 2>/dev/null
done
# 删除组和文件
groupdel ops
rm -f /root/user_list.txt