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
두 번째 줄은 가독성을 위해 출력하기 전에 서버 이름을 인쇄합니다.
그것이 나에게 주는 것은 행복이 아니지만,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
스크립트와 인간 모두에게 좋습니다.
나중에 포트를 변경하면 한 곳에서 수정할 수 있습니다.
와일드카드도 사용할 수 있으므로 모든 시스템에 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