bash의 export -f와 동일한 zsh는 무엇입니까


24

그래서을 사용하기 시작했습니다 zsh. 나는 그것을 좋아한다. 그것은 매우 시원하고 매끈 해 보이고 현재 작업 디렉토리와 실제 명령 줄이 다른 줄에 있다는 사실은 좋지만, 동시에 텍스트를 인쇄 할 zsh때보 다 조금 느릴 수 있습니다 bash. 화면.

내가 가장 좋아하는 것은 zshmy에 정의 된 모든 함수와 '역방향으로 호환' 되었다는 사실 이었습니다 .bashrc.

그래도 하나. 기능은 모두 완벽하게 작동하지만 내보내기 시스템의 작동 방식을 알 수 없습니다.

.bashrc스크립트 및 외부 프로그램과 같은 다른 곳에서 사용할 수 있도록 일부 함수를 내보냈습니다 export -f.

zsh에서는 내보내기에 대해 이야기조차하지 않습니다. 자동 로딩입니까? 그 두 가지가 같은가요? 나는 그것을 알아내는 데 정말로 어려움을 겪고 있습니다.


2
이것은 매우 오래된 질문이지만 "현재 작업 디렉토리와 실제 명령 줄이 다른 줄에 있습니다"는 zsh와 전혀 관련이 없다고 말하고 싶습니다. 프롬프트 설정 방법에 따라 다릅니다.
4ae1e1

답변:


11

함수를 포함하는 환경 변수는 bash hack입니다. Zsh에는 비슷한 것이 없습니다. 몇 줄의 코드로 비슷한 것을 할 수 있습니다. 환경 변수에는 문자열이 포함됩니다. 쉘 쇼크 가 발견 되기 전에 bash의 이전 버전은 함수의 이름이 함수의 이름이고 그 () {뒤에 값이 오는 함수의 코드 가 뒤에 오는 변수에 함수의 코드를 저장 했습니다 }. 다음 코드를 사용하여이 인코딩으로 변수를 가져오고 bash와 같은 설정으로 변수를 실행할 수 있습니다. zsh가 모든 bash 기능을 에뮬레이트 할 수는 없습니다. 조금 더 가까이 다가 가면됩니다 (예 : $foo값 을 나누고 와일드 카드를 확장하고 배열을 0 기반으로 만들기).

bash_function_preamble='
    emulate -LR ksh
'
for name in ${(k)parameters}; do
  [[ "-$parameters[name]-" = *-export-* ]] || continue
  [[ ${(P)name} = '() {'*'}' ]] || continue
  ((! $+builtins[$name])) || continue
  functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done

( Shellshock의 최초 발견자인 Stéphane Chazelas 는이 함수의 이전 버전은 함수 정의가 잘못된 경우이 시점에서 임의의 코드를 실행할 수 있다고 지적했다. 환경에서 가져온 함수일 수 있습니다.)

bash의 셸 쇼크 이후 버전의 bash는 잘못된 변수 이름 (예 :)을 사용하여 환경에서 함수를 인코딩합니다 BASH_FUNC_myfunc%%. zsh는 환경에서 이러한 변수 이름을 추출하는 인터페이스를 제공하지 않기 때문에 안정적으로 구문 분석하기가 더 어려워집니다.

나는 이것을하지 않는 것이 좋습니다. 스크립트에서 내 보낸 함수에 의존하는 것은 나쁜 생각입니다. 스크립트에서 보이지 않는 의존성을 만듭니다. 기능이없는 환경 (쉘 초기화 파일을 변경 한 후 다른 컴퓨터, cron 작업 등)에서 스크립트를 실행하면 스크립트가 더 이상 작동하지 않습니다. 대신 모든 기능을 하나 이상의 별도 파일 (같은 것 ~/lib/shell/foo.sh)에 저장하고 사용하는 기능 ( . ~/lib/shell/foo.sh) 을 가져 와서 스크립트를 시작하십시오 . 이런 식으로 수정 foo.sh하면에 의존하고있는 스크립트를 쉽게 검색 할 수 있습니다. 스크립트를 복사하면 필요한 보조 파일을 쉽게 찾을 수 있습니다.

