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