긴 크론 작업이 병렬로 실행되는 것을 막는 일반적인 솔루션? 실행되지 않도록하는 간단하고 일반적인

crontab에서 스크립트 또는 응용 프로그램을 실행하고 두 번 실행되지 않도록하는 간단하고 일반적인 솔루션을 찾고 있습니다.

솔루션은 실행 된 명령과 독립적이어야합니다.

lock && (command ; unlock)다른 잠금이 있으면 잠금이 false를 반환하는 위치 와 같아야한다고 가정합니다 .

두 번째 부분은 오류를 반환하더라도 잠금, 실행 명령 및 명령 실행 후 잠금 해제를 얻은 경우와 같습니다.



답변

상기 봐 가지고 실행 하나의 패키지. 로부터 에 대한 맨 페이지 run-one명령 :

run-one 은 고유 한 인수 세트를 사용하여 명령의 고유 인스턴스를 하나 이상 실행하는 랩퍼 스크립트입니다.

한 번에 하나 이상의 사본을 실행하지 않으려는 경우 cronjob에 유용합니다.

time또는 과 같이 sudo명령 앞에 추가하면됩니다. 따라서 cronjob은 다음과 같습니다.

  */60 * * * *   run-one rsync -azP $HOME example.com:/srv/backup

자세한 내용과 배경 은 Dustin Kirkland가 소개 한 블로그 게시물을 확인하십시오 .


답변

잠금을 설정하는 매우 간단한 방법 :

if mkdir /var/lock/mylock; then
  echo "Locking succeeded" >&2
else
  echo "Lock failed - exit" >&2
  exit 1
fi

실행하려는 스크립트는 잠금을 생성해야합니다. 잠금이 존재하면 다른 스크립트가 사용 중이므로 첫 번째 스크립트를 실행할 수 없습니다. 파일이 존재하지 않으면 스크립트가 잠금을 획득하지 않은 것입니다. 따라서 현재 스크립트는 잠금을 획득합니다. 스크립트가 완료되면 잠금을 제거하여 잠금을 구현해야합니다.

bash 잠금에 대한 자세한 내용은 페이지를 확인 하십시오.


답변

멋진 패키지를 설치할 필요가 없습니다.

#!/bin/bash
pgrep -xf "$*" > /dev/null || "$@"

“apt-get install”을 실행하는 것보다 스크립트를 직접 작성하는 것이 더 빠르지 않습니까? 현재 사용자 만 실행하는 인스턴스를 확인하기 위해 “-u $ (id -u)”를 pgrep에 추가 할 수 있습니다.


답변

solo사용자에게 고유 한 루프백 주소의 포트를 바인딩하여 잠금을 수행하는 Tim Kay ‘s도 참조하십시오 .

http://timkay.com/solo/

그의 사이트가 다운되는 경우 :

용법:

solo -port=PORT COMMAND

where
    PORT        some arbitrary port number to be used for locking
    COMMAND     shell command to run

options
    -verbose    be verbose
    -silent     be silent

다음과 같이 사용하십시오.

* * * * * solo -port=3801 ./job.pl blah blah

스크립트:

#!/usr/bin/perl -s
#
# solo v1.7
# Prevents multiple cron instances from running simultaneously.
#
# Copyright 2007-2016 Timothy Kay
# http://timkay.com/solo/
#
# It is free software; you can redistribute it and/or modify it under the terms of either:
#
# a) the GNU General Public License as published by the Free Software Foundation;
#    either version 1 (http://dev.perl.org/licenses/gpl1.html), or (at your option)
#    any later version (http://www.fsf.org/licenses/licenses.html#GNUGPL), or
#
# b) the "Artistic License" (http://dev.perl.org/licenses/artistic.html), or
#
# c) the MIT License (http://opensource.org/licenses/MIT)
#

use Socket;

alarm $timeout                              if $timeout;

$port =~ /^\d+$/ or $noport                     or die "Usage: $0 -port=PORT COMMAND\n";

if ($port)
{
    # To work with OpenBSD: change to
    # $addr = pack(CnC, 127, 0, 1);
    # but make sure to use different ports across different users.
    # (Thanks to  www.gotati.com .)
    $addr = pack(CnC, 127, $<, 1);
    print "solo: bind ", join(".", unpack(C4, $addr)), ":$port\n"   if $verbose;

    $^F = 10;           # unset close-on-exec

    socket(SOLO, PF_INET, SOCK_STREAM, getprotobyname('tcp'))       or die "socket: $!";
    bind(SOLO, sockaddr_in($port, $addr))               or $silent? exit: die "solo($port): $!\n";
}

sleep $sleep if $sleep;

exec @ARGV;

답변

자물쇠가 필요합니다. run-one작업을 수행하지만 패키지 flock에서 살펴볼 수도 있습니다 util-linux.

커널 개발자가 제공하는 표준 패키지로, 더 많은 사용자 정의를 허용하며 run-one여전히 매우 간단합니다.


답변

나를 위해 일한 bash-hackers.org 의 간단한 솔루션은 mkdir 을 사용하는 것 입니다. 이것은 하나의 프로그램 인스턴스 만 실행되도록하는 쉬운 방법입니다. 있는 디렉토리 만들기 에서 mkdir .lock 하는 수익을

  • 성공적으로 만든 경우 true
  • 잠금 파일이 존재하면 현재 실행중인 인스턴스가 하나 있음을 나타내는 false 입니다.

따라서이 간단한 함수는 모든 파일 잠금 논리를 수행했습니다.

if mkdir .lock; then
    echo "Locking succeeded"
    eval startYourProgram.sh ;
else
    echo "Lock file exists. Program already running? Exit. "
    exit 1
fi


echo "Program finished, Removing lock."
rm -r .lock

답변

이 솔루션은 자체 확인이 필요한 bash 스크립트를위한 것입니다.

v=$(pgrep -xf "/bin/bash $0 $@")
[ "${v/$BASHPID/}" != "" ] && exit 0