前言:
通过一个多月的shell学习,总共写出30个案例,此次为最后一次发布,希望对大家的学习有所帮助。
案例二十六、自动校准时间
1.问题:
在系统中编写一个 shell 脚本,能够自动连接网络时间服务器并校准系统时间,确保系统时间的准确性,以避免因时间误差导致的各种问题,如日志记录时间错乱、证书验证失败等。
2.分析:
要实现自动校准时间,首先需要确定合适的网络时间协议(NTP)服务器。常见的公共 NTP 服务器如 pool.ntp.org 可以使用。
在 Linux 系统中,可以使用 ntpdate 命令(如果已安装)或者 chrony 服务来与 NTP 服务器进行时间同步。ntpdate 是一个简单的时间同步工具,直接从指定的 NTP 服务器获取时间并设置系统时间;chrony 则是一个更为强大和灵活的时间同步服务,它不仅可以同步时间,还能在网络连接不稳定时进行时间补偿和调整。
考虑到不同系统可能安装的时间同步工具不同,脚本需要先检查系统是否安装了 ntpdate 或 chrony,如果没有则尝试安装。
3.流程图:
4.实现:
bash
#!/bin/bash
# 检查是否安装 ntpdate
if command -v ntpdate &>/dev/null; then
# 使用 ntpdate 校准时间
ntpdate pool.ntp.org > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "使用 ntpdate 校准时间成功"
else
echo "使用 ntpdate 校准时间失败"
fi
else
# 检查是否安装 chrony
if command -v chronyc &>/dev/null; then
# 使用 chrony 校准时间
chronyc -a makestep > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "使用 chrony 校准时间成功"
else
echo "使用 chrony 校准时间失败"
fi
else
# 安装 chrony
yum install -y chrony > /dev/null 2>&1
if [ $? -eq 0 ]; then
# 再次尝试使用 chrony 校准时间
chronyc -a makestep > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "安装 chrony 并校准时间成功"
else
echo "安装 chrony 后校准时间失败"
fi
else
echo "安装 chrony 失败"
fi
fi
fi
5.实现解析:
if command -v ntpdate &>/dev/null; then... else... fi:使用 command -v 命令检查 ntpdate 是否存在于系统的可执行路径中。如果存在,则执行后续的 ntpdate 校准时间操作;如果不存在,则进入下一个检查步骤。
ntpdate pool.ntp.org > /dev/null 2>&1:使用 ntpdate 命令连接到 pool.ntp.org 服务器进行时间校准,并将标准输出和标准错误输出重定向到 /dev/null,避免命令执行过程中的输出信息干扰脚本执行。if [ $? -eq 0 ]; then... else... fi:检查 ntpdate 命令的返回值,如果返回值为 0,表示校准成功,输出相应信息;否则输出失败信息。
如果 chrony 也不存在,则使用 yum install -y chrony > /dev/null 2>&1 安装 chrony 服务。安装完成后再次尝试使用 chronyc -a makestep 进行时间校准,并根据最终的结果输出相应的信息。
6.结果验证:
直接执行脚本
案例二十七、检测当前系统版本
1.问题:
在 Linux 系统中,编写一个 shell 脚本以获取并输出当前系统的版本信息,包括发行版名称、版本号等,以便于系统管理员或开发人员快速了解系统的基础信息,用于系统维护、软件兼容性检查等操作。
2.分析:
在 Linux 系统中,不同的发行版存储系统版本信息的文件或命令有所不同。例如,在 CentOS、Red Hat 等基于 Red Hat 系的系统中,可以通过查看 /etc/redhat-release 文件获取详细的发行版和版本信息;在 Ubuntu、Debian 等基于 Debian 系的系统中,可以使用 lsb_release -a 命令获取相关信息。
脚本需要先判断系统属于哪种类型,然后根据相应的方式获取并输出系统版本信息。
3.流程图:
4.实现:
bash
#!/bin/bash
# 检查是否为 Red Hat 系系统
if [ -f /etc/redhat-release ]; then
# 从 /etc/redhat-release 获取版本信息并输出
cat /etc/redhat-release
elif command -v lsb_release &>/dev/null; then
# 使用 lsb_release -a 获取版本信息并输出
lsb_release -a
else
echo "未知系统类型,无法获取版本信息"
fi
5.实现解析:
if [ -f /etc/redhat-release ]; then...:通过检查 /etc/redhat-release 文件是否存在来判断系统是否为 Red Hat 系系统。如果该文件存在,则执行下面的操作。
cat /etc/redhat-release:直接输出 /etc/redhat-release 文件的内容,该文件包含了 Red Hat 系系统的发行版名称和版本号等详细信息。
elif command -v lsb_release &>/dev/null; then...:如果系统不是 Red Hat 系,进一步检查 lsb_release 命令是否存在。如果存在,则使用 lsb_release -a 命令获取并输出系统版本信息。lsb_release -a 命令会输出包括发行版 ID、描述、版本号等多方面的系统版本信息。
else...:如果既不是 Red Hat 系系统,也没有 lsb_release 命令,说明系统类型未知,输出相应提示信息。
6.结果验证:
直接执行脚本
案例二十八、统计指定目录下文件数量
1.问题:
编写一个 shell 脚本,用于统计指定目录下的文件数量,以便用户快速了解该目录中的文件规模,可用于文件管理、磁盘空间分析等场景。
2.分析:
需要获取用户输入的目标目录路径。
使用合适的命令(如 ls 结合管道和 wc -l)来统计目录下的文件数量。
要考虑对用户输入的目录路径进行有效性验证,防止因路径错误导致脚本出错。
3.流程图:
4.实现:
bash
#!/bin/bash
# 获取用户输入的目录路径
echo "请输入要统计文件数量的目录路径:"
read target_dir
# 验证目录路径是否有效
if [ -d "$target_dir" ]; then
# 统计目录下文件数量
file_count=$(ls -A "$target_dir" | wc -l)
echo "目录 $target_dir 下的文件数量为:$file_count"
else
echo "输入的目录路径无效,请检查后重新输入。"
fi
5.实现解析:
echo "请输入要统计文件数量的目录路径:" 和 read target_dir:提示用户输入要统计文件数量的目录路径,并将用户输入的值存储到变量 target_dir 中。
if [ -d "$target_dir" ]; then... else... fi:使用 -d 选项判断变量 target_dir 所表示的路径是否为一个有效的目录。如果是,则执行后续的统计操作;如果不是,则输出错误提示信息。
file_count=(ls -A "target_dir" | wc -l):在目录路径有效的情况下,使用 ls -A 命令列出目录下的所有文件(包括隐藏文件,但不包括 . 和 ..),然后通过管道将结果传递给 wc -l 命令,wc -l 命令会统计输入的行数,也就是文件的数量,并将结果赋值给变量 file_count。
最后根据情况输出文件数量结果或错误提示信息。
6.结果验证:
直接执行脚本,检测/etc目录下的文件
再次执行脚本,检测一个不存在的目录
案例二十九、获取今日的天气预报
1.问题:
编写一个 shell 脚本,能够获取并显示指定城市当天的天气预报信息,包括天气状况、最高温度、最低温度、风向风力等。
2.分析:
需要选择一个可靠的天气预报 API 来获取数据,如易客云天气 API、天气.sojson.com等,这些 API 通常会以 JSON 或 XML 格式返回数据134.
使用curl命令向 API 发送请求并获取响应数据234.
借助jq等工具对获取到的 JSON 数据进行解析,提取出所需的天气信息245.
将提取到的信息进行格式化输出,展示给用户。
3.流程图:
4.实现:
bash
#!/bin/bash
# 设置城市名称和API地址
city="沈阳"
api_url="http://t.weather.sojson.com/api/weather/city/101070101"
# 使用curl发送请求获取天气数据
response=$(curl -s $api_url)
# 检查请求是否成功
if [ $? -eq 0 ]; then
# 使用jq解析天气数据
weather=$(echo $response | jq -r '.data.forecast[0].type')
high=$(echo $response | jq -r '.data.forecast[0].high')
low=$(echo $response | jq -r '.data.forecast[0].low')
wind_direction=$(echo $response | jq -r '.data.forecast[0].fx')
wind_power=$(echo $response | jq -r '.data.forecast[0].fl')
# 格式化并输出今天的天气预报信息
echo "今天沈阳的天气预报如下:"
echo "天气状况:$weather"
echo "最高温度:$high℃"
echo "最低温度:$low℃"
echo "风向:$wind_direction"
echo "风力:$wind_power"
else
echo "获取天气预报失败,请检查网络连接或API地址是否正确。"
fi
5.实现解析:
首先定义了要查询的城市名称city和对应的天气 API 地址api_url。这里的城市编码101070101是沈阳的编码,不同城市有不同的编码,可以通过查询相关文档或在该 API 的网站上查找4.
使用curl -s命令向 API 发送请求,并将响应结果存储在response变量中。-s参数表示 silent,即静默模式,不显示请求的进度信息245.
通过检查?的值来判断curl请求是否成功。如果?等于 0,表示请求成功,继续使用jq工具对response中的 JSON 数据进行解析。通过指定不同的键,如.data.forecast[0].type、.data.forecast[0].high等,提取出天气状况、最高温度、最低温度、风向、风力等信息,并分别存储在相应的变量中4.
最后,将提取到的天气信息进行格式化输出,展示给用户。如果curl请求失败,则输出错误信息提示用户检查网络连接或 API 地址。
6.结果验证:
直接执行脚本
案例三十、shell一键部署joomla
1.问题:
在 LAMP(Linux、Apache、MySQL、PHP)环境下部署 Joomla 是一个复杂的过程,涉及到多个软件的安装、配置和启动,以及文件的下载、解压和权限设置等操作。手动完成这些步骤容易出错且耗时,因此需要一个脚本来实现一键自动化部署,同时还要考虑防火墙对部署过程的影响,以及后续可能需要的备份和日志检查功能。
2.分析:
环境准备与检查:
防火墙处理:检查防火墙(firewalld)状态,如果处于活动状态则关闭它,以避免在后续安装和配置过程中出现网络访问问题。
软件安装检查:分别检查 Apache、PHP 和 MySQL(这里使用 MariaDB)是否已经安装,若未安装则进行安装。对于已安装的软件,仅输出相应提示信息。
软件安装与配置:
Apache 安装与启动:若未安装 Apache(httpd),使用yum进行安装。安装完成后启动 Apache,并检查启动是否成功。
PHP 安装:检查 PHP 是否已安装,如果没有安装则使用yum安装包括php、php - mysql、php - gd、php - mbstring、php - xml等必要的 PHP 模块。
MySQL(MariaDB)安装与配置:使用yum安装 MariaDB 服务器和客户端。安装完成后启动 MariaDB,并设置为开机自启。然后修改 root 用户的数据库密码,并创建名为joomla的数据库,为 root 用户授予对该数据库的所有权限,最后刷新权限。
joomla部署:
下载与解压:从指定网址下载 Joomla 安装包到/tmp目录,然后检查目标解压目录/var/www/html/joomla是否存在,若不存在则创建,之后将下载的 Joomla 安装包解压到该目录。
权限设置:将/var/www/html/joomla目录及其内容的所有权授予apache用户和组,并设置合适的权限(755)。
其他功能(注释部分):
站点备份:创建以当前日期时间命名的备份目录,将/var/www/html/joomla目录下的所有内容复制到备份目录中,实现 Joomla 站点的备份。
数据库备份:创建以当前日期时间命名的数据库备份目录,使用mysqldump将joomla数据库备份为 SQL 文件到该目录中。
日志检查:检查 Apache 的访问日志文件/var/log/httpd/access_log,统计访问次数,并查找其中的错误状态码(4xx和5xx)。
3.流程图:
整体流程图:
防火墙的流程图:
Apache启动流程图:
Php的安装流程图:
Mariadb 的下载流程图:
Mariadb的配置流程图:
Joomla下载流程图:
4.实现:
bash
# /bin/bash
#Date:2024.10.30
#Author:created by yc
#Mail:2207696178@qq.com
#Function:该脚本可以在LAMP环境下一键部署Joomla
#Version:Joomla-3.10
function echo_info() {
echo -e "[\033[36m$(date +%T)\033[0m] [\033[32mINFO\033[0m] \033[37m$@\033[0m"
}
function echo_warning() {
echo -e "[\033[36m$(date +%T)\033[0m] [\033[1;33mWARNING\033[0m] \033[1;37m$@\033[0m"
}
function echo_error() {
echo -e "[\033[36m$(date +%T)\033[0m] [\033[41mERROR\033[0m] \033[1;31m$@\033[0m"
}
check_and_close_firewall() {
firewall_status=$(systemctl is-active firewalld)
if [ "$firewall_status" == "active" ]; then
echo_info 防火墙正在运行,正在关闭...
systemctl stop firewalld
echo_info 防火墙已关闭。
else
echo_warning 防火墙已关闭。
fi
}
install_apache() {
restart=$(rpm -qa|grep httpd)
if [ -z "${restart}" ]
then
echo_info 安装Apache
yum install httpd -y
else
echo_warning 已经安装有Apache
fi
echo_info 正在启动Apache中...
systemctl start httpd
if [ $? -eq 0 ]; then
echo_info Apache已经启动
else
echo_error Apache启动失败
fi
}
install_php() {
some=$(rpm -qa|grep php)
if [ -z "${some}" ]
then
echo_info 正在下载php中...
yum install php php-mysql php-gd php-mbstring php-xml -y
echo_info 下载完成
else
echo_warning 已有php
fi
}
Downmysql(){
echo_info 下载mariadb中...
yum install mariadb-server mariadb -y
echo_info 下载完成
systemctl start mariadb
if [ $? -eq 0 ];
then
echo_info mariadb 启动成功
else
echo_error mariadb 启动失败
fi
echo_info mariadb 自启动中...
systemctl enable mariadb
echo_info mariadb 自启动成功
}
Mainmysql(){
echo_info 更改数据库密码中...
mysqladmin -u root password 123456
if [ $? -eq 0 ];
then
echo_info 数据库密码修改成功,新密码为123456
else
echo_error 数据库密码修改失败
fi
mysql -uroot -p123456 <<EOF
create database joomla;
grant all privileges on joomla.* to 'root'@'localhost' identified by '123456';
flush privileges;
EOF
if [ $? -eq 0 ]; then
echo_info "创建 joomla 表成功"
echo_info "授予权限成功"
echo_info "表刷新成功"
else
echo_error "数据库操作失败"
fi
}
Downjoomla(){
echo_info 下载joomla中...
cd /tmp && wget https://downloads.joomla.org/cms/joomla3/3-10-10/joomla_3-10-10-stable-full_package.zip
echo_info joomla下载完成
DIR="/var/www/html/joomla"
if [ ! -d "${DIR}" ];
then
echo_info 创建目录
mkdir "${DIR}"
else
echo_warning 该目录已存在,无需创建
fi
echo_info 正在解压中...
if ! unzip joomla_3-10-10-stable-full_package.zip -d "${DIR}";
then
echo_error 解压失败
else
echo_info 解压成功
fi
if ! chown -R apache:apache "${DIR}"; then
echo_error "授权失败"
else
echo_info "授权成功"
fi
if ! chmod -R 755 "${DIR}"; then
echo_error "权限设置失败"
else
echo_info "权限设置成功"
fi
}
restart_httpd() {
echo_info httpd重启中...
systemctl restart httpd
if [ $? -eq 0 ];
then
echo_info httpd重启成功
else
echo_error httpd重启失败
fi
}
#备份joomla站点
#backup_joomla() {
# echo_info "开始备份 Joomla 站点"
# backup_dir="/backup/joomla_$(date +%Y%m%d%H%M%S)"
# mkdir -p "$backup_dir"
# cp -r /var/www/html/joomla "$backup_dir"
# if [ $? -eq 0 ]; then
# echo_info "Joomla 站点备份成功,备份目录为 $backup_dir"
# else
# echo_error "Joomla 站点备份失败"
# fi
#}
#备份数据库
# backup_database() {
# echo_info "开始备份数据库"
# backup_db_dir="/backup/database_$(date +%Y%m%d%H%M%S)"
# mkdir -p "$backup_db_dir"
# mysqldump -u root -p123456 joomla > "$backup_db_dir/joomla.sql"
# if [ $? -eq 0 ]; then
# echo_info "数据库备份成功,备份文件为 $backup_db_dir/joomla.sql"
# else echo_error
# "数据库备份失败"
# fi
#}
# 检查日志文件函数,包括统计访问次数和检查错误状态码
#check_log_file() {
# log_file="/var/log/httpd/access_log"
# if [ -f "$log_file" ]; then
# echo_info "检查日志文件 $log_file"
# # 统计访问次数
# access_count=$(wc -l < "$log_file")
# echo_info "日志文件中的访问次数为 $access_count"
# # 检查错误状态码
# error_status_codes=$(grep -E ' 4[0-9][0-9] | 5[0-9][0-9] ' "$log_file" | cut -d' ' -f9)
# if [ -n "$error_status_codes" ]; then
# echo_info "以下是错误状态码:$error_status_codes"
# else
# echo_info "未发现错误状态码"
# fi
# else
# echo_error "日志文件 $log_file 不存在"
# fi
#}
check_and_close_firewall
install_apache
install_php
Downmysql
Mainmysql
Downjoomla
restart_httpd
#backup_joomla
#backup_database
#check_log_file
ip_addr=$(hostname -I | awk '{print $1}')
if [ -n "$ip_addr" ]; then
echo "网页地址为:http://$ip_addr/joomla"
else
echo "无法获取 IP 地址。"
fi
5.实现解析:
定义了echo_info、echo_warning和echo_error三个函数,用于输出不同类型(信息、警告、错误)的消息。
使用systemctl is - active firewalld获取防火墙(firewalld)的状态,并将结果存储在firewall_status变量中。
通过if [ "$firewall_status" == "active" ];判断防火墙是否处于活动状态。如果是,则使用systemctl stop firewalld关闭防火墙,并输出相应的信息;如果防火墙已经关闭,则输出警告信息。
使用rpm -qa|grep httpd检查系统中是否已经安装了 Apache(httpd)。如果没有安装(-z "${restart}"判断结果为真),则使用yum install httpd -y安装 Apache,并输出安装信息。如果已经安装,则输出警告信息。
安装完成后,使用systemctl start httpd启动 Apache,并通过检查上一个命令的返回值(?)来判断启动是否成功。如果? -eq 0,则输出启动成功信息;否则输出启动失败信息。
使用rpm -qa|grep php检查 PHP 是否已安装。如果未安装,则使用yum install php php - mysql php - gd php - mbstring php - xml -y安装 PHP 及相关模块,并输出下载完成信息。如果已经安装,则输出警告信息。
使用yum install mariadb - server mariadb -y安装 MariaDB 服务器和客户端,并输出下载完成信息。
使用systemctl start mariadb启动 MariaDB,并根据启动命令的返回值判断启动是否成功,输出相应信息。如果启动成功,使用systemctl enable mariadb将 MariaDB 设置为开机自启,并输出自启动成功信息。
使用mysqladmin -u root password 123456修改 root 用户的数据库密码,并根据命令返回值判断修改是否成功,输出相应信息。
使用mysql -uroot -p123456 <<EOF... EOF的方式在数据库中执行一系列 SQL 命令,包括创建joomla数据库、授予 root 用户对该数据库的所有权限以及刷新权限。根据这些操作的返回值判断是否成功,并输出相应信息。
使用cd /tmp && wget https://downloads.joomla.org/cms/joomla3/3 - 10 - 10/joomla_3 - 10 - 10 - stable - full_package.zip下载 Joomla 安装包到/tmp目录,并输出下载完成信息。
检查/var/www/html/joomla目录是否存在,如果不存在则使用mkdir "${DIR}"创建。然后使用unzip命令将下载的 Joomla 安装包解压到该目录,并根据解压命令的返回值输出解压成功或失败信息。
使用chown -R apache:apache "{DIR}"和chmod -R 755 "{DIR}"分别设置/var/www/html/joomla目录及其内容的所有权和权限,并根据命令返回值输出授权和权限设置成功或失败信息。
使用systemctl restart httpd重启 Apache,并根据重启命令的返回值判断重启是否成功,输出相应信息。
6.结果验证:
创建一个文本文件为joomla.sh,直接运行脚本sh joomla.sh即可
当脚本运行结束之后,打开浏览器,输入http://你的ip地址/joomla,当出现以下界面表示joomla部署成功