Мне ничего не известно о такой утилите. Однако ваш подход несовершенен (, и я согласен, что его очень трудно понять правильно ).
Модификатор :a
вычисляет абсолютный путь без доступа к файловой системе. В частности, он заменяет a/b/..
на a
независимо от того, является ли a/b
символической ссылкой или нет.
Если у вас есть символическая ссылка /a/b ->../foo
, это /foo
, только если /a
не является символической ссылкой. Даже если вы канонизируете $(dirname $1)
, это все равно не будет работать для символических ссылок, таких как /a/b -> x/../../foo
, если x
сам по себе является символической ссылкой.
В вашем случае:
/tmp/example/A/B/C/D/symlink-0 ->../../symlink-1/b/c/d/target
разрешается в /tmp/example/A/B/symlink-1/b/c/d/target
только потому, что ни /tmp/example/A/B/C/D
, ни /tmp/example/A/B/C
не являются символическими ссылками.
Другими словами, чтобы получить абсолютный путь к цели символической ссылки, не содержащей компонентов ..
, вам может потребоваться разрешить более одной символической ссылки, и вы не можете сделать это в одиночку, комбинируя путь к файлу и цель символической ссылки.
Если вам нужен такой путь, самый простой (и, я бы сказал, единственно разумный и/или полезный )подход — это получить канонический путь этой цели символической ссылки, где все компоненты пути не являются ни ..
, .
, ни символическими ссылками, за исключением, возможно, последнего. Для этого вы можете:
zmodload -F zsh/stat b:zstat
canonicalize1() {
if [ -L "$1" ]; then
local link
zstat -A link +link -- "$1" || return
case $link in
(/*) ;;
(*)
case $1:h in
(*/) link=$1:h$link;;
(*) link=$1:h/$link;;
esac;;
esac
printf '%s\n' $link:h:A/$link:t
else
printf '%s\n' $1:A
fi
}
На ваших символических ссылках /tmp/example/A/B/C/D/symlink-0
это по-прежнему дает /tmp/example/a/b/c/d/target
, так как цель символической ссылки не является символической ссылкой, но если это не то, что вы хотите,то я спрашивал :, какой результат вы бы хотели получить при выполнении:
canonicalize1 /tmp/x/y
Где /tmp/x/y
— символическая ссылка на ../foo
, а /tmp/x
— символическая ссылка на /a/b/c
, а /a
, /a/b
, /a/b/c
— тоже символические ссылки?
Во-первых, я бы порекомендовал использовать специальный инструмент, работающий на сервере D, который прослушивает пакеты UDP и дважды отправляет копию, одну для A и одну для B.Это можно сделать, например, с помощью замены процесса bash + tee + socat(примера, свободно адаптированного изudp-multi-socat.sh
с его удобным обратным порядком, чтобы tee немедленно запускается ), но я не знаю, может ли некоторая буферизация не происходить в некоторых случаях (лучше создать специальное приложение):
socat -U - udp4-recv:3070 | tee >(socat -u - udp4-datagram:167.111.111.111:5640) | socat -u - udp4-datagram:192.111.111.111:5640
Теперь, когда сказано, что для метода «помощь ядра -» существует цель iptablesTEE , которая может дублировать пакеты. Поскольку дублирование должно обходить обычную обработку маршрутизации, необходимо «эвакуировать» дублированный пакет на другой хост, напрямую доступный (параметр--шлюза ). Без этого, похоже, нет хорошего способа обработки скопированного пакета с помощью TEE .
Достаточно честно, мы можем просто создать этот хост, используя сетевое пространство имен. Затем верните продублированный трафик обратно на хост D через стек маршрутизации и iptables, которые теперь могут использовать для него другую ДНК (, потому что он пришел с другого интерфейса ). Из-за асимметричной маршрутизации и дублирования потока необходимо выполнить некоторые настройки (свободный rp _фильтр на виртуальном интерфейсе и другую зону conntrack (origin )чтобы различать потоки, потому что conntrack знает только об IP-адресах, а не об интерфейсах)
Вот конфигурация для использования на сервере D (возможно, можно было бы избежать некоторого дублирования, но это было бы менее читабельно):
ip netns del dup 2>/dev/null || : # to remove previous instance, if needed
ip netns add dup
ip link add name dup1 type veth peer netns dup name eth0
ip link set dup1 up
ip -n dup link set eth0 up
ip address add 10.10.10.1/24 dev dup1
ip -n dup address add 10.10.10.2/24 dev eth0
ip -n dup route add default via 10.10.10.1
sysctl -q -w net.ipv4.conf.dup1.rp_filter=2
ip netns exec dup sysctl -q -w net.ipv4.conf.eth0.forwarding=1
iptables -t mangle -A PREROUTING -i eth0 -p udp --dport 3070 -j TEE --gateway 10.10.10.2
iptables -t raw -A PREROUTING -i dup1 -p udp --dport 3070 -j CT --zone-orig 1
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 3070 -j DNAT --to-destination 192.111.111.111:5640
iptables -t nat -A PREROUTING -i dup1 -p udp --dport 3070 -j DNAT --to-destination 167.111.111.111:5640
С помощью этого метода даже ответы от A и B могут быть отправлены обратно на C (, который будет думать, что они оба пришли из одного и того же начального пункта назначения ), если это вообще имеет смысл. Таким образом, если ничего не прослушивается на A или B, источнику C будет отправлено ICMP-порт назначения недостижим .который может прервать :дополнительный брандмауэр, чтобы избежать этого, вероятно, следует где-то добавить.