Что лучший способ состоит в том, чтобы гарантировать, что только один экземпляр сценария Bash работает? [дубликат]

Я реализовал синтаксический анализатор с рекурсивным спуском в Java в Синтаксический анализатор MathEclipse проект. Это могло также использоваться в в качестве модуль Google Web Toolkit

99
задан codeforester 11 January 2017 в 01:57
поделиться

6 ответов

Если сценарий одинаков для всех пользователей, вы можете использовать подход файл блокировки . Если вы получили блокировку, продолжайте, иначе покажите сообщение и выйдите.

В качестве примера:

[Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"

[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $ 

После того, как /tmp/the.lock будет получен, ваш скрипт будет единственным, у кого есть доступ к исполнение. Когда вы закончите, просто снимите замок. В форме сценария это может выглядеть так:

#!/bin/bash

lockfile -r 0 /tmp/the.lock || exit 1

# Do stuff here

rm -f /tmp/the.lock
101
ответ дан 24 November 2019 в 04:58
поделиться

из вашего скрипта:

ps -ef | grep $0 | grep $(whoami)
-2
ответ дан 24 November 2019 в 04:58
поделиться

Я не уверен, что существует надежное однострочное решение, так что вы можете в конечном итоге свернуть свой собственный.

Lockfiles несовершенны, но в меньшей степени, чем при использовании 'ps | grep | grep -v 'pipelines.

Сказав это, вы могли бы подумать о сохранении контроля над процессом отдельно от вашего скрипта - имейте стартовый скрипт. Или, по крайней мере, разложите его на функции, хранящиеся в отдельном файле, так что в вызывающем скрипте вы можете иметь:

. my_script_control.ksh

# Function exits if cannot start due to lockfile or prior running instance.
my_start_me_up lockfile_name;
trap "rm -f $lockfile_name; exit" 0 2 3 15

в каждом скрипте, которому нужна управляющая логика. Ловушка гарантирует, что файл блокировки будет удален при выходе вызывающего объекта, поэтому вам не нужно кодировать это в каждой точке выхода в скрипте.

Использование отдельного управляющего скрипта означает, что вы можете проверить работоспособность на крайние случаи: удалите устаревшие файлы журнала, убедитесь, что файл блокировки правильно связан с текущий запущенный экземпляр сценария, дать возможность убить запущенный процесс и так далее. Это также означает, что у вас больше шансов успешно использовать команду grep для вывода ps . Команда ps-grep может использоваться для проверки того, что с файлом блокировки связан запущенный процесс. Возможно, вы могли бы назвать свои файлы блокировок каким-либо образом, чтобы включить информацию о процессе: user, pid и т. д., которые могут использоваться при последующем вызове сценария, чтобы решить, будет ли процесс файл блокировки все еще существует.

3
ответ дан 24 November 2019 в 04:58
поделиться

Я нашел довольно простой способ справиться с «одной копией скрипта на систему». Однако это не позволяет мне запускать несколько копий скрипта из многих учетных записей (то есть в стандартном Linux).

Решение:

В начале скрипта я дал:

pidof -s -o '%PPID' -x $( basename $0 ) > /dev/null 2>&1 && exit

Очевидно pidof отлично работает в том смысле, что:

  • у него нет ограничений на имя программы вроде ps -C ...
  • мне не нужно делать grep -v grep (или что-то подобное)

И он не полагается на файлы блокировки, что для меня является большой победой, потому что ретрансляция на них означает, что вам нужно добавить обработку устаревших файлов блокировки - что на самом деле не сложно, но если этого можно избежать - почему бы и нет?

Что касается проверки с «одной копией скрипта на каждого работающего пользователя», я написал это, но меня это не слишком устраивает:

(
    pidof -s -o '%PPID' -x $( basename $0 ) | tr ' ' '\n'
    ps xo pid= | tr -cd '[0-9\n]'
) | sort | uniq -d

, а затем я проверяю его вывод - если он пуст - нет копий скрипта от того же пользователя.

-1
ответ дан 24 November 2019 в 04:58
поделиться

Advisory locking has been used for ages and can be used in bash scripts. Я предпочитаю простой flock (из util-linux[-ng]), а не lockfile (из procmail). И всегда помните о ловушке на выходе (sigspec == EXIT или 0, ловушка специфических сигналов лишняя) в этих скриптах.

В 2009 году я выпустил свой блокируемый boilerplate скрипта (изначально доступный на моей вики-странице, теперь доступный как gist). Преобразование этого скрипта в одноэтапный - это тривиально. Используя его, вы также можете легко писать скрипты для других сценариев, требующих некоторой блокировки или синхронизации.

Вот упомянутая шаблонная версия для вашего удобства.

#!/bin/bash
# SPDX-License-Identifier: MIT

## Copyright (C) 2009 Przemyslaw Pawelczyk <przemoc@gmail.com>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate

### HEADER ###

LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99

# PRIVATE
_lock()             { flock -$1 $LOCKFD; }
_no_more_locking()  { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking()  { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }

# ON START
_prepare_locking

# PUBLIC
exlock_now()        { _lock xn; }  # obtain an exclusive lock immediately or fail
exlock()            { _lock x; }   # obtain an exclusive lock
shlock()            { _lock s; }   # obtain a shared lock
unlock()            { _lock u; }   # drop a lock

### BEGIN OF SCRIPT ###

# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1

# Remember! Lock file is removed when one of the scripts exits and it is
#           the only script holding the lock or lock is not acquired at all.
139
ответ дан 24 November 2019 в 04:58
поделиться

В дистрибутивах Ubuntu / Debian есть инструмент start-stop-daemon , который предназначен для той же цели, которую вы описываете. См. Также /etc/init.d/skeleton , чтобы узнать, как он используется при написании сценариев запуска / остановки.

- Ной

1
ответ дан 24 November 2019 в 04:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: