Проверка поддержки массивов оболочкой

Да, со специализированным профилем apparmor, т.е.

/usr/bin/curl {
    ...

    # block ipv4 acces
    deny network inet,
    # ipv6 
    deny network inet6,
    # raw socket
    deny network raw,

}

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

11
10.04.2019, 06:15
2 ответа

Предполагая, что вы хотите ограничиться оболочками, подобными Bourne (многие другие оболочки, такие как csh , tcsh , rc , es или fish поддерживают массивы, но пишут скрипт, совместимый в то же время с оболочками типа Борна, а это сложно и, как правило, бессмысленно, поскольку они являются интерпретаторами для совершенно разных и несовместимых языков), обратите внимание, что между реализациями есть существенные различия.

Оболочки, подобные Bourne, которые поддерживают массивы:

  • ksh88 (это первый реализующий массивы, ksh88 по-прежнему встречается как ksh в большинстве традиционных коммерческих Unix-систем, где он также является основой для sh )

    • массивы являются одномерными
    • Массивы определяются как set -A array foo bar или set -A array - "$ var". .., если вы не можете гарантировать, что $ var не будет начинаться с - или + .
    • Индексы массива начинаются с 0 .
    • Отдельные элементы массива назначаются как a [1] = значение .
    • массивы разрежены. То есть a [5] = foo будет работать, даже если a [0,1,2,3,4] не установлены, и оставит их неустановленными.
    • $ {a [5]} для доступа к элементу индекса 5 (не обязательно к 6-му элементу, если массив разреженный). 5 может быть любым арифметическим выражением.
    • Размер массива и нижний индекс ограничены (до 4096).
    • $ {# a [@]} - это номер назначенного элемента в массиве (не самый большой присвоенный индекс).
    • нет способа узнать список присвоенных индексов (кроме тестирования 4096 элементов по отдельности с помощью [[-n "$ {a [i] + set}"]] ).
    • $ a совпадает с $ {a [0]} . То есть массивы каким-то образом расширяют скалярные переменные, давая им дополнительные значения.
  • pdksh и производные (это основа для ksh , а иногда sh нескольких BSD и была единственной реализацией ksh с открытым исходным кодом до того, как исходный код ksh93 был освобожден):

    В основном похож на ksh88 , но примечание:

    • Некоторые старые реализации не поддерживали set -A array - foo bar , ( - wasn ' т нужен там).
    • $ {# a [@]} - это единица плюс индекс наибольшего присвоенного индекса. ( a [1000] = 1; echo "$ {# a [@]}" выводит 1001, даже если массив имеет только один элемент.
    • в более новых версиях размер массива больше не ограничен (кроме размера целых чисел).
    • в последних версиях mksh есть несколько дополнительных операторов, вдохновленных bash , ksh93 или zsh как присваивания а-ля а = (ху) , а + = (z), $ {! A [@]} , чтобы получить список присвоенных индексов.
  • zsh . Массивы zsh , как правило, лучше спроектированы и используют лучшее из массивов ksh и csh . Они похожи на ksh , но со значительными отличиями: индексы

    • начинаются с 1, а не с 0 (за исключением эмуляции ksh ), что согласуется с массивом Борна (параметры позиции $ @, который zsh также предоставляет как массив $ argv) и csh массивы.
    • они представляют собой отдельный тип от нормальных / скалярных переменных. Операторы применяются к ним по-разному, как и следовало ожидать. $ a не то же самое, что $ {a [0]} , но расширяется до непустых элементов массива ( "$ {a [@]}" для всех элементов, как в ksh ).
    • это обычные массивы, а не разреженные массивы. a [5] = 1 работает, но присваивает всем элементам с 1 по 4 пустую строку, если они не были назначены. Итак, $ {# a [@]} (то же самое, что $ {# a} , которое в ksh является размером элемента индекса 0) - это количество элементов в массиве и наибольший присвоенный индекс. Поддерживаются
    • ассоциативные массивы.
    • Поддерживается большое количество операторов для работы с массивами, слишком большое, чтобы перечислять здесь.
    • массивы, определенные как a = (x y) . set -A axy также работает, но set -A a - xy не поддерживается, если только в эмуляции ksh ( - не требуется в эмуляции zsh ).
  • кш93 . (здесь описаны последние версии). ksh93 , долгое время считавшийся экспериментальным , теперь можно найти во все большем количестве систем, поскольку он был выпущен как FOSS. Например, это / bin / sh (где он заменил оболочку Bourne, / usr / xpg4 / bin / sh , оболочка POSIX по-прежнему основана на ksh88 ) и ksh из Solaris 11 . Его массивы расширяют и улучшают ksh88.

    • a = (xy) можно использовать для определения массива, но поскольку a = (...) также используется для определения составных переменных ( a = (foo = bar bar = baz) ), a = () неоднозначно и объявляет составную переменную, а не массив.
    • массивы являются многомерными ( a = ((0 1) (0 2)) ), а элементы массива также могут быть составными переменными ( a = ((ab) (c = dd = f)); echo "$ {a [1] .c}" ).
    • Синтаксис a = ([2] = foo [5] = bar) может использоваться для одновременного определения разреженных массивов.
    • Ограничения по размеру сняты.
    • Не до степени zsh , но также поддерживается большое количество операторов для управления массивами.
    • "$ {! A [@]}" для получения списка индексов массива.
    • Ассоциативные массивы также поддерживаются как отдельный тип.
  • Баш . bash - это оболочка проекта GNU. Он используется как sh в последних версиях OS / X и некоторых дистрибутивах GNU / Linux. Массивы bash в основном имитируют массивы ksh88 с некоторыми особенностями ksh93 и zsh .

    • a = (x y) поддерживается. set -A a x y не поддерживается . a = () создает пустой массив (в bash нет составных переменных).
    • "$ {! A [@]}" для списка индексов. Поддерживается синтаксис
    • a = ([foo] = bar) , а также некоторые другие из ksh93 и zsh .
    • Последние версии bash также поддерживают ассоциативные массивы как отдельный тип.
  • яс . Это относительно недавняя, чистая, многобайтовая реализация POSIX sh. Не широко используется. Его массивы - это еще один чистый API, похожий на zsh

    • массивы не разреженные
    • Индексы массивов начинаются с 1
    • определены (и объявлены) с вставленными элементами a = (var value)
    • , удалено или изменено с помощью array builtin
    • array -sa 5 value для изменения 5 -го элемента приведет к ошибке, если этот элемент не был назначен заранее.
    • количество элементов в массиве равно $ {a [#]} , $ {# a [@]} - размер элементов в виде списка.
    • Массивы - это отдельный тип. Вам понадобится a = ("$ a") , чтобы переопределить скалярную переменную как массив, прежде чем вы сможете добавлять или изменять элементы.
    • массивы не поддерживаются при вызове как sh .

Итак, из этого вы можете видеть, что обнаружение поддержки массивов, которое вы могли бы сделать с:

if (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'
   ) > /dev/null 2>&1
then
  array_supported=true
else
  array_supported=false
fi

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

Как

unset a
array_elements() { eval "REPLY=\"\${#$1[@]}\""; }
if (set -A a -- a) 2> /dev/null; then
  set -A a -- a b
  case ${a[0]}${a[1]} in
    --) set_array() { eval "shift; set -A $1"' "$@"'; }
        set_array_element() { eval "$1[1+(\$2)]=\$3"; }
        first_indice=0;;
     a) set_array() { eval "shift; set -A $1"' -- "$@"'; }
        set_array_element() { eval "$1[1+(\$2)]=\$3"; }
        first_indice=1;;
   --a) set_array() { eval "shift; set -A $1"' "$@"'; }
        set_array_element() { eval "$1[\$2]=\$3"; }
        first_indice=0;;
    ab) set_array() { eval "shift; set -A $1"' -- "$@"'; }
        set_array_element() { eval "$1[\$2]=\$3"; }
        first_indice=0;;
  esac
elif (eval 'a[5]=x') 2> /dev/null; then
  set_array() { eval "shift; $1=("'"$@")'; }
  set_array_element() { eval "$1[\$2]=\$3"; }
  first_indice=0
elif (eval 'a=(x) && array -s a 1 y && [ "${a[1]}" = y ]') 2> /dev/null; then
  set_array() { eval "shift; $1=("'"$@")'; }
  set_array_element() {
    eval "
      $1=(\${$1+\"\${$1[@]}"'"})
      while [ "$(($2))" -ge  "${'"$1"'[#]}" ]; do
        array -i "$1" "$2" ""
      done'
    array -s -- "$1" "$((1+$2))" "$3"
   }
  array_elements() { eval "REPLY=\${$1[#]}"; }
  first_indice=1
else
  echo >&2 "Array not supported"
fi

А затем вы обращаетесь к элементам массива с помощью "$ {a [$ first_indice + n]}" , ко всему списку с помощью "$ {a [@]}" и используйте функции оболочки ( array_elements , set_array , set_array_element ), чтобы получить количество элементов массива (в $ REPLY ), задайте массив целиком или назначьте отдельные элементы.

Наверное, не стоит усилий. Я бы использовал perl или ограничился массивом оболочки Bourne / POSIX: «$ @» .

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

Вы можете настроить массивы zsh так, чтобы они были больше похожи на массивы ksh в локальных областях (в функциях или анонимных функциях).

myfunction() {
  [ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
  # use arrays of indice 0 in this function
}

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

myfunction() {
  [ -z "$ZSH_VERSION" ] || emulate -L ksh
  # ksh code more likely to work here
}

Имея это в виду, и вы готовы отказаться от поддержки yash и ksh88 и более старые версии pdksh производных, и пока вы не пытаетесь создавать разреженные массивы, вы должны иметь возможность последовательно использовать:

  • a [0] = foo
  • a = (foo bar) (но не a = () )
  • "$ {a [#]}" , "$ {a [@]}" , "$ {a [0]}"

в тех функциях, у которых есть emulate -L ksh , а пользователь zsh по-прежнему использует свои массивы, как правило, способом zsh.

12
27.01.2020, 19:57

Вы можете использовать eval , чтобы попробовать синтаксис массива:

is_array_support() (
  eval 'a=(1)'
) >/dev/null 2>&1

if is_array_support; then
  echo support
else
  echo not
fi
7
27.01.2020, 19:57

Теги

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