Мне кажется, это идеальная возможность нанять вас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
в одной и той же командной строке, согласно справочной странице, включенной в xfsprogs
4.5.something.
Решение, которое я применил проще, приняв во внимание все ваши предложения, за которые я благодарен, состоит в том, чтобы использовать индексы массива следующим образом:
#!/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
Чтобы выполнить итерацию по парным -элементам двух массивов, а не по всем комбинациям элементов из массивов, выполните цикл по одному и вытягивайте следующий элемент из другого на каждой итерации.
Это упрощается (с точки зрения синтаксиса ), если второй список сохраняется в списке позиционных параметров, на котором мы можем использовать 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
Оба приведенных выше фрагмента кода предполагают, что текущий каталог будет домашним каталогом пользователя, с которым мы подключаемся.