Bash: подождите, пока загрузка процессора не станет ниже порога

В bash script мне нужно подождать, пока загрузка процессора не станет ниже порога.

Другими словами, мне нужна команда wait_until_cpu_low, которую я бы использовал следующим образом:

# Trigger some background CPU-heavy command
wait_until_cpu_low 40
# Some other commands executed when CPU usage is below 40%

Как я могу это сделать?

Edit:

  • целевая ОС: Red Hat Enterprise Linux Server release 6.5
  • Я рассматриваю среднее использование ЦП (по всем ядрам)

Ответ 1

wait_for_cpu_usage()
{
    current=$(mpstat 1 1 | awk '$12 ~ /[0-9.]+/ { print int(100 - $12 + 0.5) }')
    while [[ "$current" -ge "$1" ]]; do
        current=$(mpstat 1 1 | awk '$12 ~ /[0-9.]+/ { print int(100 - $12 + 0.5) }')
        sleep 1
    done
}

Обратите внимание, что пакет sysstat установлен.

Ответ 2

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

Функция:

function wait_for_cpu_usage {
    threshold=$1
    while true ; do
        # Get the current CPU usage
        usage=$(top -n1 | awk 'NR==3{print $2}' | tr ',' '.')

        # Compared the current usage against the threshold
        result=$(bc -l <<< "$usage <= $threshold")
        [ $result == "1" ] && break

        # Feel free to sleep less than a second. (with GNU sleep)
        sleep 1
    done
    return 0
}

# Example call
wait_for_cpu_usage 25

Обратите внимание, что я использую bc -l для сравнения, так как top печатает использование ЦП в качестве значения поплавка.

Ответ 3

Более эффективная версия просто вызывает mpstat и awk один раз каждый и удерживает их обоих до тех пор, пока они не будут выполнены; нет необходимости явно sleep и перезапускать оба процесса каждую секунду (что на встроенной платформе может привести к измеримым служебным данным):

wait_until_cpu_low() {
  awk -v target="$1" '
    $13 ~ /^[0-9.]+$/ {
      current = 100 - $13
      if(current <= target) { exit(0); }
    }' < <(mpstat 1)
}

Я использую $13 здесь, потому что там, где idle % для моей версии mpstat; замените соответствующим образом, если ваш отличается.

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