shell编程3-循环控制

脚本实战

nginx管理脚本

源码安装 NGINX

  预先安装编译安装依赖的库

yum -y install gcc gcc-c++ autoconf automake make      
yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel
 
或者
LANG=C yum -y groupinstall "Development tools"

 

  去官网找包(稳定版)下载

[root@localhost ~]# wget https://nginx.org/download/nginx-1.28.0.tar.gz

1、解压缩

[root@localhost ~]# tar xf nginx-1.28.0.tar.gz

2、进到解压目录进行编译安装

[root@localhost ~]# cd nginx-1.28.0
#定制安装信息,指定安装目录 ./configure --prefix=/usr/local/nginx_1.28.0
#或者 ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-stream --with-http_gzip_static_module --with-http_sub_module

#1、--prefix 指定安装的目录,/usr/local/nginx 是安装目录
#2、带ssl stub_status模块 添加stream模块 –with-stream,这样就能传输tcp协议了
#3、http_stub_status_module 状态监控
#4、http_ssl_module 配置https
#5、stream 配置tcp得转发
#6、http_gzip_static_module 压缩
#7、http_sub_module 替换请求

 

3、编译

make -j 2  #并发2个任务去编译

4、安装

make install

 

 
# 将程序设定一个软连接,便于后续的升级

[root@localhost nginx]# ln -s /usr/local/nginx-1.28.0 /usr/local/nginx

注意:现在百分之90,能用上的软件,都提供了rpm包. --->使用户可以使用yum直接安装使用.

 

补充:连接多个命令组成一条大命令

分号:左边命令运行完毕,无论成功与否,都会执行左边的命令。

make j 2;make install

&&:左边命令运行成功之后才能执行右边的命令

make j 2 && make install

 

常用命令:

yum install net-tools -y
netstat -an |grep 80
/usr/local/nginx/sbin/nginx
ps aux |grep nginx
pkill -9 nginx
/usr/local/nginx/sbin/nginx -s stop
ll /usr/local/nginx/conf/
/usr/local/nginx/sbin/nginx -s reload
[root@localhost scripts]# netstat -an |grep ":80\b"

 

nginx_manager.sh脚本要实现哪些功能:start|stop|reload|restart|status

#!/bin/bash -

#如果给脚本指定的命令行参数的数目小于1 ,则显示脚本的使用方法信
if [ $# -ne 1 ]; then
    echo "Usage: $0 start|stop|reload|restart|status"
    exit 1
fi

args=$1

function f1() {
    if [ $? -eq 0 ];then
        echo "nginx $args 成功"
    else
         echo "nginx $args 失败"
    fi
}




#if [ "$1" = "start"  ]; then
#   pass
#elif [ "$1" = "stop" ]; then
#    pass
#elif [ "$1" = "restart" ]; then
#    pass
#elif [ "$1" = "staus" ]; then
#    pass
#
#fi

case $1 in
    start)
        #判断如果已经是启动状态,只打印提示信息,nginx已经启动了,否则运行启动命令,并判断启动命令是否>运行成功。
        netstat -an |grep ":80\b" &>/dev/null
        if [ $? -eq 0 ];then
            echo "nginx原本已经启动了"
        else
            /usr/local/nginx/sbin/nginx &>/dev/null
            #if [ $? -eq 0 ];then
            #    echo "nginx 启动成功"
            #else
            #    echo "nginx 启动失败"
            #fi
            f1

        fi
        ;;
    stop)
        #判断如果已经是关系状态,只打印提示信息,nginx已经关闭了,否则运行关闭命令,并判断关闭命令是否>运行成功。
        /usr/local/nginx/sbin/nginx -s stop &>/dev/null
            #if [ $? -eq 0 ];then
            #    echo "nginx 关闭成功"
            #else
            #    echo "nginx 关闭失败"
            #fi
         f1

        ;;
    reload)
        /usr/local/nginx/sbin/nginx &>/dev/null
        f1
        ;;
    restart)
        #先关闭 再启动 并判断是否重启成功 先判断如果是已经启动就直接关闭再启动
        netstat -an |grep ":80\b" &>/dev/null
        if [ $? -eq 0 ];then
            /usr/local/nginx/sbin/nginx -s stop &>/dev/null

        fi
        sleep 3
        #再启动
        /usr/local/nginx/sbin/nginx &>/dev/null
        #判断是否重启成功
        f1
        ;;
    status)
        /usr/local/nginx/sbin/nginx &>/dev/null
        ;;
    *)
        echo "Usage: $0 start|stop|reload|restart|status"
        ;;

esac
脚本

 

 

 

 

两种条件循环

  循环就是重复做一件事情