Zsh (및 그 전에 ksh)는 함수가 사용되는 스크립트에서 함수를 자동으로로드하는 방법을 제공하여보다 편리합니다. 제약 조건은 파일 당 하나의 함수 만 넣을 수 있다는 것입니다. 함수를 자동로드 된 것으로 선언하고 이름이 함수 이름 인 파일에 함수 정의를 넣으십시오. 이 파일을 $fpath( FPATH환경 변수를 통해 구성 할 수있는)에 나열된 디렉토리에 넣으십시오 . 스크립트에서로 자동로드 된 함수를 선언하십시오 autoload -U foo.

또한 zsh는 스크립트를 컴파일하여 구문 분석 시간을 절약 할 수 있습니다. zcompile스크립트를 컴파일하기 위해 호출 합니다. .zwc확장명을 가진 파일을 만듭니다 . 이 파일이 있으면 autoload소스 코드 대신 컴파일 된 파일을로드합니다. zrecompile함수 를 사용하여 디렉토리의 모든 함수 정의를 (재) 컴파일 할 수 있습니다 .


1
재미는 코드가 같은 셸 쇼크 취약점 얼마나 bash했다을 (변수의 내용은 확인하지 않습니다 단지 함수 정의와 같은 모든 변수 이름을 처리 HTTP_HOST또는 LC_X). 그렇지 않으면 좋은 대답입니다.
Stéphane Chazelas 2016 년

@ StéphaneChazelas 환경에서 가져온 함수를 사용하여 명령을 실행하려는 경우 손실이 거의 없습니다. 그러나 임의 코드를 실행하지 않도록 가져 오기 코드를 업데이트했습니다. post-shellshock bash는 내 보낸 함수를 같은 방식으로 인코딩하지 않기 때문에별로 유용하지 않습니다.
Gilles 'SO- 악마 그만해'

이제 CVE-2014-6271과 동등한 기능을 수정했지만 여전히 zsh 파서를 변수에 코드로 노출함에 따라 CVE-2014-6277 / 6278 유형의 많은 취약점에 노출 될 수 있습니다. 일부 상황에서는 잠재적으로 공격자가 제어 할 수있는 일부를 포함합니다 ( 함수가 호출되지 않아도 코드 zsh -c 'functions[f]=$VAR'구문 분석 되므로 f). 해결책은 이름이 변수와 같은 예약 된 템플릿을 따르는 변수 만 고려하는 것입니다 $BASH_FUNC_x%%. 그러나 말했듯이 변수 zsh를 나열하거나 검색 할 API가 없습니다. perl예를 들어 전화해야 합니다.
Stéphane Chazelas

7

함수 선언을 .zshenv넣으면 아무런 노력없이 스크립트에서 함수를 사용할 수 있습니다.


왜 내 대답을 공감 했어? 설명 해주십시오.
rools

여전히 답변을 기다리고 있으며 여전히 작동합니다!
rools

방금이 답변을 발견했으며 이상적인 솔루션입니다.
AFH

나는 그것을 공감하지 않았다. 그리고 TBH OP는 나쁜 아이디어 인 .bashrc에서 물건을 내보내는 것에 대해 물었습니다. 거대한 환경으로 끝나지 않도록 스크립트에 넣는 것이 좋습니다. 그러나 솔루션은 똑같은 나쁜 생각의 변형 일뿐입니다. 모든 스크립트를 넣은 다음 .zshenv결코 사용되지 않는 많은 코드를 구문 분석하여 zsh를 호출 할 때마다 속도가 느려집니다. 또한 내 보낸 변수와 마찬가지로 함수를 내보내는 것과 같지 않으며 내 보낸 함수는 자식 프로세스에서만 사용할 수 있습니다. 입력 한 내용 .zshenv은 모든 zsh 에서 사용할 수 있습니다.
변성

마지막으로에 입력 한 개인 코드에 의존하면 .zshenv모든 스크립트를 이식 할 수 없습니다. 일반적으로 스크립트는 서로 의존 할 수 있으며, 함께 배포하면됩니다. 그러나에 특수 기능 .zshenv을 사용하는 데 의존하는 사람은 아무도 사용하지 않거나 특수 기능 을 사용 ZDOTDIR하여 자신의 .zshenv실행을 방해해야합니다 . 고통 스러울 것입니다.
변성
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.