SSH를 통해 중첩된 로컬 bash 기능 실행

SSH를 통해 중첩된 로컬 bash 기능 실행

다른 함수 등을 사용하는 여러 함수를 선언하는 이와 같은 스크립트가 있습니다.

#!/bin/bash

function a {
    ...
}

function b {
    ...
    a
    ...
}

...

또 다른 스크립트는 이 스크립트의 일부 기능을 사용합니다.

#!/bin/bash

do_something

source "/path/to/functional/script"

ssh user@host "$(typeset -f f_from_that_script); f_from_that_script"
...

그것이 말하는 문제는 environment: line N: another_f_from_that_script: command not found첫 번째 함수가 두 번째 함수를 내부적으로 사용한다는 것을 의미합니다.

function f_from_that_script {
    ...
    another_f_from_that_script
    ...
}

SSH를 통해 실행할 수 있도록 이러한 모든 기능을 정의하는 방법이 있습니까?

답변1

아니요, bash의 파서는 이러한 심층적인 구문 분석이 불가능합니다(호출된 함수의 이름이 런타임에 계산될 수 있기 때문에 종종 불가능합니다). 내가 아는 한, 이를 수행할 수 있는 타사 파서는 없지만 모든 경우에 이것이 이론적으로 불가능한 이유를 설명하는 논문이 있습니다. 나는 썼다답변그것에 대해.

개별 기능을 전달하는 대신 모든 기능이 포함된 전체 스크립트를 실행하는 것이 좋습니다. scp를 통해 스크립트를 임시 위치에 복사한 다음 sourcessh를 통해 복사하거나 ssh를 통해 전체 스크립트를 stdin으로 파이핑하여 이를 수행할 수 있습니다 .

정기적으로 SSH를 통해 복잡한 기능을 수행해야 하는 경우 SSH와 같은 보다 강력하고 공식적인 원격 관리 도구를 사용할 수 있습니다 ansible.

답변2

넌 언제나 합격할 수 있어모두원격 쉘에 대해 알려진 기능 정의:

#! /bin/bash -

do_something

source "/path/to/functional/script" || exit

{
  typeset -f # output all function definitions
  echo f_from_that_script
} | ssh user@host bash

sshdon은 전달한 명령을 해석하기 위해 로그인 셸을 host실행한다는 점에 유의하세요 . 이는 반드시 bash일 필요는 없습니다( 요즘 누가 이것을 로그인 셸로 사용할까요?).userbash

또한 bash구문은 다음에 따라 달라집니다.

  • 로캘(특히 LC_CTYPE범주: 문자 집합 및 문자 클래스)
  • extglob활성화된 옵션 세트(예: )
  • 배쉬 버전

따라서 bash 로케일과 버전이 로컬 호스트와 원격 호스트 간에 다르거나 기본 옵션을 변경하는 경우 잠재적인 문제에 유의하십시오.

답변3

다음을 통해 함수를 수동으로 로드할 수 있습니다.

. /path/to/functional/script

그런 다음 해당 스크립트를 현재 환경에 로드하고 두 번째 스크립트가 해당 기능에 액세스할 수 있습니다.

자동화하려면 ~/.bashrc 하단에 추가하면 됩니다.

. /path/to/functional/script

이렇게 하면 문제가 해결될 것입니다.

문제를 잘못 이해했거나 ssh 명령에 오류가 있는 것 같습니다.

내 테스트는 다음과 같습니다.

파일: function_source.sh

#!/bin/bash

function testcall {

echo "now here I am"

}

파일 do_something.sh

#!/bin/bash

source ./function_source.sh

echo -e "This is called from within the script:\r\n"
testcall
echo -e "End Script - Any further output is from the function call:\r\n\r\n"

스크립트 파일 do_something.sh는 function_source.sh의 소스 파일을 로드한 후 function_source.sh에서 testcall 함수를 호출합니다.

ssh %server% "./do_something.sh; testcall"

산출:

-ssh %server% "./do_something.sh; 테스트콜"

이는 스크립트 내에서 호출됩니다.

지금 난 여기 있어

스크립트 종료 - 추가 출력은 함수 호출에서 나옵니다.

bash: 1행: testcall: 명령을 찾을 수 없음

이제 function_source.sh is .bashrc를 참조하고 .bashrc 끝에 다음 줄을 추가하면 됩니다.

. ./function_source.sh

이제 동일한 명령을 실행합니다.

ssh %server% "./do_something.sh; testcall"

출력은 다음과 같습니다

-ssh %server% "./do_something.sh; 테스트콜"

이는 스크립트 내에서 호출됩니다.

지금 난 여기 있어

스크립트 종료 - 추가 출력은 함수 호출에서 나옵니다.

지금 난 여기 있어

.bashrc에서 파일을 참조하는 것이 작동하지 않는 유일한 방법은 .bashrc에 다음이 있는 경우입니다.

case $- in
    *i*) ;;
      *) return;;
esac

.bashrc에 해당 코드가 있는 경우 ssh를 사용하여 명령을 실행하면 .bashrc 환경과 소스 파일이 로드되지 않습니다.

참고: 이것이 바로 표준 bashrc 및 스크립트 파일을 사용하는 것이 아니라 처음부터 직접 작성하거나 모든 줄을 읽고 각 줄의 기능을 알 수 있는 이유입니다.

다른 설정을 재정의하려면 먼저 소스 파일을 로드한 다음 함수를 호출하십시오. 참고: bashrc에서 소스 코드에 대한 참조를 제거했습니다.

주문하다:

ssh %server% ". ~/function_source.sh; testcall"

산출:

-ssh %server% ".~/function_source.sh; 테스트콜"

지금 난 여기 있어

마지막으로 bashrc에 소스 파일을 로드하고 ssh를 사용하여 함수를 호출합니다.

주문하다:

ssh %server% "testcall"

산출:

-ssh%server%"테스트콜"

지금 난 여기 있어

더 많은 예제가 필요하면 알려주시기 바랍니다.

참고: Windows 명령 프롬프트(수정된 프롬프트는 -)를 사용하여 ssh 명령을 실행했고, 개인 정보 보호를 위해 %server% 변수를 사용하고, 인증을 위해 ssh 키를 사용했습니다.

모든 것을 다 다루었는지 확인하기 위해 terdon이 제안한 대로 localhost에 SSH를 통해 연결할 수 있도록 Linux 가상 머신 중 하나로 SSH를 이동했습니다.

또한 함수 소스도 수정했습니다.

-cat function_source.sh
#!/bin/bash

function testcall {

echo -e "now here I am\r\n\r\n"
testanother
}

function testanother {
        echo -e "this is another function\r\n\r\n"
}
 

다음 명령을 실행하면:

ssh localhost "$(typeset -f testcall); testcall"

산출:

-ssh localhost "$(typesetting -f testcall); testcall"

지금 난 여기 있어

그러나 다음 명령을 실행하면:

ssh localhost "$(cat function_source.sh); testcall"

산출:

-ssh localhost "$(cat function_source.sh); 테스트 호출"

지금 난 여기 있어

이건 또 다른 기능이에요

SSH 연결 중인 서버에 대한 쓰기 권한이 없고 매번 환경에 함수를 로드해야 하는 경우에만 이 작업을 수행하면 됩니다.

관련 정보