SSHを介して一連のサーバーでコマンドを実行しようとしています。最近、インターネットスキャナを避けるためにSSHポートを変更しましたが、これはスクリプトを壊しました。 forループの各user@serverエントリに対して異なるポートを指定する「簡単な方法」を知っている人はいますか?
for i in '[email protected] -p 12345' '[email protected] -p 54321'
do printf "\e[%sm%s\e[00m\n" 32 $i
ssh $i crontab -l
done
2行目は、読みやすくするために出力する前にサーバー名を印刷します。
それが私に与えるのは幸せではありませんが、ssh: Could not resolve hostname server1.domain1.com -p 12345: Name or service not known
以前は、すべてのポートがデフォルト値22のときに機能し、指定する必要はありませんでした。
答え1
バージョン7.7以降、OpenSSH ssh
(およびそのscp
同僚sftp
)はURI形式のターゲットを受け入れます。必要に応じて、ポート番号をURIの一部として指定できます。たとえば、「ssh://someuser@somehost:42」はポート 42 に接続されます。シェルに関する限り、URIの利点は、焦点を合わせる単一の文字列であることです。だからあなたはこれを行うことができます:
for i in 'ssh://[email protected]:12345' 'ssh://[email protected]:54321'
do printf ...
ssh "$i" ...
done
SSH URIの一般的な形式は「ssh://user@host:port」です。 「user」と「port」の両方の部分はオプションであり、値を指定する必要がない場合は、「@」または「:」の句読点で省略できます。
答え2
正しい方法は、すべての接続ですべてを指定するのではなく、構成に保存することです。
あなたが持つことができる場所~/.ssh/config
:
Host server1.domain1.com # When connecting to this
User user1 # Use this user
Port 12345 # with this port
Host serv2 # We can also use a different, internal, name
Hostname server1.domain1.com # The actual hostname or IP it will use to connect
User user2
Port 54321
これにより、正しいことがssh server1.domain1.com
行われます™各コンピュータで使用されているユーザー名またはポートを覚えておく必要はありません。ssh serv2
スクリプトと人間の両方に最適です。
後でポートを変更すると、1 か所で変更できます。
ワイルドカードも使用できるため、すべてのシステムでsshdがポート1234をリッスンしている場合は、個別にリストすることなくすべてを一致domain1.com
させることができます。Host *.domain1.com
答え3
for
複数の変数を繰り返すことができるループの場合、変数を引用せずにすでにzsh
構文を使用しています。zsh
# zsh
for colour host port (
green [email protected] 12345
blue [email protected] 54321
) {
print -rP "%F{$colour}%B$host:$port%b%f"
ssh -p $port $host 'crontab -l'
}
パラメータリストを繰り返すには、多次元配列を含むシェルを使用できますksh93
。たとえば、次のようになります。
# ksh93
ssh_args=(
(-p 12345 [email protected])
(-p 54321 [email protected])
)
for i in "${!ssh_args[@]}"}; do
printf '\e[1;32m%s\e[m\n' "${ssh_args[i][2]}"
ssh "${ssh_args[i][@]}" 'crontab -l'
done
または、文字列に表示されないことがわかっている文字を使用して、パラメータに関連付けられた文字列を含む配列要素を作成して分離します。zsh
確かに分裂的な性格です${(s[x])var}
。
kshとbashも動作しますが、拡張機能を参照することを忘れたときに暗黙的に呼び出される薄暗い分割+globを介してのみ機能します。次のように使用できます。
# ksh93 / bash / yash / mksh / zsh --emulate ksh
ssh_args=(
-p:12345:[email protected]
-p:54321:[email protected]
)
IFS=:; set -o noglob # tune your split+glob operator by specifying
# the separator and disabling globbing
for joined_args in "${ssh_args[@]}"; do
args=( $joined_args ) # invoke split+glob
printf '\e[1;32m%s\e[m\n' "${args[2]}"
ssh "${args[@]}" 'crontab -l'
done
要素を区切るのではなく空白を使用しますが、グローバルを:
設定または無効にしないことを除いて、デフォルトではメソッドによって実行されます。$IFS
$i
分割しないという事実は、$IFS
空の文字列に設定するか、コードがbashの代わりにzshによって実行されるという事実として説明できます。ここで、分割やワイルドカードの指定は、引数拡張時に暗黙的には行われません。
zshでIFSを分割したい場合は、ワイルドカードが必要な場合は$=var
代わりに使用してください。 bashはzshに似ています。したがって、zshには次のものが必要です。$var
$~var
$var
$=~var
# zsh
ssh_args=(
-p:12345:[email protected]
-p:54321:[email protected]
)
IFS=:
for joined_args in $ssh_args; do
args=( $=joined_args ) # split on $IFS or better:
args=( ${(s[:])joined_args} ) # split explicitly on : without
# having to touch $IFS
print -rP "%F{green}%B$host[-1]%b%f"
ssh $args 'crontab -l'
done
可能な移植可能なアプローチsh
は、次のように書くことです。
# sh / bash / dash / ksh / yash / zsh...
while IFS=' ' read<&3 host port; do
{
printf '\33[1;32m%s\e[m\n' "$host:$port"
ssh -p "$port" "$host" 'crontab -l'
} 3<&-
done 3<< 'EOF'
[email protected] 12345
[email protected] 54321
EOF
次のように値の前にバックスラッシュを追加して、値に区切り文字(ここではスペース)を含めることができる-r
オプションを省略します。read
john\ doe@server1 1234
ただし、他の方法とは異なり、これらの値に改行文字を含めることはできません(ユーザー、ホスト、サービス名、またはポート番号に問題がない可能性があります)。
すべてのリストの要素数が同じで$n
制限がない別の移植可能な循環リストは、すべての要素を位置引数に格納してループ内で繰り返すことですwhile [ "$#" -ge "$n" ]; do something with "$1" "$2"...; shift "$n"; done
。だからここにあります:
# sh / bash / dash / ksh / yash / zsh...
eval "$(
printf "fg_%s='\33[3%sm' " \
black 0 red 1 green 2 yellow 3 \
blue 4 magenta 5 cyan 6 white 7
printf "bg_%s='\33[4%sm' " \
black 0 red 1 green 2 yellow 3 \
blue 4 magenta 5 cyan 6 white 7
printf "attr_%s='\33[%sm' " \
reset '' bold 1 dim 2 italics 3 underline 4 \
blink 5 standout 7 reverse 7 secure 8
)"
set -- \
"$fg_green$attr_bold" [email protected] 12345 \
"$bg_blue$fg_white" [email protected] 54321
while [ "$#" -ge 3 ]; do
colour=$1 host=$2 port=$3
printf '%s\n' "$colour$host:$port$attr_reset"
ssh -p "$port" "$host" 'crontab -l'
shift 3
done
答え4
複数のホストでpdshを使用します。クラスタホスト数が多いデータセンターで広く使用されています。
pdshドキュメントから..
ホストh0、h1、h2ではユーザ「foo」で実行し、ホストh3、h5ではユーザ「bar」として実行します。
pdsh -w foo@h[0-2],bar@h[3,5]
https://code.google.com/archive/p/pdsh/wikis/UsingPDSH.wiki
Ángelが述べたように、このツールはSSH設定ファイルで動作します。
以下の完全な例..
~/.ssh/config
Host server1
Hostname server1
User user1
Port 12345
Host server2
Hostname server2
User user2
Port 54321
今すぐ実行してください。
pdsh -w server1,server2 crontab -l