Два массива во вложенном цикле for через ssh приводят к нежелательному подключению -пользовательские перестановки

Мне кажется, это идеальная возможность нанять васxargs(или GNU Parallel):

getent passwd \
  | awk -F: '$3>=1000 && $1!="nfsnobody" {print $1}' \
  | xargs -I{} \
      echo xfs_quota -x -c \"limit bsoft=5g bhard=6g {}\" /home

# output:
# xfs_quota -x -c "limit bsoft=5g bhard=6g userone" /home
# xfs_quota -x -c "limit bsoft=5g bhard=6g usertwo" /home

Преимущество использования xargsили parallelзаключается в том, что вы можете просто удалить echo, когда будете готовы выполнить команду по-настоящему (, возможно, заменив ее на sudo, если необходимо ).

Вы также можете использовать опции -p/--interactive(этих утилит, последняя — GNU -только )или--dry-run(parallelтолько опции ), чтобы получить подтверждение перед запуском каждой из них или просто посмотреть что будет запускать до того, как вы его запустите.

Общий метод, использованный выше, должен работать на большинстве Unix-систем и не требует -особых xargsопций GNU. Двойные кавычки do необходимо «экранировать», чтобы они отображались буквально в выводе. Обратите внимание, что «строка замены» {}в xargs -I{}может быть любой, какой вы предпочитаете, а -Iподразумевает-L1(выполнение одной команды для каждой входной строки, а не группирование их ).

GNU Parallel не требует опции -I({}— это строка замены по умолчанию ), которая дает вам мгновенный бонус в виде параллельного выполнения многих заданий, даже если вы не хотите утруждать себя изучением любыеизегодругиеособенности .

В качестве примечания, я даже не уверен, что опция xfs_quota's -cдолжна использоваться вот так,хотя у меня нет файловых систем XFS для тестирования. У вас может даже не быть необходимого для работы со строкой в ​​кавычках в первую очередь (, если только вы не ожидаете, что имена пользователей содержат пробелы, что, я думаю, возможно ), поскольку похоже, что вы можете указать несколько параметров -cв одной и той же командной строке, согласно справочной странице, включенной в xfsprogs4.5.something.

0
03.12.2021, 15:46
2 ответа

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

#!/bin/bash
EXTENSIONS='/home/bi/.local/share/gnome-shell/extensions'
IPS=(
'192.168.122.60'
'192.168.122.92'
'192.168.122.93'
)
USERS=(
'mf'
'lf'
'qf'
)

echo -e "sync my extensions to my nodes \c"; read
for i in ${!IPS[*]}; do
  rsync -rt --delete --info=progress2,stats2 \
  -e ssh -tt \
  $EXTENSIONS/ \
  ${USERS[$i]}@${IPS[$i]}:/home/${USERS[$i]}/.local/share/gnome-shell/extensions/
done
0
03.12.2021, 17:20

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

Это упрощается (с точки зрения синтаксиса ), если второй список сохраняется в списке позиционных параметров, на котором мы можем использовать shiftдля удаления элементов:

#!/bin/bash

list1=( element1 element2 element3 )
list2=( thing1   thing2   thing3   )

# Assign the second list to
# the list of positional parameters:
set -- "${list2[@]}"

# Loop over the first list and pull out
# the next element of the second list
# in each iteration, to pair up the elements:
for element in "${list1[@]}"; do
    printf 'Pair: %s %s\n' "$element" "$1"
    shift
done

Выход:

Pair: element1 thing1
Pair: element2 thing2
Pair: element3 thing3

Применение этого к вашему конкретному примеру:

#!/bin/bash

node_servers=(
    '192.168.122.60'
    '192.168.122.92'
    '192.168.122.93'
)
node_users=(
    'mf'
    'lf'
    'qf'
)

extension_path=.local/share/gnome-shell/extensions

set -- "${node_users[@]}"

for server in "${node_servers[@]}"; do
    rsync -ai --delete ~bi/"$extension_path"/ "$1@$server:$extension_path"
    shift
done

Однако, поскольку исходный список серверов уже содержит имена пользователей, второй список нам не нужен.:

#!/bin/bash

node_servers=(
    'mf@192.168.122.60'
    'lf@192.168.122.92'
    'qf@192.168.122.93'
)

extension_path=.local/share/gnome-shell/extensions

for server in "${node_servers[@]}"; do
    rsync -ai --delete ~bi/"$extension_path"/ "$server:$extension_path"
done

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

1
03.12.2021, 17:44

Теги

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