【问题标题】:Looping on variables with a condition in bash (Stopping services in a specific order)在 bash 中使用条件循环变量(按特定顺序停止服务)
【发布时间】:2022-09-30 18:10:50
【问题描述】:

我正在 bash 中创建一个脚本来执行以下用例,

  • 根据名称上的特定单词查找特定服务
  • 停止这些服务按特定顺序,例如:service_1、service_2 等等
  • 检查这些服务是否已停止并如果有一个仍在运行,它会打印出它的名字

这是我的进步, 首先,我根据一些仅以其名称存在的单词找到了服务,如下所示,

service_1=$(ls /etc/systemd/system | grep -e text1 | awk -F \' \' \'{print $1}\')
service_2=$(ls /etc/systemd/system | grep -e text2 | awk -F \' \' \'{print $1}\')
service_3=$(ls /etc/systemd/system | grep -e text3 | awk -F \' \' \'{print $1}\')

然后,我按照我想要的顺序停止了它们,如下所示:

if [ ! -z \"$service_1\" ] //if service exists
then
      systemctl stop $service_1
else
      :
fi

if [ ! -z \"$service_2\" ] //if service exists
then
      systemctl stop $service_2
else
      :
fi

if [ ! -z \"$service_3\" ] //if service exists
then
      systemctl stop $service_3
else
      :
fi

问题来了。如您所知,停止服务时,可能需要一些时间才能完全停止,因此根据上述条件,它将继续停止第二个服务而不完全停止前一个服务。我想要的是按顺序停止服务,因此在停止第二个服务之前,应该完全停止第一个服务,依此类推。如何做到这一点?我认为这可以通过循环来完成,但我错过了方式。 关于第三个用例,在过滤服务的状态输出作为服务已停止的指示符后,我定义了以下包含单词“inactive”的变量:

service_1_status=$(systemctl status $service_1 | grep -e \"inactive\")
service_2_status=$(systemctl status $service_2 | grep -e \"inactive\")
service_3_status=$(systemctl status $service_3 | grep -e \"inactive\")

然后,我尝试在它们上循环以找出是否有仍然处于活动状态的服务来打印它的名称,如下所示:

arr=($service_1_status $service_2_status $service_3_status $service_q_inf_status)
for i in \"${arr[@]}\"
do
      if \"${arr[$i}\" != \"inactive\"
      then
            echo $i
      else
            echo \"All Services are now Stopped\"
      fi
done

我不知道这种语法是否完全可操作,因为它不起作用,但这是我想要做的逻辑。这样做的正确方法是什么?

  • grep | awk 是一种反模式。而不是grep -e text1 | awk -F \' \' \'{print $1}\',只需使用awk \'/text1/{print $1}\'
  • Parsing the output of ls 是一种反模式。而不是ls /etc/systemd/system | grep -e text1,只需使用ls /etc/systemd/system/*text1*。这仍然会让您将 ls 输出通过管道传输到 awk,尽管这仍然是一种反模式 - 向我们展示 /etc/systemd/system 目录的一些示例内容,以便我们可以帮助您做任何您想做的事情正确的路。
  • 您可以使用systemctl is-active 了解服务器是启动还是关闭。 --wait 将等待停止完成后再继续。查看手册页以了解 --wait 上的警告。
  • 感谢@WilliamPursell 的投入,它确实节省了很多精力。
  • 感谢@Nic3500,我还发现了一些有用的选项,可以管理启动/停止服务的顺序,例如 --after 和 --before。

标签: linux bash systemd


【解决方案1】:
# Service variables.

service_1=$(ls /etc/systemd/system | grep -e text1 | \
awk -F ' ' '{print $1}')

service_2=$(ls /etc/systemd/system | grep -e text2 | \
awk -F ' ' '{print $1}')

service_3=$(ls /etc/systemd/system | grep -e text3 | \
awk -F ' ' '{print $1}')

# Service stopping code.

[[ -n "${service_1}" ]] && systemctl stop "{$service_1}"
[[ -n "${service_2}" ]] && systemctl stop "{$service_2}"
[[ -n "${service_3}" ]] && systemctl stop "{$service_3}"


service_1_status=$(systemctl status $service_1 | grep -e "inactive")
service_2_status=$(systemctl status $service_2 | grep -e "inactive")
service_3_status=$(systemctl status $service_3 | grep -e "inactive")

[[ -n "${service_1_status}" ]] && \
[[ -n "${service_2_status}" ]] && \
[[ -n "${service_3_status}" ]] && \
echo "All services stopped."

这是一个 3 输入测试。只有当所有三个变量都等于不活动时,它才会通过。

【讨论】:

  • 这只会停止服务,然后检查它们是否已停止,但不会按照提到的特定顺序执行此操作,我想确保 service_1 在继续 service_2 之前完全停止,并且“systemctl stop”只会触发操作但不要等到服务完全停止。
  • 假设您使用的是 Linux,请使用“ps -ef | grep ${servicename}”检查它是否仍在运行。
  • 如果它仍在运行怎么办?,我想让它等到前一个服务完全停止然后重试再次停止服务(如果 service_1 仍然处于活动状态,请等到它变为非活动状态然后再次尝试启动 service_2),这就是行为我想做,我认为这应该使用带有条件的循环来处理主要条件的第二部分(检查服务是否处于非活动状态)。
  • 谢谢,我也尝试了我建议的方法并且它有效。
【解决方案2】:
#!/bin/bash

service_1=$(ls /etc/systemd/system | grep -e text1 | awk -F ' ' '{print $1}')
service_2=$(ls /etc/systemd/system | grep -e text2 | awk -F ' ' '{print $1}')
service_3=$(ls /etc/systemd/system | grep -e text3 | awk -F ' ' '{print $1}')

if [ ! -z "$service_1" ] # if service exists
then
      systemctl start $service_1
      sleep 30 # 30s
      echo "$service_1 started"
else
      :
fi

if [ ! -z "$service_1" ] # if service exists
then
      if [ $(systemctl is-active $service_1) == "active" ] # if service is active
      then
            if [ ! -z "$service_2" ] # if service exists
            then
                  systemctl start $service_2
                  sleep 30 # 30s
                  echo "$service_2 started"
            else
                  :
            fi
      else
      echo "$service_1 is either inactive or failed, Please check !"
      exit
      fi
elif [ ! -z "$service_2" ]
then
      systemctl start $service_2
      sleep 30 # 30s
      echo "$service_2 started"
else
:
fi

if [ ! -z "$service_2" ] # if service exists
then
      if [ $(systemctl is-active $service_2) == "active" ] # if service is active
      then
            if [ ! -z "$service_3" ] # if service exists
            then
                  systemctl start $service_3
                  sleep 30 # 30s
                  echo "$service_3 started"
            else
                  :
            fi
      else
      echo "$service_2 is either inactive or failed, Please check !"
      exit
      fi
elif [ ! -z "$service_3" ]
then
      systemctl start $service_3
      sleep 30 # 30s
      echo "$service_3 started"
else
:
fi`enter code here`

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-02
    • 2013-10-17
    • 1970-01-01
    • 2018-03-09
    • 2014-12-05
    • 2017-06-15
    • 2020-10-20
    • 2015-04-11
    相关资源
    最近更新 更多