비대화형 런타임 bash 테스트 오류 결과

비대화형 런타임 bash 테스트 오류 결과

재부팅이 필요할 때 스크립트를 통해 일부 Ubuntu 서버를 다시 시작해 보았습니다.

Bash에서 비대화형 명령으로 테스트를 실행하면 파일이 /var/run/reboot-required존재하더라도 재부팅이 필요하지 않다는 결과를 얻습니다.

usera@client:~$ ssh server02 bash -c 'test -f /var/run/reboot-required && echo sudo reboot || echo "$(hostname): no reboot required"'
server02: no reboot required

SSH를 통해 동일한 서버에 로그인하고 수동으로 테스트를 실행하면 올바른 결과를 얻습니다 sudo reboot.

usera@client:~$ ssh server02
Last login: Tue Jun 14 08:03:00 2022 from 146.140.16.1
usera@server02:~$ test -f /var/run/reboot-required && echo sudo reboot || echo "$(hostname): no reboot required"
sudo reboot
usera@server02:~$ bash -c 'test -f /var/run/reboot-required && echo sudo reboot || echo "$(hostname): no reboot required"'
sudo reboot

올바른 결과를 얻으려면 무엇을 변경해야 합니까?

답변1

나는 이것이 SSH가 명령을 전달하는 방식 때문이라고 확신합니다.철사원격 측에서는 가져온 모든 인수를 연결하고 공백으로 연결한 다음 원격 셸이 이를 구문 분석하고 실행하도록 하여 이를 수행합니다.

생각해 보세요. ssh somehost ls -l /etc/passwd와 동일하게 작동합니다. 셸 명령줄에서 직접 실행하는 것과 달리 존재하지 않는 이상한 이름의 명령에 대해 오류를 표시하지 않습니다 ssh somehost 'ls -l /etc/passwd'.'ls -l /etc/passwd'

그래서,

ssh somehost bash -c 'test whatever || echo no'

명령줄에

bash -c test whatever || echo no

Bash는 로 설정된 test명령 실행을 시작합니다 . 인수 없이 실패하므로 실행됩니다. 다음과 같은 것을 시도해 볼 수도 있습니다 . 이는 원격 홈 디렉토리에서만 작동해야 합니다.$0whatevertest|| echossh somehost bash -c 'ls -l /etc/passwd'ls

따라서 중간 쉘을 사용하지 마십시오.

ssh server02 'test -f /etc/passwd && echo passwd exists || echo "$(hostname): passwd does not exist"'

아니면 다음과 같은 일을 할 수도 있습니다.

ssh server02 'bash -c "test -f /etc/passwd && echo yes || echo \"\$(hostname): no\"'

그러나 다른 따옴표 붙은 문자열을 중첩하고 해당 문자열이 보유한 확장을 실행하는 가장 안쪽 셸인지 확인하려는 경우 따옴표가 까다로워집니다. 원격으로 두 셸 모두에서 동일한 결과를 제공하므로 중요하지 않지만 $(hostname)보다 일반적인 경우에는 참조 지옥이 있습니다. 이와 같은 복잡한 상황에서는 원격으로 파일을 생성하고 거기에서 스크립트를 실행하는 것이 훨씬 쉬울 것입니다.

이것은 기본적으로 다음과 같은 질문입니다.인용된 SSH 명령.

당신은 또한 볼 수 있습니다SSH를 통해 `sh -c` 스크립트 실행(매개변수를 안전하고 정상적으로 전달)복잡한 명령을 전달하기 위한 기타 솔루션원격 사용자의 로그인 셸을 모르고 SSH를 통해 임의의 간단한 명령을 어떻게 실행할 수 있습니까?잠재적으로 알려지지 않은 원격 로그인 셸과 관련된 드문 경우입니다.

관련 정보