Новий -C
варіант не є задовільним, оскільки він відкритий для перегонів час перевірки до часу використання (TOCTTOU). Якщо два процеси намагаються додати одне і те ж правило приблизно в один і той же час, -C
це не захистить їх від додавання його двічі.
Отже, це насправді не краще grep
рішення. Точне завдання обробки тексту над висновком файлу iptables-save
може працювати так само надійно -C
, оскільки цей вихід є надійним оглядом стану таблиць.
Необхідний --ensure
варіант, який атомно перевіряє та додає правило, лише якщо воно ще не існує. Більше того, було б непогано, якби правило було переміщено до правильної позиції, куди було б вставлено нове правило, якщо воно ще не існувало ( --ensure-move
). Наприклад, якщо iptables -I 1
воно використовується для створення правила на чолі ланцюга, але це правило існує вже в сьомому положенні, тоді існуюче правило повинне перейти до першого положення.
Без цих особливостей я думаю, що можливим вирішенням є написання циклу сценарію оболонки на основі цього псевдокоду:
while true ; do
# delete all copies of the rule first
while copies_of_rule_exist ; do
iptables -D $RULE
done
# now try to add the rule
iptables -A $RULE # or -I
# At this point there may be duplicates due to races.
# Bail out of loop if there is exactly one, otherwise
# start again.
if exactly_one_copy_of_rule_exists ; then
break;
fi
done
Цей код може крутитися навколо; це не гарантує, що два або більше гонщиків вийдуть за фіксовану кількість ітерацій. Щоб допомогти в цьому, можна додати кілька випадкових сплячих показників.