Хочу предложить патч, родившийся в результате ковыряния в вопросе, описанном в http://lists.altlinux.org/pipermail/sisyphus/2005-October/071563.html Получилось несколько больше, чем планировалось. Смысл изменений в следующем. 1) На время выполнения ifup/ifdown создается лок файл в директории /var/lock/etcnet. Для таких целей: - Предотвращает одновременное выполнение ifup/ifdown для одного и того же интерфейса. Если 2 и более таких процесса вдруг запущены, то они теперь будут выполняться последовательно. - Наличие лок файла является для других заинтересованных процессов признаком, что поднятие/опускание интерфейса находится в процессе. Если кому-то нужен доступ к конкретному интерфейсу, то этот кто-то должен дождаться удаления лок файла прежде чем работать. 2) Добавлен скрипт /etc/net/scripts/ifconfig-ipv4 для возможности переконфигурирования интерфейса из командной строки по ходу работы. Например, когда руками или каким другим образом сломали таблицу маршрутизации для конкретного интерфейса, она может быть восстановлена из ipv4route без ifdown iface; ifup iface. Скрипт настраивает окружение и вызывает существующий /etc/net/scripts/config-ipv4 3) Добавлены скрипты /etc/ppp/ip-{up,down}.d/etcnet для лучшего интегрирования с pppd. - При поднятии интерфейса обеспечивается конфигурирование в соответствии с параметрами в конфигурационных файлах интерфейса, в частности ipv4route - При необходимости собственных скриптов ip-up/ip-down - вместо них все, что надо выполнить достаточно прописать в ifup-post/ifdown-pre скриптах в конфигурационном директории интерфейса. Собственно, это работало и раньше, НО только при выполнении ifup/ifdown. Если ppp интерфейс в ходе работы пересоздается, например когда pppd восстанавливает потерянное соединение в соответствии с опцией persist, то возникают проблемы (см. ссылку выше). Сам скрипт ip-up.d/etcnet работает следующим образом: проверяет, что интерфейс поднят через /etc/net (по ipparam, с которым запускается pppd и по наличию конфигурационного директория интерфейса), если нет, то выходит. Проверяет, не выполняется ли ifup/ifdown данного интерфейса (по наличию лок файла), если да, то выходит (ifup/ifdown сами все сделают). Потом лезет в конфигурационный директорий интерфейса и работает дальше.
Created attachment 1251 [details] Собственно патч Новые файлы /etc/net/scripts/ifconfig-ipv4 /etc/ppp/ip-{up,down}.d/etcnet должны быть executable
Спасибо, я посмотрю.
По поводу пункта 1: хорошая мысль, я раньше не знал, чем это реализовать. По поводу пункта 2: зачем ограничиваться IPv4? И наверное, лучше будет ifup изменить так, чтобы он для уже поднятого интерфейса проверял его соответствие конфигурации.
(In reply to comment #3) > По поводу пункта 2: зачем ограничиваться IPv4? Я этим ограничился _пока_, только лишь для решения наболевшей у меня конкретной проблемы с ppp интерфейсами (некоторыми) -- собственно пункт 2 можно считать побочным эффектом пункта 3 :) Что касается остального -- можно считать, что оно в состоянии вялотекущего TODO. На данный момент я сделал то, на что сам нарывался и смог некоторое время погонять-оттестить. > И наверное, лучше будет ifup изменить так, чтобы он для уже поднятого > интерфейса проверял его соответствие конфигурации. Совершенно согласен. Но раз уж я пока ограничился только IPv4, то возложить это сразу на ifup было бы не честно. Дабы ничего не сломать (одинаковых правил iptables к примеру не размножить)
> И наверное, лучше будет ifup изменить так, чтобы он для уже поднятого > интерфейса проверял его соответствие конфигурации. А вот еще осенило. Что все-таки не ifup, а отдельный скрипт (какой-нибудь ifcheck), который проверяет соответствие состояния интерфейса его конфигурации. Вот он пускай и восстанавливает состояние интерфейса. А еще ему опцию придумать, чтобы наоборот -- сохранял текущее состояние в конфигах... Ну и опцию -- просто докладывать про несоответствия (вспоминая service network status).
В патче ошибочка вышла. В пропатченных if{up,down} необходимо исправление: -trap 'rm -f "$IFACE_LOCK_FILE" ' EXIT SIGHUP SIGTERM SIGINT +trap 'rm -f "$IFACE_LOCK_FILE" ' EXIT
(1) пока не принимается, так как появляется зависимость на procmail
(In reply to comment #7) > (1) пока не принимается, так как появляется зависимость на procmail Плохо. Все остальное использует лок-файлы, которые этим (1) создаются. Чтобы отзависимости на procmail уйти, может вместо /usr/bin/lockfile свой скрипт аналогичный сочинить? Типа такого /etc/net/scripts/lockfile.sh: ----------------- #!/bin/bash test $# -ge 1 || exit 1 umask 333 while ! echo $$ > "$1" 2>/dev/null do sleep 1 done ----------------- Это только идея, если принимается, то я могу довести этот скрипт до ума. В таком виде он, например от рута не будет работать -- файл в любом случае перезапишется. Ну и надо какого-то системного пользователя завести (или назначить), которому лок-файлы будут принадлежать...
Created attachment 1316 [details] Скрипт /etc/net/scripts/lockfile.sh Этот скрипт можно использовать вместо /usr/bin/lockfile для ухода от зависимости на procmail. Он использует только утилиты из coreutils, на который уже есть зависимость. Дополнительно скрипту можно передавать в параметрах pid процесса, который будет записан в локфайл. Соответственно в пропатченных if{up,down} заменить: - /usr/bin/lockfile "$IFACE_LOCK_FILE" || exit 3 + ${SCRIPTDIR}/lockfile.sh -p $$ "$IFACE_LOCK_FILE" || exit 3
Состояние на etcnet 0.9.35-alt1: блокировок в ifup/ifdown по-прежнему нет (ни flock, ни lockfile), пункты 2 и 3 предложения тоже не реализованы. Патч 2005 года к 0.7.x не применим, а его зависимость на procmail (lockfile) была причиной отказа (комментарий 7). Предлагаю пункт 1 через flock(1) из util-linux (в базовой системе): ifup/ifdown/ifup-removable/ifdown-removable перезапускают себя под `flock -o /run/etcnet.lock`; вложенные вызовы (ifup_parents/ifdown_children) пропускают блокировку по ETCNET_LOCK_HELD; -o закрывает дескриптор лока у потомков, чтобы dhcp-клиенты/ifplugd/pppd не держали его вечно. Проверено в podman (dummy-интерфейсы, dummy1 REQUIRES=dummy0): вложенный ifup dummy0 из ifup dummy1 не блокируется сам на себя, во время работы ifup лок занят (flock -n → 1), после — свободен, одновременные ifup/ifdown одного интерфейса выполняются последовательно, network.init reload работает. Serialize ifup/ifdown with flock(1) --- a/etc/net/scripts/ifup +++ b/etc/net/scripts/ifup @@ -15,6 +15,16 @@ [ -z "$1" ] && usage export NAME=$1 +# Serialize ifup/ifdown system-wide: the initscript, udev/hotplug, ifplugd +# and pppd hooks may call them concurrently, even for the same interface. +# Nested calls (parents/children) inherit ETCNET_LOCK_HELD and skip locking; +# flock -o closes the lock descriptor in the child, so daemons started from +# here (dhcp clients, ifplugd, pppd) do not keep the lock forever. +if [ -z "$ETCNET_LOCK_HELD" ] && [ -x /usr/bin/flock ]; then + export ETCNET_LOCK_HELD=1 + exec /usr/bin/flock -o /run/etcnet.lock "$0" "$@" +fi + if [ -z "$SCRIPTDIR" ]; then export SCRIPTDIR=/etc/net/scripts . $SCRIPTDIR/functions --- a/etc/net/scripts/ifdown +++ b/etc/net/scripts/ifdown @@ -11,6 +11,16 @@ [ -z "$1" ] && usage export NAME=$1 +# Serialize ifup/ifdown system-wide: the initscript, udev/hotplug, ifplugd +# and pppd hooks may call them concurrently, even for the same interface. +# Nested calls (parents/children) inherit ETCNET_LOCK_HELD and skip locking; +# flock -o closes the lock descriptor in the child, so daemons started from +# here (dhcp clients, ifplugd, pppd) do not keep the lock forever. +if [ -z "$ETCNET_LOCK_HELD" ] && [ -x /usr/bin/flock ]; then + export ETCNET_LOCK_HELD=1 + exec /usr/bin/flock -o /run/etcnet.lock "$0" "$@" +fi + if [ -z "$SCRIPTDIR" ]; then export SCRIPTDIR=/etc/net/scripts . $SCRIPTDIR/functions --- a/etc/net/scripts/ifup-removable +++ b/etc/net/scripts/ifup-removable @@ -18,6 +18,16 @@ [ -z "$1" ] && usage NAME=$1 CALLER=${2:?$0: missing 2nd arg} + +# Serialize ifup/ifdown system-wide: the initscript, udev/hotplug, ifplugd +# and pppd hooks may call them concurrently, even for the same interface. +# Nested calls (parents/children) inherit ETCNET_LOCK_HELD and skip locking; +# flock -o closes the lock descriptor in the child, so daemons started from +# here (dhcp clients, ifplugd, pppd) do not keep the lock forever. +if [ -z "$ETCNET_LOCK_HELD" ] && [ -x /usr/bin/flock ]; then + export ETCNET_LOCK_HELD=1 + exec /usr/bin/flock -o /run/etcnet.lock "$0" "$@" +fi . ${SCRIPTDIR:=/etc/net/scripts}/functions case "$CALLER" in --- a/etc/net/scripts/ifdown-removable +++ b/etc/net/scripts/ifdown-removable @@ -15,6 +15,16 @@ [ -z "$1" ] && usage NAME=$1 CALLER=${2:?$0: missing 2nd arg} + +# Serialize ifup/ifdown system-wide: the initscript, udev/hotplug, ifplugd +# and pppd hooks may call them concurrently, even for the same interface. +# Nested calls (parents/children) inherit ETCNET_LOCK_HELD and skip locking; +# flock -o closes the lock descriptor in the child, so daemons started from +# here (dhcp clients, ifplugd, pppd) do not keep the lock forever. +if [ -z "$ETCNET_LOCK_HELD" ] && [ -x /usr/bin/flock ]; then + export ETCNET_LOCK_HELD=1 + exec /usr/bin/flock -o /run/etcnet.lock "$0" "$@" +fi [ -z "$SCRIPTDIR" ] && . ${SCRIPTDIR:=/etc/net/scripts}/functions case "$CALLER" in