명령 전용 유틸리티를 사용하여 "zsh" 기능 처리

명령 전용 유틸리티를 사용하여 "zsh" 기능 처리

(이 질문에서는 Mac caffeinate도구를 예로 사용하지만 이 개념은 xargs유틸리티를 인수로 받아들이는 모든 도구에 적용됩니다.)

Mac용 도구에서는 caffeinate유틸리티 이름을 허용합니다( caffeinate sleep 1예 : sleep유틸리티는 어디에 있습니까). zsh도구 자체를 수정하지 않고 기능도 허용하도록 하는 방법이 있습니까 ? 예를 들어:

function mysleep {
  sleep 2
}

caffeinate mysleep    # mysleep: No such file or directory

편집: 이 질문은 실제로 Bash와 중복됩니다. 답변을 알려주셔서 감사합니다. 그러나 zsh에서는 export -f작동하지 않습니다. zsh에서 이 작업을 수행할 수 있는 방법이 있나요? ( bash혼잡함을 줄이기 위해 라벨을 제거하고 있습니다 .)

답변1

caffeinate명령이 새 프로세스에서 실행될 것으로 예상합니다.

기능을 해석하려면 명령이 zsh필요합니다 zsh.

함수 정의(및 필요할 수 있는 다른 함수)를 전달해야 합니다. 예를 들면 다음과 같습니다.

mysleep() {
  sleep 2
}
caffeinate zsh -c "$(functions mysleep);mysleep"

functions mysleepby가 최종적으로 해석되도록 함수를 호출하기 전에 mysleep해석을 위해 new에 전달한 함수 정의를 덤프합니다.zshzshcaffeinate

mysleep() {
  sleep 2
};mysleep

다음과 비교하면 bash:

mysleep() {
  sleep 2
}
export -f mysleep
caffeinate bash -c "mysleep"

(입력 시 2자 더 짧게 작성) bash다음을 수행합니다.

execve("/path/to/caffeinate",
  ["caffeinate", "bash", "-c", "mysleep"],
  ["BASH_FUNC_mysleep%%=() {  sleep 2\n}", rest-of-environment])

zsh, 우리는 다음을 얻습니다:

execve("/path/to/caffeinate",
  ["caffeinate", "zsh", "-c", "mysleep () {\n\tsleep 2\n};mysleep"],
  [rest-of-environment])

후자의 접근 방식에는 몇 가지 장점이 있습니다.

  • 우리는 완전한 제어권을 갖고 있습니다. 함수 정의를 전달하는 방법과 이를 사용하는 방법을 알고 있습니다. 여기에서는 쉘 쇼크와 같은 불쾌한 일이 발생할 가능성이 적습니다.
  • 함수 정의를 전달하는 bash 환경 변수의 이름에는 %문자가 포함되어 있으므로(예를 들어 문자가 아닌 경우에도 ) 해당 변수가 실행하는 명령 에 전파된다는 sudo보장은 없습니다 .caffeinatebash
  • 전파되면 함수 정의가 argv[]가 아닌 envp[]에 저장되기 때문에 해당 환경에서 실행되는 다른 모든 명령의 환경이 오염된다는 의미입니다( sleep이 경우 예제 포함).
  • (사소한) bash셸 코드는 더 짧지만 더 많은 데이터를 전달하므로 execve()이 시스템 호출의 E2BIG 제한에 더 많은 영향을 미칩니다.

해당 환경을 사용하려는 경우에도 다음을 수행할 수 있습니다.

FUNCS=$(functions mysleep) caffeinate zsh -c '
  eval "$FUNCS";mysleep'

이 경우 함수가 실행 중일 때만 실행 caffeinate하면 되지만 caffeinate반드시 함수를 실행할 필요는 없으며 다음과 같은 다른 방법을 사용할 수 있습니다.

mysleep | caffeinate cat

cat실행되는 한 mysleep실행됩니다. mysleep여전히 별도의 프로세스에서 실행되지만 이는 표준 출력에 영향을 미칩니다 mysleep.

mysleep 3> {fd}>(caffeinate cat)

두 가지 문제를 모두 해결해 드립니다.

위에서 언급했듯이 이렇게 mysleep하면 cat. 그러나 파이프의 쓰기 끝은 이제 $fd10보다 큰 새로 할당된 파일 설명자(에 저장됨) 에 있으며 mysleep일반적으로 기록되지 않습니다. cat따라서 아무것도 읽히지 않지만 파이프의 파일이 끝날 때까지 기다립니다. 이는 mysleep(및 이 fd를 상속하는 모든 하위 프로세스) 종료되는 경우에만 발생합니다.

답변2

이를 수행하는 가장 좋은 방법은 함수를 스크립트 파일에 넣고 다음과 같이 스크립트를 호출하는 것입니다.

caffeinate myfunction.sh

myfunction.sh의 내용:

#!/bin/bash
sleep 2

스크립트 파일이 실행 가능한지 확인하세요. 그렇지 않으면 권한 오류가 발생합니다.

chmod +x myfunction.sh

관련 정보