Один из способов сделать это — использовать цикл while IFS=, read -r
в CSV-документе здесь -.
#! /bin/sh -
while IFS=, read <&3 -r ip key; do
ssh -i "$key" "$ip" << ENDSSH
...
ENDSSH
done 3<< ENDCSV
10.0.0.1,p1.pem
10.0.0.2,p2.pem
ENDCSV
Тогда вам даже не нужно требовать от пользователей установки bash. Если переносимость не является проблемой, вы можете использовать вместо этого zsh
, который поддерживает цикл по более чем одной переменной.
#! /usr/bin/env zsh
for ip key (
10.0.0.1 p1.pem
10.0.0.2 p2.pem
) ssh -i $key $ip << ENDSSH
...
ENDSSH
Поскольку вы используете bash, вы можете использовать ассоциативные массивы:
#!/usr/bin/env bash
declare -A ip_list=(["ip_1"]="mykey1.pem" ["ip_2"]="mykey2.pem")
for ip in "${!ip_list[@]}"; do
ssh -i "${ip_list[$ip]}" myuser@"$ip" << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done
Обратите внимание, что ассоциативные массивы, в отличие от обычных массивов с индексами, не сохраняются в определенном порядке, поэтому нет гарантии, что ip_1
будет обработан раньше ip_2
.
Если вам нужно использовать простую, совместимую с POSIX оболочку, создайте файл с файлами ip и ключей, по одному на строку:
$ cat iplist.txt
ip1 mykey1.pem
ip2 mykey2.pem
Затем используйте этот скрипт:
#!/bin/sh
while read -r ip key; do
ssh -i "$key" myuser@"$ip" << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done
И запустите его с помощью:
sh /path/to/script < /path/to/iplist.txt
Но если вы пойдете по этому пути, подход Стефана лучше.
Ваш исходный скрипт можно сделать немного более переносимым с помощью set
встроенного -, а также объединить ip и ключ в одну строку, разделенную двоеточием. Позже мы можем использовать удаление префикса и суффикса для извлечения соответствующей записи
#!/usr/bin/env bash
# Set positional parameters
# Example ip addresses
set -- 192.168.0.1:mykey1 192.168.1.1:mykey2
# iterating without specifying 'in' assumes positiona parameters
for host; do
ssh -i ${host##*:}.pem myuser@${host%%:*} << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done