Цикл проходит через условие полностью перед else.

Вопрос или проблема

У меня есть большой файл со списком хостов. Я подключаюсь удаленно к серверам, чтобы извлечь переменную, которая может заканчиваться на нечетное или четное число. Я запускаю цикл for, чтобы выполнить одно и то же действие (перезапуск) для всех переменных, заканчивающихся на нечетное число, а затем выполняю то же действие (перезапуск) для переменных, заканчивающихся на четное число.

У меня есть следующий код, где он просто проходит по списку переменных и выполняет действие в порядке. Но я хочу, чтобы действие выполнялось над набором переменных, заканчивающихся на нечетное число, и не предпринимать никаких действий, если встречается четная переменная, пока все переменные с нечетными номерами не будут обработаны.

Есть ли способ, чтобы я мог запускать свои команды (действия) на всех серверах с нечетными номерами, а затем запускать их на серверах с четными номерами?

пример моей переменной:

apple01
mango02
bat13
ball21
bread24


for i in $(cat mylist.txt);
do
var1=$(ssh -q -o StrictHostKeyChecking=no myid$i cat /etc/sysconfig|grep mystring|awk -F"=" '{print $2}')
if [[ ${var1: -1} =~ [13579] ]]; then
    echo "String ends with an odd number $var1"
else

  if [[ ${var1: -1} =~ [02468] ]]; then
    echo "String ends with an even number $var1"
  fi

fi
done

Вот вывод

String ends with an odd number apple01
String ends with an even number mango02
String ends with an odd number bat13
String ends with an odd number ball21
String ends with an even number bread24

Вот что я хотел бы увидеть

String ends with an odd number apple01
String ends with an odd number bat13
String ends with an odd number ball21
String ends with an even number mango02
String ends with an even number bread24

Почему вы ожидаете, что структура if изменит порядок строк в вашем файле? Вы повторно запускаете вложенные if для каждой строки отдельно. Единственный способ получить их в вашем порядке — это отсортировать после завершения цикла.

for i in $(cat mylist.txt);
do
var1=$(ssh -q -o StrictHostKeyChecking=no myid$i cat /etc/sysconfig|grep mystring|awk -F"=" '{print $2}')
if [[ ${var1: -1} =~ [13579] ]]; then
    echo "String ends with an odd number $var1"
else

  if [[ ${var1: -1} =~ [02468] ]]; then
    echo "String ends with an even number $var1"
  fi

fi
done | sort -k5,5r

Если разделительная строка важна для вас, вам понадобится немного более сложная команда ….

... | sort -k5,5r | awk '{a[$5]++; if(NR>1&&a[$5]==1){print ""}}1'

Во-первых, /etc/sysconfig — это каталог, а не файл. Вы не можете его использовать с cat. Я предполагаю, что вы имели в виду /etc/sysctl.conf.

Если я правильно понимаю ваши комментарии, вы хотите выполнить удаленное действие по перезапуску службы в зависимости от четности или нечетности значения определенной переменной в /etc/sysctl.conf. Вы хотите перезапустить все нечетные значения, и только после этого перезапустить все четные. И имена хостов, судя по вашему комментарию и примеру, на самом деле не имеют ничего общего с тем, является ли значение в /etc/sysctl.conf четным или нечетным.

Если я ошибаюсь и вам просто нужно разделить на основе того, что имя хоста имеет четное или нечетное значение, тогда просто разделите на два файла перед выполнением циклов:

mylist="$1"
[ -f "$mylist" ] || { echo "List $mylist not found"; exit 1;}
mydir="$(mktemp -d)"
grep -E '[13579]$' "$mylist" > "$mydir"/odds.txt
grep -E '[02468]$' "$mylist" > "$mydir"/evens.txt
grep -q '[^0-9]$' "$mylist" && { echo "Warning, unexpected line contents in $mylist, aborting for safety"; exit 1;}
for h in $(cat "$mydir"/odds.txt); do
  some-command-with "$h"
done
for h in $(cat "$mydir"/evens.txt); do
  some-command-with "$h"
done
rm -rf "$mydir"

