目录
一、环境拓扑图
二、主机环境描述
主机名 | 主机地址 | 需要提供的服务 |
---|---|---|
content.exam.com | 172.25.250.101 | 提供基于 httpd/nginx 的 YUM仓库服务 |
ntp.exam.com | 172.25.250.102 | 提供基于Chronyd 的 NTP 服务 |
mysql.exam.com | 172.25.250.103 | 提供基于 MySQL 的数据库服务 |
nfs.example.com | 172.25.250.104 | 提供基于 NFS 的网络文件系统服务 |
dns.exam.com | 172.25.250.105 | 提供基于 bind 的 DNS 服务 |
bbs.exam.com | 172.25.250.106 | 提供基于 Discuz 的论坛服务 |
三、注意
- 172.25.250.101-172.25.250.105 共 5 个 IP 地址由servera.exam.com服务器进行提供。
- 172.25.250.106 由 serverb.exam.com 服务器进行提供。
四、需求描述
- 172.25.250.101 主机上的 Web 服务要求提供 www.exam.com Web站点,该站点在任何路由可达的主机上被访问,页面内容显示为 “Hello,Welcome to www.exam.com !”,并提content.exam.com/yum/AppStream和content.exam.com/yum/BaseOS URL 作为网络仓库供所有主机使用。
- 172.25.250.102 主机提供基于Chronyd 的 NTP 服务将本主机作为时间服务器,对外提供 NTP 服务,并设置本服务器为 3 层。
- 172.25.250.103 主机提供的MySQL 数据库服务,要求使用需求1中提供的仓库进行安装,并将数据库密码设定为 redhat。创建名称为 bbs 的数据库提供给论坛服务使用。
- 172.25.250.104 主机提供 NFS 服务,该服务将导出本地的 /bbs 目录作为论坛数据目录,该导出指定只能论坛所在主机使用,并且开机自动挂载。
- 172.25.250.105 主机提供 DNS 服务,该服务需要提供对项目中所有主机名的正向和反向解析,并要求所有服务器的 DNS 配置为该 DNS 服务器。
- 172.25.250.106 主机提供基于 Discuz 的论坛服务,该论坛服务使用 172.25.250.103 主机提供的数据库 bbs,使用 172.25.250.104 主机提供的 NFS 作为论坛数据目录,并开机挂载。并使用172.25.250.101 主机提供的网络仓库,172.25.250.102 主机提供的 NTP 服务,172.25.250.105 主
机提供的 DNS 服务。 - 所有服务器的防火墙服务和 SELinux 服务必须开启。
- 所有服务器提供的网络服务必须在系统重启后仍然可以正常提供服务.
- 根据所有服务的相关代码,编写一键部署shell脚本
五、shell代码的编写
#!/bin/bash
#########################
#File name:demo.sh
#Version:v1.0
#Created time:2024-07-19 10:08:38
#Description:
#########################
#安装httpd/Chronyd/MySQL/NFS/bind软件包
read -p "请确保你的Discuz文件在本机的/root目录里[y/n]:" result
if [ $result == "n" ];then
echo -e "\033[32m请准备好环境 \033[0m "
exit 0
fi
file_n=$(ls /root/Discuz* | wc -l)
if [ $file_n -eq 0 ];then
echo -e "\033[32m在本机的家目录没有Discuz文件\033[0m "
exit 0
fi
read -p "注意 : 两台主机必须做免密登录[y/n]:" resu
if [ "$resu" == "n" ];then
echo "请你先做免密登录"
exit 0
fi
read -p "请输入你另一台主机的ip地址:" other_ip
$(ping -c2 $other_ip &>/dev/null)
if [ $? -eq 0 ];then
echo "另一台主机已经准备好了"
else
echo "该主机不存在????"
exit 0
fi
check_local_yum(){
local n=$(df -h | grep "/dev/sr0" | wc -l)
if [ $n -eq 0 ];then
cat << EOF > /etc/yum.repos.d/local.repo
[localrepo]
name=localrepo1
baseurl = file:///mnt/AppStream/
enabled = 1
gpgcheck = 0
[localrepo1]
name=localrepo2
baseurl = file:///mnt/BaseOS/
enabled = 1
gpgcheck = 0
EOF
mount /dev/sr0 /mnt
fi
echo "-本地yum仓库没有问题-"
}
ip_yes()
{
ip_nums=$(hostname -I | awk '{for(i=1;i<=NF;i++) count++}END {print count}')
if [ $ip_nums -ge 5 ];then
echo "主机的ip地址充足,地址个数:$ip_nums"
else
echo "主机的ip地址不满足要求"
exit 0
fi
}
dns_localhost()
{
echo "nameserver $1" > /etc/resolv.conf
echo "本机的dns地址临时修改为$1"
}
install_softs()
{
httpd_status=$(rpm -qa httpd | wc -l)
if [ $httpd_status -eq 0 ];then
yum install httpd -y &>/dev/null
echo "正在安装httpd服务"
fi
chrony_status=$(rpm -qa chrony | wc -l)
if [ $chrony_status -eq 0 ];then
yum install chrony -y &>/dev/null
echo "正在安装chrony的服务"
fi
mysql_status=$(rpm -qa mariadb |wc -l)
if [ $mysql_status -eq 0 ];then
yum install mariadb mariadb-server -y &>/dev/null
echo "正在安装mysql的服务"
fi
nfs_status=$(rpm -qa nfs-utils | wc -l)
if [ $nfs_status -eq 0 ];then
yum install nfs_utils -y &>/dev/null
echo "正在安装nfs的服务"
fi
bind_status=$(rpm -qa bind |wc -l)
if [ $bind_status -eq 0 ];then
yum install bind -y &>/dev/null
echo "正在安装bind的服务"
fi
echo "httpd/Chronyd/MySQL/NFS/bind软件包***安装完成***"
}
httpd_config()
{
ls /web-server/test &>/dev/null
if [ $? -ne 0 ];then
mkdir /web-server/test -p
echo "Hello,Welcome to www.exam.com !" > /web-server/test/index.html
chcon -t httpd_sys_content_t /web-server/test/ -R
fi
ls /web-server/yum/yum &>/dev/null
if [ $? -ne 0 ];then
mkdir /web-server/yum/yum -p
chcon -t httpd_sys_content_t /web-server/yum/
fi
cat << EOF > /etc/httpd/conf.d/vhost.conf
<directory /web-server>
allowoverride none
require all granted
</directory>
<virtualhost 0.0.0.0:80>
documentroot /web-server/test
servername www.exam.com
</virtualhost>
<virtualhost 0.0.0.0:80>
documentroot /web-server/yum
servername content.exam.com
</virtualhost>
EOF
#配置网络yum仓库
cat << EOF > /root/local.repo
[localrepo]
name=localrepo1
baseurl = http://content.exam.com/yum/AppStream/
enabled = 1
gpgcheck = 0
[localrepo1]
name=localrepo2
baseurl = http://content.exam.com/yum/BaseOS/
enabled = 1
gpgcheck = 0
EOF
mount_host=$(df -h | grep -o "mnt")
if [ "$mount_host" == "mnt" ];then
umount /mnt
mount /dev/sr0 /web-server/yum/yum/
fi
systemctl restart httpd
echo "httpd的服务配置完成"
}
chrony_config(){
local num=$(grep "local stratum 3" /etc/chrony.conf | wc -l)
if [ $num -eq 0 ];then
echo "local stratum 3" >> /etc/chrony.conf
echo "allow $other_ip/32" >> /etc/chrony.conf
echo "server ntp.aliyun.com iburst" >>/etc/chrony.conf
sed -i '/pool 2.rhel.pool.ntp.org/d' /etc/chrony.conf
fi
systemctl restart chronyd
local ch_num=$(chronyc tracking -V | awk '/Stratum/{print $3}')
echo "chrony服务客服端配置完成,本服务器设置为$ch_num层"
}
mysql_config(){
systemctl restart mariadb.service
#数据库设置密码
mysql -u root -e "SELECT 1;" &>/dev/null
if [ $? -ne 0 ];then
echo "数据库密码已经设置好了"
else
mysql -u root << EOF
alter user 'root'@'localhost' identified by 'redhat';
flush privileges;
EOF
mysql -uroot -predhat -e "grant all privileges on *.* TO 'root'@'%' identified by 'redhat' with grant option;"
mysql -uroot -predhat -e "create database bbs;"
echo "数据库已经设置完成,密码:redhat,创建好bbs数据库"
fi
}
nfs_config()
{
ls /bbs &> /dev/null
if [ $? -ne 0 ];then
mkdir /bbs
fi
local num=$(grep '/bbs' /etc/exports |wc -l)
if [ $num -eq 0 ];then
echo "/bbs $other_ip(rw,sync,anonuid=0,anongid=0)" > /etc/exports
fi
systemctl restart nfs-server
echo "nfs配置完成,导出的目录为/bbs"
}
dns_config()
{
content_ip=$(hostname -I | awk '{print $1}')
ntp_ip=$(hostname -I | awk '{print $2}')
mysql_ip=$(hostname -I | awk '{print $3}')
nfs_ip=$(hostname -I | awk '{print $4}')
dns_ip=$(hostname -I | awk '{print $5}')
# dns_localhost $dns_ip
cat <<EOF > /etc/named.conf
options {
listen-on port 53 { $dns_ip; };
directory "/var/named";
};
zone "." IN {
type hint;
file "named.ca";
};
zone "exam.com" IN {
type master;
file "named.exam";
};
EOF
#编写区域配置文件
cat <<'EOF' > /var/named/named.exam
$TTL 1D
@ IN SOA @ admin.exam.com. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS ns1
EOF
cat <<EOF>> /var/named/named.exam
ns1 A $dns_ip
www A $dns_ip
content A $content_ip
ntp A $ntp_ip
mysql A $mysql_ip
nfs A $nfs_ip
dns A $dns_ip
bbs A $other_ip
EOF
systemctl restart named
echo "----dns服务配置完成---"
echo "YUM仓库服务地址:$content_ip"
echo "NTP服务地址:$ntp_ip"
echo "mysql服务地址:$mysql_ip"
echo "nfs服务地址:$nfs_ip"
echo "dns服务地址:$dns_ip"
}
firewall_config()
{
local fire=$(systemctl is-active firewalld.service)
if [ $fire=="inactive" ];then
systemctl start firewalld.service
fi
firewall-cmd --add-service=http --permanent &>/dev/null
firewall-cmd --add-service=dns --permanent &>/dev/null
firewall-cmd --add-service=nfs --permanent &>/dev/null
firewall-cmd --add-port=123/udp --permanent &>/dev/null
firewall-cmd --add-port=3306/tcp --permanent &>/dev/null
firewall-cmd --add-service=mountd --permanent &>/dev/null
firewall-cmd --add-service=rpc-bind --permanent &>/dev/null
firewall-cmd --reload
ssh $other_ip systemctl restart firewalld.service
setenforce 1
echo "---------正在改变客户端的selinux的配置,时间有点长,耐心等待--------------"
ssh $other_ip setenforce 1
ssh $other_ip setsebool -P httpd_use_nfs 1
ssh $other_ip setsebool -P httpd_unified 1
#ssh $other_ip ausearch -c 'php-fpm' --raw | audit2allow -M my-phpfpm
#ssh $other_ip semodule -i my-phpfpm.pp
ssh $other_ip setsebool -P httpd_can_network_connect_db 1
ssh $other_ip firewall-cmd --add-service=http --permanent &>/dev/null
ssh $other_ip firewall-cmd --add-port=9000/tcp --permanent &>/dev/null
ssh $other_ip firewall-cmd --reload
echo "客户端和服务端的防火墙、selinux都配置完成"
}
client_yum_config()
{
ssh $other_ip "echo \"nameserver $dns_ip\" > /etc/resolv.conf"
scp /root/local.repo $other_ip:/etc/yum.repos.d/rpm.repo
}
client_ntp_config()
{
chrony_status=$(ssh $other_ip rpm -qa chrony | wc -l)
if [ $chrony_status -eq 0 ];then
ssh $other_ip yum install chrony -y &>/dev/null
echo "正在安装chrony的服务"
fi
local ch_file=$(ssh $other_ip egrep '^server.*iburst' /etc/chrony.conf | wc -l)
if [ $ch_file -eq 0 ];then
ssh $other_ip "echo \"server ntp.exam.com iburst\" >> /etc/chrony.conf"
ssh $other_ip sed -i '/pool\ 2\.rhel\.pool\.ntp\.org\ iburst/d' /etc/chrony.conf
ssh $other_ip systemctl restart chronyd
fi
echo "@@@@@@@客户端的ntp服务配置完成@@@@@@@"
}
client_php_config(){
local php_num=$(ssh $other_ip rpm -qa php-fpm | wc -l)
if [ $php_num -eq 0 ];then
echo "正在安装php软件"
ssh $other_ip yum install php* -y &>/dev/null
fi
ssh $other_ip systemctl restart php-fpm.service
}
client_php_http(){
local httpd_num=$(ssh $other_ip rpm -qa httpd|wc -l)
if [ $httpd_num -eq 0 ];then
ssh $other_ip yum install httpd -y
fi
ssh $other_ip systemctl restart httpd
echo "客服端的httpd的服务配置完成"
}
Discuz_config(){
scp Discuz* $other_ip:/var/www/html/
local file_n=$(ssh $other_ip ls /var/www/html | wc -l)
if [ $file_n -le 3 ];then
ssh $other_ip yum install unzip -y &>/dev/null
ssh $other_ip unzip /var/www/html/Discuz* -d /var/www/html &>/dev/null
fi
echo "Discuz论坛解压完成"
ssh $other_ip ls -d /var/www/html/upload/data.bak &>/dev/null
if [ $? -ne 0 ];then
ssh $other_ip mv /var/www/html/upload/data /var/www/html/upload/data.bak
ssh $other_ip mkdir /var/www/html/upload/data
ssh $other_ip mount $nfs_ip:/bbs /var/www/html/upload/data
ssh $other_ip cp -p -r /var/www/html/upload/data.bak/* /var/www/html/upload/data/
fi
ssh $other_ip chmod o+w /var/www/html/upload/config -R
ssh $other_ip chmod o+w /var/www/html/upload/data -R
ssh $other_ip chmod o+w /var/www/html/upload/uc_* -R
echo "discuz论坛搭建完成"
echo "客户端的dns指向服务端成功"
}
server_config()
{
ip_yes
check_local_yum
install_softs
httpd_config
chrony_config
mysql_config
nfs_config
dns_config
firewall_config
}
client_config(){
client_yum_config
client_php_config
client_ntp_config
client_php_http
Discuz_config
}
server_config
client_config
echo -e "\033[33m 论坛已经完成安装,请在浏览器 http://$other_ip/upload/install/ 访问\033[0m"
六、总结
在编写这个shell脚本前,我的一个编写代码思路是,以模块化的思想编写,比如安装软件在一个模块,http配置在一个模块,dns配置在一个模块,先编写服务端,在编写客户端,然后分模块去测试,为了让这个shell脚本可以多次运行,有些相应的判断就必须要做,比如某个配置文件追加修改了,第二次运行就不能追加修改了。为了让脚本可以在不同的主机上去运行,shell脚本中的主机地址就不能写死,要用变量来获取ip地址。
在编写脚本中,如果出现问题,很难发现错误,最好的方法就是去看日志,像selinux一开启,就会出现很多问题,可以去:tail -f /var/log/messages查看,里面都会给你一些命令解决。像httpd,mariadb,php都有自己单独的日志文件,出错了都可以去上面找答案。