그러나 나는 ps
사람들이 그것을 사용하는 것을 계속보고 있기 때문에 여러 가지 파괴되고 반 작업 가능한 접근법 과 그들이 가지고있는 많은주의 에 대해 이야기하고 싶습니다 .
이 답변은 정말 대답은 "왜 사용하지 ps
와 grep
쉘에 잠금 처리하기 위해?"
접근 방식 # 1
첫째, 다른 답변 에서 주어진 접근 방식 은 작동하지 않으며 결코 테스트 할 수 없다는 사실에도 불구하고 몇 가지 공감대를 가지고 있습니다.
running_proc=$(ps -C bash -o pid=,cmd= | grep my_script);
if [[ "$running_proc" != "$$ bash my_script" ]]; do
echo Already locked
exit 6
fi
구문 오류와 깨진 ps
인수를 수정 하고 다음을 얻습니다.
running_proc=$(ps -C bash -o pid,cmd | grep "$0");
echo "$running_proc"
if [[ "$running_proc" != "$$ bash $0" ]]; then
echo Already locked
exit 6
fi
이 스크립트는 실행 방법에 관계없이 항상 6을 종료합니다.
로 실행 ./myscript
하면 ps
출력은 단지 12345 -bash
필수 문자열과 일치하지 않으므로 12345 bash ./myscript
실패합니다.
로 실행하면 bash myscript
상황이 더 흥미로워집니다. 배쉬 프로세스 포크는 파이프 라인을 실행하고, 자식 쉘은 실행 ps
및 grep
. 원래 셸과 자식 셸 모두 ps
출력에 다음과 같이 표시됩니다 .
25793 bash myscript
25795 bash myscript
예상되는 출력 $$ bash $0
이 아니므로 스크립트가 종료됩니다.
부러진 접근법 # 2
이제 깨진 접근법 # 1을 작성한 사용자에게 공평하게, 나는 이것을 처음 시도했을 때 비슷한 것을했습니다.
if otherpids="$(pgrep -f "$0" | grep -vFx "$$")" ; then
echo >&2 "There are other copies of the script running; exiting."
ps >&2 -fq "${otherpids//$'\n'/ }" # -q takes about a tenth the time as -p
exit 1
fi
이것은 거의 작동합니다. 그러나 파이프를 포크로 돌리는 사실은 이것을 버립니다. 따라서 이것도 항상 종료됩니다.
신뢰할 수없는 접근법 # 3
pids_this_script="$(pgrep -f "$0")"
if not_this_process="$(echo "$pids_this_script" | grep -vFx "$$")"; then
echo >&2 "There are other copies of this script running; exiting."
ps -fq "${not_this_process//$'\n'/ }"
exit 1
fi
이 버전은 명령 행 인수에 현재 스크립트가있는 모든 PID를 먼저 가져온 다음 해당 pidlist를 개별적으로 필터링하여 현재 스크립트의 PID를 생략 함으로써 접근법 # 2에서 파이프 라인 분기 문제점을 방지합니다 .
이것은 다른 프로세스를 제공하지 것은 일치하는 명령 라인을 가지고 ... 작동 할 수 있습니다 $0
, 그리고 스크립트를 제공하는 것이 항상이 다음 상대 경로와 절대 경로라고한다면, 후자의 경우는 전자를 통지하지 않습니다 예를 들어, (같은 방식이라고합니다 ).
신뢰할 수없는 접근법 # 4
전체 명령 줄 검사를 건너 뛰면 스크립트가 실제로 실행되고 있음을 나타내지 lsof
않고 대신이 스크립트가 열려있는 모든 프로세스를 찾기 위해 검사 할 수 있습니까?
예,이 접근법은 실제로 그렇게 나쁘지 않습니다.
if otherpids="$(lsof -t "$0" | grep -vFx "$$")"; then
echo >&2 "Error: There are other processes that have this script open - most likely other copies of the script running. Exiting to avoid conflicts."
ps >&2 -fq "${otherpids//$'\n'/ }"
exit 1
fi
물론, 스크립트 사본 이 실행 중이면 새 인스턴스가 정상적으로 시작되고 두 개의 사본이 실행됩니다.
또는 실행중인 스크립트가 수정 된 경우 (예 : Vim 또는 git checkout
), 스크립트의 "새"버전은 문제없이 시작됩니다. Vim과 git checkout
그 대신 새 파일 (새 inode)이 생성되기 때문입니다. 오래된 것.
그러나 스크립트를 수정하지 않고 복사하지 않으면 이 버전이 좋습니다. 검사에 도달하기 전에 스크립트 파일이 열려 있어야하므로 경쟁 조건이 없습니다.
다른 프로세스에 스크립트 파일이 열려 있으면 여전히 긍정 오류가있을 수 있지만 Vim에서 편집하기 위해 열려있는 경우에도 vim은 실제로 스크립트 파일을 열어 두지 않으므로 오탐 (false positive)이 발생하지 않습니다.
스크립트를 편집하거나 복사 할 수 있습니다하지만 당신이 얻을 것이기 때문에 거짓이 방법을 사용하지 않는 기억 악재가 빔으로 편집하는 오탐 (false positive)이 종류의 문제가되지해야합니다 제공하지 않습니다 너무 사실 - 한 번에 여러 인스턴스가 실행 즉, 당신에게. 방법 # 3이 때문에,하지만 그것을 언급 않습니다 당신은 빔 오픈 스크립트가있는 경우 (즉, 시작하는 것을 거부) 잘못된 반응을 제공합니다.
그럼 어떻게해야합니까?
이 질문에 대한 최고의 투표 대답은 좋은 고체 접근 방식을 제공합니다.
아마도 더 좋은 것을 쓸 수는 있지만 위의 모든 접근 방식의 모든 문제와주의를 이해하지 못하면 모든 것을 피하는 잠금 방법을 작성하지 않을 것입니다.
kill
. 자신의 pid를 만지는 것이 아니라 잠금 파일에 저장하는 것이 좋습니다.