내 스크립트가 이미 실행 중인지 감지하고 싶기 때문에 다음을 사용합니다.이것:
pidof -o %PPID -x "$0" >/dev/null && echo 'already running!' && exit 1
이것은 작동합니다. 하지만 나는 그것이 함수에 있기를 원합니다.
#!bin/bash
set -eu
set -o pipefail
checkIfRunning() {
pidof -o %PPID -x "$0" >/dev/null && echo 'already running!' && exit 1
}
#...
checkIfRunning
이것은 작동하지 않습니다. 실행 중인 스크립트 인스턴스가 하나만 있어도 항상 종료됩니다.
pidof
서브쉘에서 실행하면 서브쉘과 스크립트를 감지하여 결과를 해석할 것이라고 생각합니다 . 하지만 여기서 서브쉘이 어떻게 생성되는지 이해가 안 가나요?
이 문제의 원인은 무엇이며 어떻게 해결할 수 있나요?
답변1
코드에서 처리되지 않은 명령이 실패하면 set -e
(약어로 set -o errexit
) 셸이 종료됩니다.
pidof
일치하는 프로세스를 찾을 수 없으면 실패한 종료 상태가 반환되지만 사용자가 실패를 처리했습니다. pidof
다음과 같이 사용됨그리고-또는 목록, 그래서 실제로 실패합니다아니요방아쇠 errexit
.
하지만 당신이 사용했기 때문에그리고-또는 목록0이 아닌 종료 상태로 종료되는 if
생성자를 사용해야 하는 경우 해당 and-or-list가 함수에서 마지막으로 실행 되기 때문에 함수 자체도 실패한 종료 상태를 반환합니다.pidof && othercommand
checkIfRunning
checkIfRunning
그리고 결함이 처리되지 않아 errexit
트리거됩니다. 실패로 인해 errexit
발생하는 것이 아니라 실패로 인해 발생합니다.pidof
checkIfRunning
여기에 다음을 작성해야 합니다.
checkIfRunning() {
if pidof -o %PPID -x -- "$0" >/dev/null; then
echo >&2 'Already running!'
exit 1
fi
}
구성된 종료 상태는 if
또는 섹션에서 실행된 마지막 명령의 종료 상태이거나, 실행된 명령이 없는 경우 조건 섹션의 종료 상태입니다.then
else
0
일반적으로 if
and-or 목록 대체 구조는 다음과 같습니다.잘못된. 전반적인 종료 상태 문제 외에도 스크립트 echo
가 실패 하면 pidof && echo && exit 1
스크립트가 종료되지 않습니다 .
errexit
나는 이것을 피해야 하며 함수나 가장 간단한 스크립트 이외의 다른 것을 사용하면 적절한 오류 처리를 수행해야 한다고 생각합니다.
바라보다set -euo pipefail
Bash 위키의 해당 섹션(의 약어 set -o errexit -o nounset -o pipefail
) 또는이 FAQ 항목.
~에 대한귀하의 (현재 삭제된) 답변이 문제를 해결하려고 시도합니다.
checkIfRunning() { set +e # <--- pidof -o %PPID -x $0 >/dev/null \ && echo "running!" && exit 1 set -e # <--- }
작동하는 유일한 이유는 set -e
성공 상태로 종료되기 때문입니다. 따라서 이 checkIfRunning
역시 set +e
관련성이 없고 불필요하며 or set -e
로 대체될 수 있습니다 .true
return 0