while循环和until循环

  while循环语法:

while 条件为真
do
    代码块
done

  until循环语法:

until 条件为假
do
    代码块
done

区别是while的条件为真的时候,才会运行一次代码块,运行完一次之后会回过头来再判断一次条件是否为真,如果为真再执行一次代码块,再回头进行判断条件是否为真,直到条件为假也就停了。

而until是条件为假的时候它才执行代码块。

while循环脚本:

#!/bin/bash -

i=0
#while true

while [ $i -lt 6 ]
do
    echo $i
    let i++
done
#!/bin/bash -
i=0
until [ $i -eq 5 ]
do
    echo $i
    let i++
done
#!/bin/bash -

i=0
#while true

#while (( i < 6 ))
#do
#    echo $i
#    let i++
#done



until (( i > 5  ))
do
    echo $i
    let i++
done
c语言风格的条件写法

 

break和continue

  循环体内会用到的两个关键字

  break:终止本层循环,意味着本层循环整体结束。

  continue:继续的意思,终止本次循环,直接进入下一次。

continue与continue同一级别的代码永远运行不到。

循环体的最后一步代码也不能是continue。

#!/bin/bash -

i=1

while [ $i -lt 6 ]
do
    if [ $i -eq 3 ]; then
        let i++
        continue
    fi
    echo $i
    let i++
done
continue
#!/bin/bash -

i=1

while [ $i -lt 6 ]
do
    if [ $i -eq 3 ]; then
        let i++
        break
    fi
    echo $i
    let i++
done
break

写一个跳板机程序:具体要求:

1、执行脚本就输出主机信息

  1、backup 1.1.1.11

  2、web01 1.1.1.12

  3、db01 192.168.1.32

  4、web02 1.1.1.34

2、用户输入编号则自动ssh连接到目标主机

#!/bin/bash -

#执行脚本就输出主机信息
#cat << EOF
#1、backup 1.1.1.11
#2、web01 1.1.1.12
#3、db01 192.168.1.32
#4、web02 1.1.1.34
#EOF

#声明一个整型变量
declare -i num
#显示提示输入一个数值的信息,然后将用户的输入促驽变量count中
read -p "Enter an num: " num

while true
do
cat << EOF
1、backup 1.1.1.11
2、web01 1.1.1.12
3、db01 192.168.1.32
4、web02 1.1.1.34
EOF

        case $num in
        1)
            echo "backup 1.1.1.11"
            ;;
        2)
            echo "web01 1.1.1.12"
            ;;
        3)
            ssh root@ "192.168.1.32"
            ;;
        4)
            echo "web02 1.1.1.34"
            ;;
        quit)
            break
            ;;
        *)
            echo "输入编码错误"
            ;;
        esac
done

echo "跳板机结束"
跳板机

优化思路:

  定制化配置---->写一个配置文件

[root@localhost ~]# mkdir /work

 

[root@localhost work]# cp /scripts/3.sh /work/

 自己建一个配置文件目录

[root@localhost work]# mkdir conf
[root@localhost work]# vim conf/jump.conf
0、backup 1.1.1.11
1、web01 1.1.1.12
2、db01 192.168.1.32
3、web02 1.1.1.34
配置文件内容

jump脚本内容:

#!/bin/bash -

ip_array=(`cat ./conf/jump.conf |awk '{print $NF}'`)

while true
do
    cat ./conf/jump.conf
    read -p "Enter an num: " num
    case $num in
        1)
            echo $(ip_array[$num])
            ;;
        1)
            echo $(ip_array[$num])
            ;;
        2)
            ssh root@$(ip_array[$num])
            ;;
        3)
            echo $(ip_array[$num])
            ;;
        quit)
            break
            ;;
        *)
            echo "输入编码错误"
            ;;
        esac
done

echo "跳板机结束"

登录认证脚本:

#!/bin/bash -
username="zrg"
psaaword="123"

failed=0
while true
do

    read -p "Enter a username: " inp_user
    read -p "Enter a password: " inp_pwd

    if [[ "$inp_user" = "$username" && "$inp_pwd" = "$psaaword" ]];then
        echo -e "\nLogin successful."
        #认证成功之后可以做后续的事
        break
    else
        echo -e "\n用户名或密码错误。"
        let failed++
    if [ $failed -eq 3 ]; then
        echo "输出的次数太多了,退出"
        break
    fi
    fi
    echo ""输出的次数:$failed
