Проверьте на Процесс, если То же Работает

Ядро сохраняет данные кэшируемыми в памяти, считывание данных очень важно (кто-то ожидает его), записи могут делаться лениво (никто не торопит Вас; данные просто могли бы использоваться снова/изменил снова). Поскольку устройства могут или читать или писать за один раз, это окупается для задержки записи как можно больше. Таким образом, данные записаны "добровольно" ядром, только если нет никакого выхода (нуждайтесь в пространстве теперь). Можно форсировать события вводными файлами синхронно (запись, как только что-либо изменяется), путем вызова fsync(2) на файле для вытеснения данных. При размонтировании устройства очевидно, все данные, кэшируемые для него, должны быть выписаны заранее.

Вышеупомянутое должно дать, Вы дрожите, поскольку машина могла бы отказать в любое время и оставить много незаписанных данных. Именно поэтому существует названная программа sync(1), который заставляет ядро выписать все кэшируемые данные файла. Это обычно настраивается так, это работает периодически (обычно каждые 5 секунд или так) для предотвращения потери данных, как описано. Необходимо было бы проверить документацию распределения, как точно это настраивают или настраивают.

4
01.03.2014, 14:28
6 ответов

Вы можете использовать этот лайнер, чтобы делать то, что хотите:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )

Пример

Скажем, у меня был этот скрипт:

$ cat script.bash 
#!/bin/bash

echo "Hello World"
sleep 10

Если мы используем наш единственный лайнер:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )
Hello World
$

Мы запускаем его снова:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )
10197
already running
$

Подождав 10 секунд и запустив снова, он снова работает:

$ pgrep script.bash && echo "already running" || ( ./script.bash & )
Hello World
$
7
27.01.2020, 20:46

Есть много способов сделать это. Я предпочитаю, чтобы скрипт не запускал одни и те же копии сам по себе, сохраняя их pid.

Одним из удобных методов является pidof

$ pidof -x /bin/yourscript || /bin/yourscript  

с самопроверкой ps

$ ps aux|grep -q /bin/yourscript || /bin/yourscript

#!/bin/sh

NAME=$(basename $0)

if ps -p `cat /var/run/$NAME".pid` >/dev/null 2>&1; then
   echo "script already running"
   exit 1
fi

echo $$ > /var/run/$NAME".pid"

...
rm /var/run/$NAME".pid"

, есть много других скриптов. Например, solo

1
27.01.2020, 20:46

Обратите внимание, что этот ответ ориентирован на самопроверяющийся скрипт, для ручной проверки запущен ли процесс перед попыткой запустить его из командной строки, смотрите ответ slm.

Самый простой способ - использовать pgrep, если он доступен:

if pgrep "$0" >/dev/null
then
  echo "$0 is already running" 2>&1
  exit 1
fi

Если нет, вы можете использовать комбинацию ps и grep:

if ps -Ao comm | grep -q "^$0\$"
then
  echo "$0 is already running" 2>&1
  exit 1
fi

Однако надежнее использовать файл блокировки, поскольку всегда есть вероятность, что процесс запущен под другим именем. Вот пример с использованием flock:

lockfile=/var/lock/mprog
{
  if ! flock -n 9
  then
    echo "Unable to lock $lockfile, exiting" 2>&1
    exit 1
  fi

  # do stuff here

} 9>"$lockfile"
6
27.01.2020, 20:46

Тот факт, что сделать что-то подобное надежно в Unix в целом невозможно, был одной из причин, побудивших к разработке инструментов. например systemd (он использует специфичную для Linux функцию cgroups, чтобы отсекать процессы и, таким образом, держать их под строгим контролем, включая перезапуск по мере необходимости). Вы можете что-то сколотить, используя ps (1) или pgrep (1), спрятав PID в файл и проверив его, и так далее. Но все они подвержены гонкам, обману или явным ошибкам.

Вы должны изучить свои потребности и посмотреть, насколько это важно, если что-то пойдет не так, насколько это повторяется (стоит ли автоматизировать, или это что-то делается то и дело?), Насколько это интересно для потенциальных злоумышленников. , и так далее.

0
27.01.2020, 20:46

Использование каталога блокировки:

#!/bin/sh

lockdir=${TMPDIR:-/tmp}/mylock

if ! mkdir "$lockdir" 2>/dev/null; then
    exit 1
fi

trap 'rmdir "$lockdir" 2>/dev/null' EXIT HUP INT TERM

# The rest of code goes here.

Использование каталога блокировки безопаснее, чем использование файла блокировки. Если вы используете файл, вам нужно будет выполнить отдельную проверку существования файла перед его созданием. В промежутке между этими двумя операциями другой экземпляр скрипта может попытаться сделать то же самое. Утилита mkdirпредоставляет атомарную операцию «создать -, если -не -существует».

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


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

#!/bin/sh

lockdir=${TMPDIR:-/tmp}/mylock

if { read pid <"$lockdir/pid" && ! kill -0 "$pid"; } 2>/dev/null then
    printf 'Detected left-over lock "%s"\n' "$lockdir" >&2
    exit 1
fi

if ! mkdir "$lockdir" 2>/dev/null; then
    echo 'Could not get lock' >&2
    exit 1
fi

printf '%d\n' "$$" >"$lockdir/pid"

trap '{ rm "$lockdir/pid" && rmdir "$lockdir"; } 2>/dev/null' EXIT HUP INT TERM

# The rest of code goes here.

Команда ! kill -0 "$pid"будет истинной, если $pidне относится к идентификатору процесса, который в настоящее время выделен для запущенного процесса.

0
27.01.2020, 20:46

У меня была похожая проблема. Самым простым решением, которое я нашел, было проверить наличие файла check _running.txt в каталоге. если файл существует; то скрипт уже запущен, Затем инициализируйте файл, и в конце вашего скрипта rm файл из каталога. Таким образом, пока файл находится в каталоге, скрипт работает.

if [[ -f check_running.txt ]]; then 
  echo "already running"
  exit 
fi

touch check_running.txt 
...
...
...
rm check_running.txt 

Я считаю, что это можно реализовать и с помощью переменной флага.

0
27.01.2020, 20:46

Теги

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