Чтобы заменить пробел символом табуляции с помощью $ IFS
, вы можете использовать массив аргументов:
unset IFS
set a b c
IFS=$(printf \\t)
printf "%s\n" "$*"
Помните, что $ IFS
касается разделения - он содержит список символов оболочка использует для разделения раскрытий без кавычек в контекстах списка. Вы не можете использовать его для замены символов, за исключением особого случая специального параметра оболочки $ *
. Во всех остальных случаях его использование будет равняться null при выделении и ограничении определенных частей расширений оболочки без кавычек.
Я собрал "кластерный экран", чтобы сделать что-то подобное. Вы настраиваете файл /etc/clusters
так же, как и clusterssh
cluster1 host1 host2
cluster2 host3 host4
Затем у меня есть файл в /usr/local/bin/cs
(легкое копирование имени cssh : ), который выглядит так
#!/bin/bash
if [[ $# < 1 ]]
then
echo -e "Usage : $0 cluster [command]";
exit;
fi;
cluster=$(/bin/grep $1 /etc/clusters | sed -e 's/[^\ ]*\ //')
for s in $cluster; do
if [ -n "$2" ]
then
exec screen -t "$s" $s "$2";
else
exec screen -t "$s" $s;
fi
done;
Затем вы можете запустить
screen
cs clustername "optional command"
Это не так хорошо, как clusterssh, но это делает свою работу
Хорошо, нет, вам не нужно ssh
сначала на одну машину, а затем на другую. Даже на старых ssh
клиентах вам не пришлось бы делать такое.
У меня есть сценарий, похожий на ваш, хотя мне не интересно вводить одну и ту же команду на нескольких удаленных машинах.
Я спрашивал в своем комментарии, потому что вы задаете вопрос, не раскрывая подробностей. Итак, позвольте мне сделать несколько предположений. Я предполагаю, что на вашем локальном компьютере установлены Tmux и ssh
(клиент) в достаточно свежей версии. Если нет, например, потому что это Windows, используйте виртуальную машину.Я также предполагаю, что на вашем «удаленном ПК», который я буду называть хостом перехода , также установлен ssh
, и к нему можно подключиться из вашего локальный ящик и может достичь узлов кластера по очереди. У нас будут узлы кластера с node1
до node5
. Затем localbox
и jumphost
для двух других участвующих.
Теперь, когда нет терминологии, откройте эту ссылку на ssh_config (5) и переключитесь на нее, когда что-то из следующего станет неясным.
В вашей домашней папке на localbox
откройте .ssh / config
в вашем любимом текстовом редакторе. При необходимости создайте папку ~ / .ssh
. Затем введите следующее:
Host jumphost
HostName the.name.of.your.jumphost.tld
ForwardAgent yes # YMMV
Host node1 node 2 node3 node4 node5
ProxyCommand ssh -W %h:%p jumphost
Это говорит ssh
, что для подключения к node1
через node5
он должен сначала подключиться к jumphost
] и перенаправить / прокси на другой хост:
-W host: port
Запрашивает, чтобы стандартный ввод и вывод на клиенте был перенаправлен на хост на порт по защищенному каналу. Подразумевает-N
,-T
,ExitOnForwardFailure
иClearAllForwardings
. Работает только с протоколом версии 2.
Если у вас особенно старая версия ssh
на jumphost
(т. Е.не поддерживает -W
), , но установлен netcat ( nc
), вы можете заменить ProxyCommand
соответствующим образом на:
ProxyCommand ssh user@proxy nc %h %p 2> /dev/null
Теперь, когда указанные выше строки находятся в текстовом файле, добавьте по одной на каждый узел кластера, если необходимо:
Host node1 node1.cluster.domain.tld
HostKeyAlias node1.cluster.domain.tld
HostName 1.2.3.4 # you can give IPs
Предполагается, что имя node1
не является общедоступным и не известно вашему localbox
, и поиск по нему тоже невозможен. Но IP известен. HostKeyAlias
гарантирует, что позже вы сможете переключиться с HostName $ IP
на фактическое имя хоста. Я также стараюсь сократить псевдоним до node1.cluster
или аналогичного, на случай, если домены верхнего уровня когда-либо изменятся.
Итак, для node2
у нас может быть общедоступная запись DNS:
Host node2 node2.cluster.otherdomain.tld
HostKeyAlias node2.cluster
HostName node2.cluster.otherdomain.tld # ... or hostnames
И это позволяет вам теперь использовать (рекомендуется):
ssh node1
ssh node2
или (не рекомендуется):
ssh node`.cluster.domain.tld
ssh node2.cluster.otherdomain.tld
для подключения к ним узлы через узел перехода
. Он также позволяет подключиться к jumphost
, просто набрав ssh jumphost
.
Здесь важно понимать, что имя в строке Host
полностью не зависит от DNS-имени или IP-адреса, предоставил HostName
линия существует для этой строки Host
. Отступ IIRC является условным, но не обязательным.
Теперь единственное, что нужно решить на стороне SSH, - это аутентификация. Вы можете явно указать пользователя
в каждом из этих «блоков» для подключения с использованием альтернативного имени пользователя. И вам нужно решить, достаточно ли вы доверяете хосту jumphost
, чтобы активировать пересылку агента. Если вы этого не сделаете, вам придется создать ключ на jumphost
и сообщить его узлам кластера (в .ssh / authorized_keys
). Все остальное слишком часто запрашивает пароли.
Подводя итог всему, что было до сих пор, но чередуя идею, какой пользователь подключается и где:
Host jumphost
HostName the.name.of.your.jumphost.tld
User joe
Host node1 node 2 node3 node4 node5
ProxyCommand ssh -W %h:%p jumphost
User joseph
Host node1 node1.cluster.domain.tld
HostKeyAlias node1.cluster.domain.tld
HostName 1.2.3.4 # you can give IPs
User root
Host node2 node2.cluster.otherdomain.tld
HostKeyAlias node2.cluster
HostName node2.cluster.otherdomain.tld # ... or hostnames
...после ssh node1
подключится как joe @ jumphost
, чтобы перенаправить соединение root @ node1
. И после ssh node2
подключитесь как joe @ jumphost
, чтобы перенаправить соединение joseph @ node2
.
Таким образом, вы можете переопределить некоторые разделы файла конфигурации для каждого хоста.
Убрав часть SSH, давайте перейдем к параллельному запуску команд.
Вы должны иметь возможность управлять несколькими окнами xterm с помощью clusterssh
после того, как соответствующие окна xterm установили SSH-соединения с узлами кластера. Однако лично мне это показалось бы громоздким и довольно неинтуитивным.
У вас есть много вариантов. Для всех тех, которые я предлагаю, требуется только один терминал на вашем localbox
.
Вы можете использовать dsh
(танцор / распределенная оболочка) или блюдо (усердие / распределенная оболочка) для одного.
pssh
(parallel ssh
) - еще один вариант, но он основан на Python, поэтому его способность анализировать .ssh / config
- по опыту - может быть ограничивающей.
И последнее, но не менее важное: я бы порекомендовал вам Tmux . Сокращенно от термина «мультиплексор терминала», он попадает в ту же категорию, что и экран GNU
, но намного лучше, чем экран
.
Например, у меня есть ярлык для синхронизации панелей в одном окне Tmux с помощью Ctrl + a S (где Ctrl + a - мой предпочтительный префикс).
bind-key S set-window-option synchronize-panes \; display-message 'Toggled synchronize-panes'
Таким образом, вы могли открыть по одному SSH-соединению для каждой панели внутри одного окна Tmux и синхронизировать ввод для всех из них. Это позволит вам ввести команду на всех панелях в окне Tmux (окно по сути похоже на вкладку в терминологии Tmux) и сразу выполнить ее, нажав Enter .
Имейте в виду, однако, что это может работать нормально для небольшого количества удаленных узлов, но станет громоздким с большими числами. Так что, в конце концов, вы можете изучить одно из других решений, которые я рекомендовал.