Проверьте, пуст ли массив в Bash

Ну, действительно обратите внимание, что, если я вспоминаю хорошо (это было некоторое время, так как я сделал работу DB) КОЛИЧЕСТВО (*) запросы без оператора Where на innodb таблицах известно медленнее, чем на таблицах MyISAM и Memory.

Кроме того, это - случайно Xen DomU?

Каков frontend язык? Если PHP, это использует MySQL или MySQLi? Они используют постоянные соединения?

Вы не упомянули базовую операционную систему, но в случае Linux я запустил бы, уставившись на вывод free -m, обращение особого внимания на последние две строки, которые будут видеть, трудна ли память в целом.

[0:504] callisto:cyanotype $ free -m
             total       used       free     shared    buffers     cached
Mem:          3961       3816        144          0        184       1454
-/+ buffers/cache:       2177       1784
Swap:         2898          0       2898

Здесь у нас есть система, это здорово (это - моя рабочая станция). Второй столбец исключает буферы и кэш, таким образом, я на самом деле использую 2177 МБ памяти и имею легко доступные 1 784 мегабайта.

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

Затем предоставление vmstat(8), видеть, повреждает ли Ваша система как безумный, было бы полезно, также.

[0:505] callisto:cyanotype $ vmstat 5 10
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0      0 134116 189828 1499948    0    0    11     3   44   49  1  1 98  0
 0  0      0 143112 189836 1489688    0    0     0     6  526 2177  1  1 98  0
 0  0      0 139268 190504 1491864    0    0   512     4  663 4704  2  1 96  1
 2  0      0 136688 191084 1493484    0    0   473     5  641 3039  1  1 97  1
 0  0      0  52636 191712 1518620    0    0  5066     4 1321 6600  8  2 86  4
 5  0      0  72992 193264 1377324    0    0 10742    31 1602 7441 12  3 80  5
 2  1      0  84036 193896 1202012    0    0 10126    43 2621 4305 31  2 57 10
 3  0      0  42456 195812 1060904    0    0  3970    75 55327 9806 43 5 41 10
 8  1      0  34620 197040 942940     0    0  3554    64 50892 12531 43 6 44 6
^C
[0:506] callisto:cyanotype $ 

(Мой рабочий стол действительно не делает всего так очень здесь, извините. Какая трата 8 совершенно хороших ядер)

Если Вы видите много времени проводящего процесса в 'b' столбце, который означает, что они заблокированы, ожидая чего-то. Часто это - IO. Важные столбцы здесь si и so. Проверьте, заполняются ли они с высокими значениями. Если так, это может быть Вашей проблемой - что-то использует большую память, больше, чем Вы можете на самом деле усилие. Используя top(4) и упорядочивание столбцов % памяти (shift+m, в то время как в вершине) могло бы показать преступнику (преступникам).

Не невозможно, что Ваша система повреждает к и от подкачки и насыщает диски, вызывая заблокированные потоки и процессы. Инструмент iostat(8)(часть пакета sysstat, обычно), должен быть дан водоворот, чтобы видеть, есть ли у Вас процессы, которые заблокированы, застревают на IO_WAIT. Влажный диск может записать плохие новости для целой системы при высокой загрузке, особенно если система подкачивает много.

Вы могли бы выполнить iostat с расширенной статистикой, каждые пять секунд, например:

