터미널을 떠날 때까지 기다리는 대신 SSH를 통해 명령을 보내는 스크립트

터미널을 떠날 때까지 기다리는 대신 SSH를 통해 명령을 보내는 스크립트

이더넷 스위치를 통해 여러 대의 컴퓨터가 네트워크로 그룹화되어 있습니다. 이들 모두는 Fedora 서버를 실행하며 인터넷에 연결되어 있습니다.

나에게 필요한 것은 다음과 같은 스크립트입니다.

  • 목록의 모든 노드에 연결
  • 명령 또는 명령 패키지 보내기(예: 전체 업데이트 또는 특정 패키지 설치)
  • 연결을 닫지만 대상 시스템에서 명령 실행을 유지합니다.

현재 스크립트는 다음과 같습니다.

#!/bin/bash
targets_username='username'
targets_password='password'
targets_IPs=( 192.168.1.100 192.168.1.101 192.168.1.102 )

SCRIPT1='dnf update -y'
SCRIPT2='dnf update -y && poweroff'

for IP in ${targets_IPs[@]}; do
        export SSHPASS=$targets_password
        script="nohup sh -c \"( ( $SCRIPT1 & > /dev/null) &)\""
        echo $IP
        echo $script
        sshpass -e ssh -o StrictHostKeyChecking=no -l $targets_username@$IP $script
done

문제는 다음과 같습니다

  • 연결이 닫히면 명령 실행이 중지됩니다.
  • 예를 들어, 명령에 추가 명령이 포함되어 있거나 호스트 컴퓨터로 전달되는 경우 reboot해당 poweroff호스트 컴퓨터에서 스크립트가 시작됩니다.

이 문제를 어떻게 해결하나요?

게시물을 찾았습니다여기,여기그리고여기가능한 해결책에 대해 설명했지만 작동하지 않습니다.

답변1

이러한 유형의 통화는 올바른 위치에서 사물을 평가하고 있는지 확인해야 하기 때문에 항상 까다롭습니다. 즉. 올바른 수의 백슬래시를 추가하십시오.

당신이 그렇게한다면

script="sh -c \"nohup sh -c '$SCRIPT1' > /dev/null 2>&1 & \""
sshpass -e ssh -n -o StrictHostKeyChecking=no -l $targets_username $IP "$script"

원하는 대로 작동해야 합니다( -nstdin을 닫아 두십시오). timeSSH 연결 앞에 sshpass 명령을 추가하거나 실행하고 netstat열린 $SCRIPT1연결을 확인하여 SSH 연결이 실제로 닫혔는지 확인할 수 있습니다 .

stdin, stdout 및 stderr이 모두 닫혀 있는지 확인해야 합니다. 그렇지 않으면 ssh프로세스가 백그라운드로 전환되더라도 닫힐 ​​때까지 기다려야 합니다.

위의 방법이 작동하지 않으면 명령줄 인수에 대한 추가 평가가 수행될 수 있습니다 sshpass. 또한 작은따옴표를 사용하면 원격 측까지 $SCRIPT1내부 변수(예: 쉘 변수)의 확장이 지연됩니다 .$SCRIPT1

이제 이 접근 방식을 사용하여 작업을 수행할 수 있더라도 Ansible(https://docs.ansible.com/ansible/latest/index.html). 백그라운드 접근 방식을 사용하면 명령이 성공했는지 또는 실행이 완료되었는지 수동으로(또는 다른 개발된 도구를 사용하여) 확인해야 합니다.

관련 정보