(이 질문에서는 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 mysleep
by가 최종적으로 해석되도록 함수를 호출하기 전에 mysleep
해석을 위해 new에 전달한 함수 정의를 덤프합니다.zsh
zsh
caffeinate
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
보장은 없습니다 .caffeinate
bash
- 전파되면 함수 정의가 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
. 그러나 파이프의 쓰기 끝은 이제 $fd
10보다 큰 새로 할당된 파일 설명자(에 저장됨) 에 있으며 mysleep
일반적으로 기록되지 않습니다. cat
따라서 아무것도 읽히지 않지만 파이프의 파일이 끝날 때까지 기다립니다. 이는 mysleep
(및 이 fd를 상속하는 모든 하위 프로세스) 종료되는 경우에만 발생합니다.
답변2
이를 수행하는 가장 좋은 방법은 함수를 스크립트 파일에 넣고 다음과 같이 스크립트를 호출하는 것입니다.
caffeinate myfunction.sh
myfunction.sh의 내용:
#!/bin/bash
sleep 2
스크립트 파일이 실행 가능한지 확인하세요. 그렇지 않으면 권한 오류가 발생합니다.
chmod +x myfunction.sh