[0:508] callisto:cyanotype $ iostat -x 5
Linux 2.6.35-23-generic (callisto)  2010-11-30  _x86_64_    (8 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          16,55    0,12    2,70    2,60    0,00   78,02

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm      %util
sdc               0,00     2,00    1,00    0,80    27,20    22,40    27,56     0,01    3,33   3,33       0,60
sdd               0,00    12,60   67,60    4,80  4222,40   139,20    60,24     0,62    8,62   3,29      23,80
sde               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00       0,00
sdf               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          32,02    0,10    1,83    0,44    0,00   65,61

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sdc               0,60     3,20   11,00    0,80   265,60    32,00    25,22     0,05    3,90   2,88   3,40
sdd               0,00     8,20    0,00    3,00     0,00    89,60    29,87     0,02    8,00   7,33   2,20
sde               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00
sdf               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          49,26    0,22    3,12    0,12    0,00   47,28

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sdc               6,20     3,00    7,40    3,80   208,00    54,40    23,43     0,09    7,86   2,50   2,80
sdd               0,00    15,20    0,20    4,00     1,60   152,00    36,57     0,03    6,67   6,19   2,60
sde               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00
sdf               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          16,00    0,54    1,05    1,07    0,00   81,35

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
sdc               4,20     0,00   31,40    0,00  3204,80     0,00   102,06     0,17    4,90   2,68   8,40
sdd               0,00    28,20    0,20    2,60     1,60   246,40    88,57     0,02    7,14   7,14   2,00
sde               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00
sdf               0,00     0,00    0,00    0,00     0,00     0,00     0,00     0,00    0,00   0,00   0,00

^C

Это должно позволить Вам легко видеть, насыщаются ли Ваши объемы. Например, здесь, Вы видите, что мои диски ужасно недостаточно используются, что система тратит большую часть своего бездействия циклов CPU и т.д. и т.д. Если тот процент находится главным образом в столбце IOWAIT %, хорошо у Вас есть узкое место IO здесь. Вы, вероятно, уже знаете, что все это, но просто покрывающий все основания удостоверяется.

Идея состоит в том, что Ваш файл конфигурации изменился, и у Вас нет истории его (подвергание Ваших файлов конфигурации при управлении версиями является прекрасной идеей по той самой причине) - и это не невозможно размер буфера suddendly измененный таким образом, делающие дорогие запросы как КОЛИЧЕСТВО (*) без ВЫБОРА suddendly начинают проглатывать ресурсы.

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

Насколько большой буферы, как query_cache_size значение, и особенно sort_buffer размеры? (Если это не уместится в памяти, то это будет выполненный на диске по крупной стоимости, поскольку я уверен, что можно вообразить).

Насколько большой innodb_buffer_pool_size?

Насколько большой table_cacheи самое главное, который оценивает соответствия в системных пределах для дескрипторов файлов? (и открытый предел файлов в [mysqld] и на уровне ОС).

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

Вы могли также использовать innotop(1) видеть, что продолжается больше подробно, также.

Я надеюсь, что это помогает так или иначе или дает Вам начальную точку :)

111
задан 29 June 2019 в 13:05
8 ответов

Предположим, что ваш массив $ errors , просто проверьте, равно ли нулю количество элементов.

