로컬 컴퓨터에 원격 master
컴퓨터에 대한 SSH 세션을 만든 다음 다른 내부 SSH 세션을 master
원격 slaves
에서 각각의 원격 컴퓨터로 만들고 2 개의 명령을 실행합니다. 즉, 특정 디렉토리를 삭제하고 다시 만듭니다.
로컬 머신에는 마스터에 대한 비밀번호가없는 SSH가 있고 마스터에는 슬레이브에 대한 비밀번호가없는 SSH가 있습니다. 또한 모든 호스트 이름은 .ssh/config
로컬 / 마스터 머신에 있으며 슬레이브의 호스트 이름은 slaves.txt
로컬에 있으며 거기서 읽습니다.
그래서 내가하고 일하는 것은 이것입니다 :
username="ubuntu"
masterHostname="myMaster"
while read line
do
#Remove previous folders and create new ones.
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition""
ssh -n $username@$masterHostname "ssh -t -t $username@$line "mkdir -p EC2_WORKSPACE/$project Input Output Partition""
#Update changed files...
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""
done < slaves.txt
이 클러스터는 Amazon EC2에 있으며 각 반복마다 6 개의 SSH 세션이 생성되어 상당한 지연을 유발하는 것으로 나타났습니다. 더 적은 SSH 연결을 얻기 위해이 3 개의 명령을 1로 결합하고 싶습니다. 그래서 처음 두 명령을
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""
그러나 예상대로 작동하지 않습니다. 첫 번째 ( rm -rf Input Output Partition
) 를 실행 한 다음 세션을 종료하고 계속됩니다. 어떡해?
답변
&&
이것이 논리 연산자 라고 생각하십시오 . 그것은 수행 하지 평균 “이 명령을 수행”은 “다른 성공했을 경우이 명령을 실행”을 의미한다.
즉, rm
명령이 실패하면 (세 개의 디렉토리 중 하나가 존재하지 않으면 발생 함) mkdir
실행되지 않습니다. 원하는 동작처럼 들리지 않습니다. 디렉토리가 존재하지 않는 경우 디렉토리를 작성하는 것이 좋습니다.
사용하다 ;
세미콜론 ;
은 명령을 구분하는 데 사용됩니다. 명령은 순차적으로 실행되어 다음을 계속하기 전에 각 명령을 기다리지 만 성공 또는 실패는 서로 영향을 미치지 않습니다.
내부 인용문 탈출
다른 따옴표 안의 따옴표는 이스케이프되어야합니다. 그렇지 않으면 추가 끝점과 시작점을 만듭니다. 당신의 명령 :
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""
된다 :
ssh -n $username@$masterHostname "ssh -t -t $username@$line \"rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input OutputPartition\""
이스케이프 된 따옴표가 없기 때문에 현재 명령을 실행해야합니다.
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition
성공하면 :
mkdir -p EC2_WORKSPACE/$project Input Output Partition"" # runs on your local machine
구문 강조 표시는 여기에서 전체 명령을 빨간색으로 표시합니다. 이는 전체 명령이 ssh에 전달되는 문자열임을 의미합니다. 로컬 머신을 확인하십시오. 디렉토리 Input
Output
와 Partition
이것을 실행 한 위치 가있을 수 있습니다 .
답변
OpenSSH 의 점프 박스 멀티플렉싱에서 항상 정의 할 수 있습니다
멀티플렉싱은 단일 회선 또는 연결을 통해 둘 이상의 신호를 전송하는 기능입니다. 멀티플렉싱을 사용하면 OpenSSH는 매번 새 세션을 생성하지 않고 여러 개의 동시 SSH 세션에 기존 TCP 연결을 재사용 할 수 있습니다.
SSH 멀티플렉싱의 장점은 새 TCP 연결을 만드는 오버 헤드가 제거된다는 것입니다. 기계가 수용 할 수있는 전체 연결 수는 유한 자원이며 일부 기계에서는 다른 기계보다 한계가 더 눈에 띄며로드와 사용량에 따라 크게 다릅니다. 새 연결을 열 때 상당한 지연이 있습니다. 멀티플렉싱을 사용하여 새 연결을 반복적으로 여는 활동을 크게 가속화 할 수 있습니다.
그것을 위해 /etc/ssh/ssh_config
:
ControlMaster auto
ControlPath ~/.ssh/controlmasters/ssh_mux_%h_%p_%r
ControlPersist 30m
이러한 방식으로 다음 30 분 동안 동일한 서버에 대한 연속 연결은 이전 ssh 연결을 재사용하여 수행됩니다.
머신 또는 머신 그룹에 대해이를 정의 할 수도 있습니다. 제공된 링크에서 가져 왔습니다.
Host machine1
HostName machine1.example.org
ControlPath ~/.ssh/controlmasters/%r@%h:%p
ControlMaster auto
ControlPersist 10m
답변
모든 명령을 “마스터”서버의 별도 스크립트에 넣을 수 있습니다.
마스터 스크립트
#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"
그런 다음 SSH 스크립트에서 다음과 같이 호출하십시오
.SSH 스크립트
username="ubuntu"
masterHostname="myMaster"
while read line
do
ssh -n $username@$masterHostname "ssh -t -t $username@$line < /path/to/masterscript.sh"
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""
done < slaves.txt
또는
모든 파일이 초기 시스템에 있어야하는 경우 다음과 같이 할 수 있습니다.
스크립트 1
script2="/path/to/script2"
username="ubuntu"
while read line; do
cat $script2 | ssh -t -t $username@line
done < slaves.txt
script2
#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"
rsync --delete -avzh "/EC2_NFS/$project/* EC2_WORKSPACE/$project"
ssh 스크립트
script1="/path/to/script1"
username="ubuntu"
masterHostname="myMaster"
cat $script1 | ssh -n $username@$masterHostname
답변
몇 시간 전, 나는 다른 답변 (이 대답은 본질적으로 같은 제어 소켓을 사용하는 조합 추천처럼 제어 소켓을 사용하는 기회 있었다 이 대답 과 같은 스크립트 이 답변을 ).
유스 케이스는 해킹 authorized_keys
이었습니다. 대상 사용자의 일정이 예약 된 작업으로 주기적으로 덮어 쓰였고 해당 파일에 무언가를 추가하는 데 필요한 빨간색 테이프를 거치지 않고 신속하게 테스트하고 싶었습니다. 그래서 필요에 따라 해당 파일에 키를 추가하고 테스트를 실행하고 루프를 취소하는 while 루프를 설정했습니다. 그러나 예약 된 작업이 파일을 덮어 쓸 작은 창이 있으며 루프가 계속 작동 sleep
합니다. 따라서 처음에 제어 소켓을 설정하면 나중에 문제없이 스크립트 SSH를 사용할 수 있습니다.
#! /bin/bash -xe
. "${CONFIG_DIR}/scripts/setup-ssh.sh"
# Build and test
export TEST_LABEL="${_started_by}-${BUILD_TAG%-BUILD*}"
#...
xargs --arg-file test-list \
--no-run-if-empty \
--process-slot-var=NUM \
--max-procs=${#SERVERS[@]} \
--max-args="${BATCH_SIZE:-20}" \
"${CONFIG_DIR}/scripts/run-test.sh"
어디에 setup-ssh.sh
:
export SSH_CONFIG="${CONFIG_DIR}/scripts/.ssh-config"
mapfile -t SERVERS < "${CONFIG_DIR}/scripts/hosts"
for SERVER in "${SERVERS[@]}"
do
while ! ssh -F "${SSH_CONFIG}" "${SERVER}" -fnN; do sleep 1; done
scp -F "${SSH_CONFIG}" "${CONFIG_DIR}/scripts/ssh-script.sh" "${SERVER}":"${TEST_LABEL}.sh"
done
그리고 .ssh-config
:
Host test-*
User test
StrictHostKeyChecking no
ControlMaster auto
ControlPath /tmp/ssh-%h-%p-%r
그리고 run-test.sh
:
mapfile -t TEST_SERVERS < "${CONFIG_DIR}/scripts/hosts"
ssh -F "${SSH_CONFIG}" "${TEST_SERVERS[$NUM]}" "./${TEST_LABEL}.sh"
순서는 다음과 같습니다.
- 기본 스크립트 (처음 표시됨) 소스
setup-ssh.sh
. setup-ssh.sh
모든 서버에 제어 소켓 설정이 설정 될 때까지 서버를 사용 중으로 반복합니다.hosts
파일은 단순히 한 줄에 서버 호스트 이름 하나를 나열합니다.- 제어 소켓을 지정하는 구성은에만 있기 때문에을
${CONFIG_DIR}/scripts/.ssh-config
사용하여 파일을 지정하지 않으면-F
SSH 연결에서 사용하지 않습니다. 따라서F
옵션을 사용하여 필요한 경우에만 제어 소켓을 사용할 수 있습니다. - 설치 스크립트는 테스트 실행 스크립트를 서버에 복사합니다. 실행 스크립트 자체에는 많은 명령이 포함되어 있으며 실행 스크립트를 복사했기 때문에 SSH에 대한 추가 인용 계층에 대해 걱정할 필요가 없습니다 (그리고 언제 확장되는지 파악하기위한 추가인지 오버 헤드).
- 그런 다음 기본 스크립트는
xargs
실행 작업이 끝나는 즉시 새 작업을 시작하여 서버에 작업 부하를 분산시키는 데 사용 됩니다.