Но если вам действительно нужно условие для действия на основе удаленной информации, т.е. на основе значения, найденного в /etc/sysctl.conf, у вас есть несколько вариантов:

  1. Сделать два прохода, один для сбора информации с целью разделения хостов на две категории, и второй проход для фактического выполнения действия. В качестве незначительного варианта этого, вы можете немедленно выполнить действие, если найдете нечетное значение в sysctl, а если будет найдено четное значение, вернуть статус вашему скрипту, который укажет вашему скрипту сохранить это имя хоста для последующей обработки.

  2. Сделать некоторый вид параллельной обработки, например, немедленно запустить действие, но для хостов с четными значениями запускать с задержкой, или —

  3. Наилучший вариант — использовать какой-либо инструмент управления конфигурацией. Я настоятельно рекомендую CFEngine, потому что он низкоуровневый и очень легкий, а также инженерно зрелый. (Альтернативы в основном требуют большой стека интерпретаторов и множества плагинов и прочего; CFEngine — это единственный бинарный файл, написанный на языке С, как и традиционные инструменты Unix.) Я был бы рад предложить, как это сделать и написать пример политики CFEngine, но, честно говоря, спецификация того, что вы пытаетесь сделать, слишком неясна, чтобы попробовать.


Дополнительный комментарий: Имейте в виду, что содержимое /etc/sysctl.conf не обязательно соответствует значениям этих параметров ядра в работающем ядре. Если вы хотите узнать, какие параметры считают себя установленными в ядре, вы должны проверить с помощью sysctl -n someconfigparametername (см. man page).

Ответ или решение

Ваш вопрос описывает ситуацию, в которой требуется выполнить определенное действие (в данном случае — перезагрузку) на основе проверки переменных, полученных с удаленных серверов. Эти переменные имеют значение, оканчивающееся на четное или нечетное число. Ваша цель — сначала выполнить действие для всех переменных, оканчивающихся на нечетное число, и только затем для переменных с четными окончаниями. Рассмотрим, как вы можете организовать обработку данных так, чтобы достичь этого порядка.

Теория

При работе с данными в текстовых файлах часто возникает потребность в их сортировке на основе определенных условий. В вашем случае, вы хотите разделить список хостов на две группы в зависимости от значения переменной, полученной при выполнении команды на удаленном сервере. Стандартная конструкция if-else в цикле for обрабатывает каждую строку последовательно, что приводит к тому, что строки сохраняют свой исходный порядок. Чтобы изменить это поведение и сначала обработать все переменные с нечетным окончанием, а затем с четным, вам потребуется два отдельных прохода по файлу.

Пример

Следующее решение описывает структуру сценария, который будет сначала собирать всю информацию, классифицировать хосты, а затем выполнять требуемое действие.

#!/bin/bash

mylist="mylist.txt"
[ -f "$mylist" ] || { echo "List $mylist not found"; exit 1;}

# Создаем временные файлы для классификации
odds_file=$(mktemp)
evens_file=$(mktemp)

# Сначала собираем информацию и классифицируем хосты
for i in $(cat "$mylist"); do
    var1=$(ssh -q -o StrictHostKeyChecking=no myid@$i cat /etc/sysctl.conf | grep mystring | awk -F"=" '{print $2}')
    if [[ ${var1: -1} =~ [13579] ]]; then
        echo $i >> "$odds_file"
    elif [[ ${var1: -1} =~ [02468] ]]; then
        echo $i >> "$evens_file"
    fi
done

# Первая итерация: выполняем действие для нечетных
for i in $(cat "$odds_file"); do
    echo "String ends with an odd number on $i"
    # Выполнение действия
done

# Вторая итерация: выполняем действие для четных
for i in $(cat "$evens_file"); do
    echo "String ends with an even number on $i"
    # Выполнение действия
done

# Удаление временных файлов
rm -f "$odds_file" "$evens_file"

Применение

В зависимости от того, что именно вы хотите сделать с переменной (например, перезапустить службу), вы можете вставить соответствующие команды в места, отмеченные комментариями # Выполнение действия. Преимущество этого подхода в его ясности: сначала происходит классификация, а затем уже обработка, что позволяет легко расширять сценарий и адаптировать его для более сложных операций.

Также, если вас интересует использование конфигурационного менеджмента, как упоминалось в подсказке, существует множество инструментов, таких как Ansible, Puppet или Chef, которые позволяют автоматизировать подобные задачи более эффективно, однако их использование подразумевает определенные накладные расходы на установку и поддержку.

В заключение, важно помнить, что взаимодействие с системными конфигурациями требует ответственности и понимания, какие именно значения должны быть проверены. Всегда тестируйте сценарии в безопасной среде перед развертыванием на рабочих серверах.

Оцените материал
Добавить комментарий

Капча загружается...