if [ ${#errors[@]} -eq 0 ]; then
    echo "No errors, hooray"
else
    echo "Oops, something went wrong..."
fi
144
ответ дан 28 November 2019 в 19:20

Можно также рассматривать массив как простую переменную. Таким образом, просто используя

if [ -z "$array" ]; then
    echo "Array empty"
else
    echo "Array non empty"
fi

или используя другую сторону

if [ -n "$array" ]; then
    echo "Array non empty"
else
    echo "Array empty"
fi

, проблема с этим решением заключается в том, что если массив объявлен таким образом: array=('' foo). В результате этих проверок массив будет объявлен пустым, а это явно не так. (спасибо @musiphil!)

Используя [ -z "$array[@]". ] тоже явно не является решением. Не указание фигурных скобок пытается интерпретировать $array как строку ([@] в этом случае является простой строкой литерала) и поэтому всегда преподносится как ложь: "пустая ли строка литерала [@]?". Очевидно, что нет.

8
ответ дан 28 November 2019 в 19:20

В моем случае второго ответа было недостаточно, потому что могли быть пробелы. Я пришел с:

if [ "$(echo -ne ${opts} | wc -m)" -eq 0 ]; then
  echo "No options"
else
  echo "Options found"
fi
0
ответ дан 28 November 2019 в 19:20

Я проверил это с помощью bash-4.4.0 :

#!/usr/bin/env bash
set -eu
check() {
    if [[ ${array[@]} ]]; then
        echo not empty
    else
        echo empty
    fi
}
check   # empty
array=(a b c d)
check   # not empty
array=()
check   # empty

и bash-4.1.5 :

#!/usr/bin/env bash
set -eu
check() {
    if [[ ${array[@]:+${array[@]}} ]]; then
        echo non-empty
    else
        echo empty
    fi
}
check   # empty
array=(a b c d)
check   # not empty
array=()
check   # empty

В последнем случае вы нужна следующая конструкция:

${array[@]:+${array[@]}}

для того, чтобы он не завершился ошибкой при пустом или неустановленном массиве. Это если вы выполните set -eu , как я обычно. Это обеспечивает более строгую проверку ошибок. Из документы :

-e

Немедленно выйти из конвейера (см. Конвейеры), который может состоять из одной простой команды (см. Простые команды), списка (см. Списки) или составная команда (см. Составные команды) возвращает ненулевое состояние. Оболочка не завершает работу, если команда, которая завершилась ошибкой, является частью списка команд сразу после ключевого слова while или until, частью теста в операторе if, частью любой команды, выполняемой в && или || list за исключением команды, следующей за последним && или ||, любой команды в конвейере, кроме последней, или если статус возврата команды инвертируется с помощью!. Если составная команда, отличная от подоболочки, возвращает ненулевое состояние из-за сбоя команды при игнорировании -e, оболочка не завершается. Ловушка на ERR, если она установлена, выполняется до выхода из оболочки.

Этот параметр применяется к среде оболочки и к каждой среде подоболочки отдельно (см. Среда выполнения команд) и может вызвать выход подоболочки перед выполнением всех команд в подоболочка.

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

-u

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

Если вам это не нужно, не стесняйтесь опускать : + $ {array [@]} часть.

Также обратите внимание, что здесь необходимо использовать оператор [, с [ вы получите:

$ cat 1.sh
#!/usr/bin/env bash
set -eu
array=(a b c d)
if [ "${array[@]}" ]; then
    echo non-empty
else
    echo empty
fi

$ ./1.sh
_/1.sh: line 4: [: too many arguments
empty
3
ответ дан 28 November 2019 в 19:20

Я предпочитаю использовать двойные скобки:

if [[ !${array[@]} ]]
then
    echo "Array is empty"
else
    echo "Array is not empty"
fi

Двойные скобки: https://stackoverflow.com/ questions / 669452 / is-preferable-over-in-bash

0
ответ дан 28 November 2019 в 19:20

Я обычно использую арифметическое расширение в этом случае:

if (( ${#a[@]} )); then
    echo not empty
fi
15
ответ дан 28 November 2019 в 19:20

Если вы хотите обнаружить массив с пустыми элементами , например ] arr = ("" "") как пустое, то же самое, что и arr = ()

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

Но "$ {arr [ *]} " расширяется элементами, разделенными первым символом IFS . Поэтому вам нужно сохранить / восстановить IFS и выполнить IFS = '' , чтобы это сработало, или проверьте, что длина строки == # элементов массива - 1. (Массив n элементов имеет разделители n-1 ). Чтобы справиться с этим поочередно, проще всего дополнить конкатенацию 1

arr=("" "")

## Assuming default non-empty IFS
## TODO: also check for ${#arr[@]} -eq 0
concat="${arr[*]} "      # n-1 separators + 1 space + array elements
[[ "${#concat}" -ne "${#arr[@]}" ]]  && echo not empty array || echo empty array

тестовым примером с помощью set -x

### a non-empty element
$ arr=("" "x")
  + arr=("" "x")
$ concat="${arr[*]} ";  [[ "${#concat}" -ne "${#arr[@]}" ]] && echo not empty array || echo empty array
  + concat=' x '
  + [[ 3 -ne 2 ]]
  + echo not empty array
not empty array

### 2 empty elements
$ arr=("" "")
  + arr=("" "")
$ concat="${arr[*]} ";  [[ "${#concat}" -ne "${#arr[@]}" ]] && echo not empty array || echo empty array
  + concat='  '
  + [[ 2 -ne 2 ]]
  + echo empty array
empty array

К сожалению, это не удается для arr = () : ] [[1 -ne 0]] . Так что вам нужно сначала отдельно проверить действительно ли пустые массивы


Или с помощью IFS = '' . Возможно, вы захотите сохранить / восстановить IFS вместо использования подоболочки, потому что вы не можете легко получить результат из подоболочки.

# inside a () subshell so we don't modify our own IFS
(IFS='' ; [[ -n "${arr[*]}" ]] && echo not empty array || echo empty array)

пример:

$ arr=("" "")
$ (IFS='' ; [[ -n "${arr[*]}" ]] && echo not empty array || echo empty array)
   + IFS=
   + [[ -n '' ]]
   + echo empty array
empty array

работает с arr = ( ) - это все еще пустая строка.

2
ответ дан 28 November 2019 в 19:20

Вы также можете воспользоваться jq, если он установлен в вашей системе:

if [[ $(echo $array | jq -r 'length') -eq 0 ]]
then
    echo "Array is empty"
else
    echo "Array is not empty"
fi
0
ответ дан 1 April 2021 в 09:52

Теги

Похожие вопросы