SSH 세션 내의 SSH 동안 여러 명령


10

로컬 컴퓨터에 원격 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) 를 실행 한 다음 세션을 종료하고 계속됩니다. 어떡해?


3
명령에 이러한 간접적 인 명령 대신 -J점프 호스트를 정의 하는 옵션을 사용할 수 있습니다 .
Hauleth

답변:


15

&&이것이 논리 연산자 라고 생각하십시오 . 그것은 수행 하지 평균 "이 명령을 수행"은 "다른 성공했을 경우이 명령을 실행"을 의미한다.

즉, 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 OutputPartition이것을 실행 한 위치 가있을 수 있습니다 .


나는 당신의 요점을 이해합니다. 내가 혼동 한 부분은 세미콜론이었습니다. 동시에 하나 이상의 명령을 실행한다고 생각했기 때문에 사용하지 않았습니다.
mgus

세미콜론으로 인해 명령이 동시에 실행되지는 않습니다. 명령 실행에 대한 참조로 여기 를 참조 하십시오 . &원인 명령은 다음에 이동하기 전에 끝까지 기다렸다 습관 수단 그는 배경, INT 실행합니다.
Centimane

10

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

그 흥미 롭군요! 주어진 연결에 대해 명시 적으로 켜고 끄는 방법이 있습니까? 이 하나의 유스 케이스에 대한 모든 SSH 연결을 대폭 변경하는 것은 과도한 것으로 보입니다. 보다 정확한 방식으로 사용할 수 있습니까? 특정 연결 만 멀티플렉싱을 시작하려면?
Centimane

@Centimane 네, 답변을 업데이트
Rui F Ribeiro

1
소켓을 읽기 가능한 세계가 아닌 사용자의 집에 두는 것이 좋습니다 /tmp/.
heemayl

@heemayl 좋은 지적입니다. 컴퓨터에있을 때 편집하겠습니다.
Rui F Ribeiro

또한 @RuiFRibeiro에있어서, 모양 man ssh, ControlPath, ControlMasterControlPersist통과 유효한 옵션이다 ssh하여 명령 -o. 더 정확한 유스 케이스가 될 수 있으며 ssh스크립트 의 첫 번째에서 멀티플렉싱을 설정 하고 다른 스크립트를 위해 재활용하지만 성능 저하를 피하십시오. "새 연결을 열 때 상당한 지연이있다"는 점을 고려할 때 3 개의 SSH 연결에 대한 다중화 VS의 벤치 마크가 무엇인지 궁금합니다.
Centimane

4

모든 명령을 "마스터"서버의 별도 스크립트에 넣을 수 있습니다.

마스터 스크립트

#!/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

1

몇 시간 전, 나는 다른 답변 (이 대답은 본질적으로 같은 제어 소켓을 사용하는 조합 추천처럼 제어 소켓을 사용하는 기회 있었다 이 대답 과 같은 스크립트 이 답변을 ).

유스 케이스는 해킹 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사용하여 파일을 지정하지 않으면 -FSSH 연결에서 사용하지 않습니다. 따라서 F옵션을 사용하여 필요한 경우에만 제어 소켓을 사용할 수 있습니다.
  • 설치 스크립트는 테스트 실행 스크립트를 서버에 복사합니다. 실행 스크립트 자체에는 많은 명령이 포함되어 있으며 실행 스크립트를 복사했기 때문에 SSH에 대한 추가 인용 계층에 대해 걱정할 필요가 없습니다 (그리고 언제 확장되는지 파악하기위한 추가인지 오버 헤드).
  • 그런 다음 기본 스크립트는 xargs실행 작업이 끝나는 즉시 새 작업을 시작하여 서버에 작업 부하를 분산시키는 데 사용 됩니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.