Это основано на ответе пользователем zgoda . В основном это касается сложной проблемы, связанной с доступом на запись в файл блокировки. В частности, если файл блокировки был впервые создан root
, другой пользователь foo
не сможет успешно перезаписать этот файл из-за отсутствия разрешений на запись для пользователя foo
. Кажется, очевидным решением является создание файла с правами на запись для всех. Это решение также основано на другом ответе , сделанном мной, для создания файла с такими пользовательскими разрешениями. Эта проблема важна в реальном мире, где ваша программа может запускаться любым пользователем, включая root
.
import fcntl, os, stat, tempfile
app_name = 'myapp' # <-- Customize this value
# Establish lock file settings
lf_name = '.{}.lock'.format(app_name)
lf_path = os.path.join(tempfile.gettempdir(), lf_name)
lf_flags = os.O_WRONLY | os.O_CREAT
lf_mode = stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH # This is 0o222, i.e. 146
# Create lock file
# Regarding umask, see https://stackoverflow.com/a/15015748/832230
umask_original = os.umask(0)
try:
lf_fd = os.open(lf_path, lf_flags, lf_mode)
finally:
os.umask(umask_original)
# Try locking the file
try:
fcntl.lockf(lf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
msg = ('Error: {} may already be running. Only one instance of it '
'can run at a time.'
).format('appname')
exit(msg)
Ограничением вышеприведенного кода является то, что если файл блокировки уже существовал с неожиданными разрешениями, эти разрешения не будут исправлены.
Я бы хотел использовать /var/run/<appname>/
в качестве каталога для файла блокировки, но для создания этого каталога требуются разрешения root
. Вы можете сами решить, какой каталог использовать.
Обратите внимание, что нет необходимости открывать дескриптор файла для файла блокировки.