done
View Code
[root@localhost scripts]# curl -I https://www.dongchedi.com/
[root@localhost scripts]# curl -I https://www.dongchedi.com/
HTTP/1.1 200 OK
Server: Tengine
Content-Type: text/html; charset=utf-8
Content-Length: 188250
Connection: keep-alive
Date: Sat, 21 Jun 2025 14:20:37 GMT
Vary: Accept-Encoding
X-Tt-Logid: 202506212220372CE4E3C7AC3544EAF60B
x-cache: HIT
Cache-Control: private, max-age=180
Server-Timing: inner; dur=37,tt_agw; dur=22
Set-Cookie: ttwid=1%7Ca8LljL9MCxiIgF5T7uMDe7FrTpFSOBNTkSkqs2WLjZA%7C1750515637%7Ced42b760aef87eec9b5237acb41a9aeb9a0044a8681d8a18d888609b15061775; Domain=.dongchedi.com; Path=/; Expires=Sun, 21 Jun 2026 14:20:37 GMT; HttpOnly
Set-Cookie: tt_webid=7518407331690382910; path=/; expires=Sun, 21 Jun 2026 14:20:37 GMT
Set-Cookie: tt_web_version=new; path=/; expires=Thu, 18 Dec 2025 14:20:37 GMT
Set-Cookie: is_dev=false; path=/
Set-Cookie: is_boe=false; path=/
x-tt-trace-host: 015683e821c8935e16e5ea9e507caf685b15919fcf8cb768b20560ddc58b2cf1feaccf1862c62490c8567214018dcb885e1cd9a77bedf40dd27569aad2a2e5628e9cbb6f046041ebe8c848e7f40018ab637a9c8af85de51d67ad4296f53164ec38a8ea751cb05900f15caa7b93f52e4392cf5b2ff536148f0b45450e2b3bdbb8c1b90f2c17b1a270ccc9a636ff2a076989
x-tt-trace-tag: id=03;cdn-cache=miss;type=dyn
x-tt-trace-id: 00-2506212220372CE4E3C7AC3544EAF60B-391828254BCE957D-00
server-timing: cdn-cache;desc=MISS,edge;dur=0,origin;dur=101
Via: dynamic16.cn820[101,0]
Timing-Allow-Origin: *
EagleId: df6ff52417505156376173512e
View Code

不带任何前缀实现脚本调用:

把脚本路径写到PATH。

[root@localhost scripts]# vi /etc/profile
PATH=$PATH:/work:/scripts
export PATH

立即生效:

[root@localhost scripts]# source /etc/profile

或者软连接到已经存在于环境变量PATH的目录

迭代循环

 

for循环

  语法

for 变量名 in 取值列表
do
    循环体
done
for ((初始值;条件;步长))
do
    循环体
done

展示:

for x in 111 112 113 113
do
    echo $x
done

命令的结果也可以当做

for x in `ls /scripts/`
do
    echo $x
done

c语言风格:

for ((i=0;i<=3;i++))
do
    echo $i
done

等同于:

i=0
while ((i<=3))
do
    echo $i
    ((i++))
done

  控制循环次数

for x in {1..3} 
do
    echo hello
    echo world
    echo !
done

  shell风格的for常用in列表格式

for i in 1 2 3
for i in {1,2,3}
for i in {1..9}
for i in {9..1}
for i in {a..z}
for i in {A..Z}
for i in {X..Z}
for i in $(命令)  # 例如:for i in $(head -10 /etc/passwd);do echo $i|cut -d: -f1,2;done
for i in $(find ...)

注意:命令的结果得是空格隔开的或者是换行符隔开的都行。

  for循环的continue和break

  continue:默认退出本次循环。

  break:默认退出本层循环。

for ((i=1;i<=;i++))
do
    if [ $i -eq 3 ]; then
        continue
    fi
    echo $i
done

得到某个网段的所有IP地址

for i in {1..254}
do
ip_addr=192.168.1.$i
echo $ip_addrdone
ping -c1 ip_addr &>/dev/null

 select

 自动生成编号和read。

  语法:

#!/bin/bash -
#PS3='请输入选择的编号:'
select month in Jan Feb mar Apr May Jun Jul Aug Sept Oct Nov Dec quit
do
    if [ "$month" == "quit" ]; then
        break
    else
        echo "$month"
    fi
done
~    
1) Jan       3) mar    5) May    7) Jul     9) Sept  11) Nov   13) quit
2) Feb       4) Apr    6) Jun    8) Aug    10) Oct      12) Dec
#? f

#? 5
May
#? 
1) Jan       3) mar    5) May    7) Jul     9) Sept  11) Nov   13) quit
2) Feb       4) Apr    6) Jun    8) Aug    10) Oct      12) Dec
#? 8
Aug
#? 13

 

 

 

 

 

 

 

  

posted @ 2025-06-18 21:59  张仁国  阅读(12)  评论(0)    收藏  举报
目录代码