BASH Как использовать каждую строку файла в качестве входной переменной для цикла for - PullRequest
0 голосов
/ 25 марта 2020

У меня есть для l oop, который считает и вносит изменения на серверах. Каждый сервер имеет множество пользователей, и мне нужно выполнить несколько простых операций с учетной записью каждого пользователя. Независимо от того, что нужно сделать, мне нужно подсчитать пространство IP каждого сервера, и для каждого запуска l oop мне нужно использовать другое имя пользователя. users.txt содержит

usera
userb
userc

Мой l oop выглядит как

for (( counter=1; counter<99; counter++))
   do
   if [ $counter -lt 10 ];
   then
     ssh -o StrictHostKeyChecking=no user@server0${counter}.domain.com  mkdir /home/${user}/newdir
   else
     ssh -o StrictHostKeyChecking=no user@server${counter}.domain.com  mkdir /home/${user}/newdir
   fi
done

Но ни один из них не адресован пользователю $ для каждой строки, и я не уверен, как лучше подойти к нему. В идеале сценарий должен использовать:

ssh -o StrictHostKeyChecking=no user@server01.domain.com  mkdir /home/username/newdir

Спасибо за любую помощь или руководство, которое вы можете предложить.

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Осторожный ответ может выглядеть следующим образом:

readarray -t users <users.txt
printf -v cmd_q '/home/%q/newdir ' "${users[@]}"

for (( counter=0; counter<99; counter++ )); do
  printf -v counter_padded '%02d' "$counter"
  ssh "user@server${counter_padded}.domain.com" 'bash -s' <<<"mkdir -p -- $cmd_q"
done

Какие примечательные преимущества (и недостатки) это имеет?

  • Нам требуется bash 4.0 в локальной системе, для функции readarray. Это позволяет нам читать users.txt только один раз, заполняя массив "${users[@]}", который мы затем используем для генерации строки "$cmd_q", которая представляет собой версию нашего списка имен домашних каталогов в кавычках (подробнее об этом позже!)
  • При использовании строки формата %q гарантированно генерируется eval -защищенная строка в кавычках (когда удаленная оболочка предоставляется bash), поэтому некоторые джокеры говорят, что их имя пользователя $(rm -rf ~) выиграно это плохой день.
  • Нет никакой зависимости от нестандартной seq команды и запрета s sh объединять свои аргументы для генерации строки для передачи удаленной команде - вместо этого, мы передаем ему явный список аргументов, уже правильно указанных в кавычках.
  • Мы запускаем mkdir только один раз , а не отдельное время для имени каталога. (xargs способен на подобные вещи, но он отключает это поведение при использовании с -I{}).
  • $(...anything...) обычно медленный, и здесь мы его избегаем. Это не приведет к заметной разнице в производительности в данном конкретном случае (поскольку другой подход не обязательно помещал бы подстановку команд в тело l oop, и даже если бы это произошло, ssh намного медленнее по сравнению ), но это хорошая привычка, если у вас есть сценарий использования, в котором ваш l oop в противном случае может быть быстрым.

Если вам нужно, чтобы он работал с произвольно большой список имен пользователей, я бы изменил mkdir -p -- $cmd_q на printf '%s\0' $cmd_q | xargs -0 mkdir -p --, который может обрабатывать больше имен файлов, чем может поместиться в одной командной строке mkdir. (Поскольку printf является встроенной оболочкой, а не внешней командой, она не подчиняется ограничениям длины командной строки операционной системы).

0 голосов
/ 25 марта 2020

Вам просто нужен внутренний l oop. Вот один из способов, который использует xargs на удаленном сервере, передавая имена пользователей через stdin. (Также показано: использование printf для генерации списка имен серверов. Но учтите, что для этого необходимо, чтобы имя сервера не включало пробелы или какой-либо другой метасимвол оболочки)

for server in $(printf "user@server%02d.domain.com" $(seq 99)); do
  cat users.txt |
  ssh -o StrictHostKeyChecking=no $server \
      xargs -I{} mkdir "/home/{}/newdir"
done

Это работает, потому что команда, которую вы запускаете на удаленном сервере есть одна команда оболочки, но не совсем очевидно, как расширить ее до более сложной команды. Это также не самый эффективный способ, поскольку вы могли создать три (или столько же) каталогов с одним mkdir.

Если скрипт, который вы пытаетесь запустить на удаленном сервере, не слишком сложен, Вы можете обернуть его в sh -c или даже bash -c (если на удаленных хостах установлено bash и вы хотите воспользоваться его возможностями). Это работает для простых последовательностей команд, но правильное управление кавычками при наличии двухуровневых кавычек может быть настоящей головной болью.

...