What's a quick-and-dirty way to make sure that only one instance of a shell script is running at a given time?
相关问题
- How to get the return code of a shell script in lu
- JQ: Select when attribute value exists in a bash a
- Invoking Mirth Connect CLI with Powershell script
- Emacs shell: save commit message
- bash print whole line after splitting line with if
相关文章
- 使用2台跳板机的情况下如何使用scp传文件
- In IntelliJ IDEA, how can I create a key binding t
- Check if directory exists on remote machine with s
- shell中反引号 `` 赋值变量问题
- How get the time in milliseconds in FreeBSD?
- Reverse four length of letters with sed in unix
- Launch interactive SSH bash session from PHP
- BASH: Basic if then and variable assignment
An example with flock(1) but without subshell. flock()ed file /tmp/foo is never removed, but that doesn't matter as it gets flock() and un-flock()ed.
When targeting a Debian machine I find the
lockfile-progs
package to be a good solution.procmail
also comes with alockfile
tool. However sometimes I am stuck with neither of these.Here's my solution which uses
mkdir
for atomic-ness and a PID file to detect stale locks. This code is currently in production on a Cygwin setup and works well.To use it simply call
exclusive_lock_require
when you need get exclusive access to something. An optional lock name parameter lets you share locks between different scripts. There's also two lower level functions (exclusive_lock_try
andexclusive_lock_retry
) should you need something more complex.Here is a more elegant, fail-safe, quick
& dirtymethod, combining the answers provided above.Usage
Script File
sh_lock_functions.sh
Usage example
sh_lock_usage_example.sh
Features
For shell scripts, I tend to go with the
mkdir
overflock
as it makes the locks more portable.Either way, using
set -e
isn't enough. That only exits the script if any command fails. Your locks will still be left behind.For proper lock cleanup, you really should set your traps to something like this psuedo code (lifted, simplified and untested but from actively used scripts) :
Here's what will happen. All traps will produce an exit so the function
__sig_exit
will always happen (barring a SIGKILL) which cleans up your locks.Note: my exit values are not low values. Why? Various batch processing systems make or have expectations of the numbers 0 through 31. Setting them to something else, I can have my scripts and batch streams react accordingly to the previous batch job or script.
Another option is to use shell's
noclobber
option by runningset -C
. Then>
will fail if the file already exists.In brief:
This causes the shell to call:
which atomically creates the file or fails if the file already exists.
According to a comment on BashFAQ 045, this may fail in
ksh88
, but it works in all my shells:Interesting that
pdksh
adds theO_TRUNC
flag, but obviously it's redundant:either you're creating an empty file, or you're not doing anything.
How you do the
rm
depends on how you want unclean exits to be handled.Delete on clean exit
New runs fail until the issue that caused the unclean exit to be resolved and the lockfile is manually removed.
Delete on any exit
New runs succeed provided the script is not already running.
The existing answers posted either rely on the CLI utility
flock
or do not properly secure the lock file. The flock utility is not available on all non-Linux systems (i.e. FreeBSD), and does not work properly on NFS.In my early days of system administration and system development, I was told that a safe and relatively portable method of creating a lock file was to create a temp file using
mkemp(3)
ormkemp(1)
, write identifying information to the temp file (i.e. PID), then hard link the temp file to the lock file. If the link was successful, then you have successfully obtained the lock.When using locks in shell scripts, I typically place an
obtain_lock()
function in a shared profile and then source it from the scripts. Below is an example of my lock function:The following is an example of how to use the lock function:
Remember to call
clean_up
at any exit points in your script.I've used the above in both Linux and FreeBSD environments.