How do I make sure my bash script isn't already running?

后端 未结 13 945
無奈伤痛
無奈伤痛 2020-12-31 05:56

I have a bash script I want to run every 5 minutes from cron... but there\'s a chance the previous run of the script isn\'t done yet... in this case, i want the new run to j

13条回答
  •  误落风尘
    2020-12-31 06:40

    You can use this.

    I'll just shamelessly copy-paste the solution here, as it is an answer for both questions (I would argue that it's actually a better fit for this question).

    Usage

    1. include sh_lock_functions.sh
    2. init using sh_lock_init
    3. lock using sh_acquire_lock
    4. check lock using sh_check_lock
    5. unlock using sh_remove_lock

    Script File

    sh_lock_functions.sh

    #!/bin/bash
    
    function sh_lock_init {
        sh_lock_scriptName=$(basename $0)
        sh_lock_dir="/tmp/${sh_lock_scriptName}.lock" #lock directory
        sh_lock_file="${sh_lock_dir}/lockPid.txt" #lock file
    }
    
    function sh_acquire_lock {
        if mkdir $sh_lock_dir 2>/dev/null; then #check for lock
            echo "$sh_lock_scriptName lock acquired successfully.">&2
            touch $sh_lock_file
            echo $$ > $sh_lock_file # set current pid in lockFile
            return 0
        else
            touch $sh_lock_file
            read sh_lock_lastPID < $sh_lock_file
            if [ ! -z "$sh_lock_lastPID" -a -d /proc/$sh_lock_lastPID ]; then # if lastPID is not null and a process with that pid exists
                echo "$sh_lock_scriptName is already running.">&2
                return 1
            else
                echo "$sh_lock_scriptName stopped during execution, reacquiring lock.">&2
                echo $$ > $sh_lock_file # set current pid in lockFile
                return 2
            fi
        fi
        return 0
    }
    
    function sh_check_lock {
        [[ ! -f $sh_lock_file ]] && echo "$sh_lock_scriptName lock file removed.">&2 && return 1
        read sh_lock_lastPID < $sh_lock_file
        [[ $sh_lock_lastPID -ne $$ ]] && echo "$sh_lock_scriptName lock file pid has changed.">&2  && return 2
        echo "$sh_lock_scriptName lock still in place.">&2
        return 0
    }
    
    function sh_remove_lock {
        rm -r $sh_lock_dir
    }
    

    Usage example

    sh_lock_usage_example.sh

    #!/bin/bash
    . /path/to/sh_lock_functions.sh # load sh lock functions
    
    sh_lock_init || exit $?
    
    sh_acquire_lock
    lockStatus=$?
    [[ $lockStatus -eq 1 ]] && exit $lockStatus
    [[ $lockStatus -eq 2 ]] && echo "lock is set, do some resume from crash procedures";
    
    #monitoring example
    cnt=0
    while sh_check_lock # loop while lock is in place
    do
        echo "$sh_scriptName running (pid $$)"
        sleep 1
        let cnt++
        [[ $cnt -gt 5 ]] && break
    done
    
    #remove lock when process finished
    sh_remove_lock || exit $?
    
    exit 0
    

    Features

    • Uses a combination of file, directory and process id to lock to make sure that the process is not already running
    • You can detect if the script stopped before lock removal (eg. process kill, shutdown, error etc.)
    • You can check the lock file, and use it to trigger a process shutdown when the lock is missing
    • Verbose, outputs error messages for easier debug

提交回复
热议问题