쉘 스크립트에서 bash 함수를 정의하고 이를 사용하여 "스크립트"를 연결합니다.

쉘 스크립트에서 bash 함수를 정의하고 이를 사용하여 "스크립트"를 연결합니다.

bash 스크립트 내에서 bash 함수를 정의하고 command 다음에 연결하려고 할 때 동일한 스크립트에서 이를 사용하는 데 문제가 있습니다 script.

최소한의 작업 예는 다음과 같습니다. my_script.sh다음을 포함하는 이라는 파일이 있습니다 .

#!/bin/bash

my_function () {
  echo "My output"
}

my_function

script my_log.log -c my_function

실행 중 반환

My output
Script started, output log file is 'my_log.log'.
bash: line 1: my_function: command not found
Script done.

my_function왜 단독으로는 인식되는데 연결 후에는 인식되지 않는지 이해가 되지 않습니다 script.

누군가 그것을 설명하고 해결책을 제시할 수 있습니까?

답변1

여기서 문제는 함수가 스크립트 내에만 존재하지만 실행하는 명령이 script새 셸(경로가 저장된 쉘 $SHELL또는 /bin/sh기타 쉘)을 호출한다는 것입니다. 새 쉘은 사용자가 함수를 정의하지 않는 한 함수에 대해 알지 못합니다.

bash지원출구환경에 대한 기능. sh해당 환경에서 실행되는 bash에 대한 다른 모든 호출(bash로 실행되는 호출도 포함)은 이러한 정의를 가져옵니다 .

함수를 내보내려면 다음을 수행해야 합니다.

export -f my_function

help export셸에서 보기 bash:

$ help export 
export: export [-fn] [name[=value] ...] or export -p
    Set export attribute for shell variables.
    
    Marks each NAME for automatic export to the environment of subsequently
    executed commands.  If VALUE is supplied, assign VALUE before exporting.
    
    Options:
      -f    refer to shell functions
      -n    remove the export property from each NAME
      -p    display a list of all exported variables and functions
    
    An argument of `--' disables further option processing.
    
    Exit Status:
    Returns success unless an invalid option is given or NAME is invalid.

그런 다음 해야 할 일은 인터프리터를 script실행 bash한 후 명령줄이 전달되었는지 확인하는 것입니다 -c. 올바른 변수 값을 전달해야 합니다 $SHELL.

SHELL=$BASH script -c myfunction

답변2

보충하다@terdon의 답변bash, (ksh, mksh, zsh) 이외의 Korn과 유사한 셸을 지원하는 것 외에도 typeset -f또는 bash함수 내보내기 기능의 함정(아래 참조)을 피하기 위한 경우 몇 가지 대안을 제안합니다.

실행된 셸에서 정의한 동일한 함수의 경우 script셸 코드가 전달되기 전에 함수 정의를 포함할 수 있으며 script -c다음을 사용하여 얻을 수 있습니다 typeset -f.

SHELL=/same/shell/as/running/the/current/script script -c "
  $(typeset -f myfunc)
  myfunc"

script함수를 정의한 다음 호출하여 시작되는 새 셸이 시작되는 곳입니다 .

또는 함수 본문을 환경 변수 1에 전달하고 script해당 변수의 내용을 평가하여 셸을 시작합니다.

SHELL=/same/shell/as/running/the/current/script \
  MYFUNC_DEFINITION="$(typeset -f myfunc)" script -c '
  eval "$MYFUNC_DEFINITION"
  myfunc'

(이 접근 방식은 모든 사람이 출력에서 ​​볼 수 있도록 명령줄 인수에 함수 본문을 노출하지 않는다는 장점이 있습니다 ps.)

export -f비교 시 장점은 다음과 같습니다(bash에만 국한되지 않음).

  • 그러면 함수는 해당 환경에서 시작될 수 있는 다른 셸이 아닌 필요한 셸에만 노출됩니다.
  • bashextglob함수가 연산자를 사용하는 경우 이 옵션을 활성화 하지 않으면 함수 가져오기가 실패합니다.extglob앞으로함수를 가져왔습니다. 우리의 접근 방식을 사용하면 함수 정의를 가져올 시기를 선택한 다음 shopt -s extglob앞에 함수 정의를 추가할 수 있습니다. 하지만 with를 사용하여 내보낸 함수의 경우 export -f옵션을 초기에 설정할 수 있는 유일한 방법은 여기서 옵션이 아닌 with를 사용하는 것입니다. 심지어 (모든 통화에 영향을 미치기 때문에 위험합니다) 작동하지 않습니다.extglobbash -O extglobscriptenv BASHOPTS=extglob script -c ...bash

1 사실 그게 bash전부입니다 export -f. 심지어는 매우 안전하지 않은 방식으로 이를 수행하기도 했는데, 이는 몇 년 전에 헤드라인을 장식했던 매우 불쾌한 취약점의 원인이었습니다. .

관련 정보