Последовательный запуск команд из Крона

Если добавить фоновые задачи в Крон, есть риск, что они будут перекрываться при выполнении. В таком случае скрипты могут работать некорректно или просто жрать лишние ресурсы. Для гарантии последовательного запуска сделал blocker.sh.

Использование:

*/10 * * * * /usr/local/bin/blocker.sh job_id "/var/www/Envs/prj/command_name command_parameters"

Он не позволит запускаться двум задачам с одним job_id.
С помощью job_id можно объединять и несколько задач, которые не должны выполняться одновременно.
В своей работе скрипт опирается на использование временного файла с pid процесса. Он создается в /tmp. Если при старте есть файл, соответствующий job_id, то он проверяет, запущен ли процесс с pid, который указан в файле. Если да, новый экземпляр не запускается.
Если запуск разрешен, создается временный файл, запускается процесс, а по завершении файл удаляется.
Сам код:

name=$1
case "$name" in
  */*)
    echo "Command ID can't use slashes"
    exit 1
esac
file="/tmp/blocker-"$1
if [ -e $file ]
then
  pid=`cat $file`
  lines=`ps $pid | wc -l`
  if [ $lines -gt 1 ]
  then
    echo "Another instance of $name is already running"
    exit 1
  fi
fi

pid=$$
echo $pid > $file
$2
rm $file

Проверка на наличие слэша в job_id нужна, чтобы уменьшить вероятность указания реального файла вместо идентификатора. Проверка через case работает и в /bin/sh.

Advertisements
Последовательный запуск команд из Крона

Управление разными версиями Postgresql с помощью Ansible

Я очень люблю использовать Ансибль для управления серверами. Недавно столкнулся с проблемой при настройке репликации Постгреса. Для ее настройки нужно редактировать файл pg_hba.conf. Сложность в том, что Постгрес ставит свои файлы в папку с номером версии, например, /etc/postgresql/9.2/. Как написать плейбук, чтобы Ансибль нашел конфиг?

Поиск в инете не принес результата. Кто-то хардкодил путь в плейбуке, кто-то выносил номер версии в константы. Мне оба эти способа не понравились.

Придуманное решение основывается на использовании модулей shell, fail и set_fact.

С помощью shell смотрим, что лежит в /etc/postgresql. В директиве register можно указать имя переменной, куда надо сохранить объект, содержащий сведения о выполнении команды. В этом объекте будет содержаться и ее вывод.

fail проверяет, что в списке только один элемент. Если это не так, то мы не можем надежно определить номер версии, и надо прервать работу.

set_fact сохраняет нужный нам единственный элемент в отдельную переменную. Ее мы и используем в дальнейшем.

Сам код:

- name: get postgres version
  shell: ls -1 /etc/postgresql
  register: postgres_versions

- name: check one version is present
  fail: msg="Can't get postgresql version"
  when: postgres_versions.stdout_lines|length != 1

- name: store postgres version
  set_fact: postgres_version="{{ postgres_versions.stdout_lines[0] }}"

- name: update pg_hba if replication
  lineinfile: dest=/etc/postgresql/{{ postgres_version }}/main/pg_hba.conf regexp="^#?\s*host    replication    postgres" line="host    replication    postgres    {{ hot_standby_ip }}/32    trust" state=present
  notify: restart postgresql
Управление разными версиями Postgresql с помощью Ansible