Запуск программы изнутри bash, не удается правильно выбрать место

Я пишу bash-скрипт на Mac OSX 10.11, чтобы автоматически использовать dns-sd для "прокси" рекламы Bonjour для AFP, SMB и некоторых принтеров при подключении к VPN.

Основная суть моего сценария заключается в том, что я объявляю несколько массивов для последующего использования при вызове dns-sd. Массив у меня возникли трудности с тем, чтобы быть:

SERVICE_TEXTS=(
''
''
model=TimeCapsule8,119
model=Xserve
'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F'
'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty="Brother MFC-9120CN" product="(Brother MFC-9120CN)" adminurl=http://BRN001BA9243652.local./ priority=75 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F'
'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp ty="Brother MFC-9120CN" product="(Brother MFC-9120CN)" adminurl=http://BRN001BA9243652.local./ priority=25 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=F TBCP=T'
)

Чтобы определить, нужно ли мне на самом деле запустить dns-sd, я делаю:

ifconfig ppp0 &>/dev/null

Проверьте возвращаемое значение ifconfig с помощью:

if [ "$?" -eq "0" ]; then...

При условии, что существует ppp0, я проверяю длину моего массива, проверяя, запущен ли в данный момент dns-sd, и так далее.

Если экземпляры dns-sd были запущены, но ppp0 сейчас недоступен, я уничтожаю их все с помощью PID, который сохраняю, и проверяю снова через несколько минут.

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

dns-sd -P "${SERVICE_NAMES[$n]}" "${SERVICE_TYPES[$n]}" local ${SERVICE_PORTS[$n]} "${SERVICE_NAMES[$n]}.local" "${SERVICE_IPS[$n]}" ${SERVICE_TEXTS[$n]} &>/dev/null &

Страница man для dns-sd показывает, что это использование -P, для ясности.

dns-sd -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...]              (Proxy)

Проблема, с которой я сталкиваюсь, - это поведение пробелов в последних трех элементах SERVICE_TEXTS. Устранение неполадок до сих пор заключалось в том, чтобы сделать все в терминале, чтобы удостовериться, что я не пропускаю что-то супер очевидное / схожу с ума. Вот именно то, что я печатаю, и именно то, что возвращается... Что работает

$ dns-sd -P "Brother MFC-9129CN" _ipp._tcp local 631 "Brother MFC-9120CN.local" 192.168.1.2 txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother\ MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F

Registering Service Brother MFC-9129CN._ipp._tcp.local host Brother MFC-9120CN.local port 631 TXT txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother\ MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F
DATE: ---Sat 03 Oct 2015---
21:11:40.927  ...STARTING...
21:11:41.818  Got a reply for record Brother MFC-9120CN.local: Name now registered and active
21:11:41.818  Got a reply for service Brother MFC-9129CN._ipp._tcp.local.: Name now registered and active

Однако, когда я использую переменную в команде (echo'd для ясности)... Это происходит

$ echo ${SERVICE_TEXTS[4]}
txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\ MFC-9120CN product=\(Brother MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F

$ dns-sd -P "Brother MFC-9129CN" _ipp._tcp local 631 "Brother MFC-9120CN.local" 192.168.1.2  ${SERVICE_TEXTS[4]}

Registering Service Brother MFC-9129CN._ipp._tcp.local host Brother MFC-9120CN.local port 631 TXT txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty=Brother\\\\ MFC-9120CN product=\(Brother MFC-9120CN\) adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F
DATE: ---Sat 03 Oct 2015---
21:18:56.968  ...STARTING...
21:18:57.842  Got a reply for record Brother MFC-9120CN.local: Name now registered and active
21:18:57.842  Got a reply for service Brother MFC-9129CN._ipp._tcp.local.: Name now registered and active

Проблема в том, что раздел элемента 4, который идет

"...ty=Brother\ MFC..."

dns-sd сообщает об этом как

"...ty=Brother\\\\ MFC..."

Вы заметите, когда я просто набираю строку, а не использую переменную, dns-sd сообщает об этом одним "\".

Очевидно, что четыре "\" не приносят мне никакой пользы... Если я уберу "\", я все равно не получу желаемый результат, потому что dns-sd думает, что я описываю новый ключ. Я печатаю

"\\"

чтобы попытаться получить буквальное "\" и из памяти dns-sd по-прежнему получает четыре.

Я также играл с одинарными и двойными кавычками, включая окружение переменной в вызове dns-sd в двойных кавычках, но это добавляет обратную косую черту к каждому пробелу. Это заставляет dns-sd обрабатывать строку TXT как один ключ с одним значением, где значение содержит пробелы. Это значительно менее полезно, чем называть его без кавычек, поэтому я отказался от дальнейшего исследования.

Так что, в основном, кажется, что dns-sd не получает ни одного, ни четырех "\"... И ему просто нужен один, тогда все будет работать отлично...

Вызов dns-sd и передача ${SERVICE_TEXTS[$n]} без кавычек очень близка к желаемому поведению, но не может обрабатывать символы пробела в "значении" пар ключ-значение.

Любое руководство здесь будет высоко ценится! Я перебираю руководство по bash, ищу обмен стека и пробую все, что могу придумать, чтобы эта работа продолжалась 4 часа:(

1 ответ

Таким образом, с помощью блоггера, где я получил вдохновение для этого сценария, проблема решена.

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

Как и предполагал приют, это был случай, когда dnd-sd получил что-то вроде "key=value key=value with spaces" вместо key=value key="value with spaces" key=valueWithoutSpaces

Проблема, с которой я столкнулся, заключалась в том, что мне было трудно увидеть команду EXACT, которая будет выполняться внутри моего скрипта, поскольку dns-sd, похоже, тоже выполнял некоторые экранирования. Отсюда было бы намного проще определить, на чем конкретно сосредоточить свои усилия, чтобы поиграть с цитатой.

Чтобы проверить это, было предложено использовать что-то вроде этого

#FIX: by using a temporary variable we can debug the exact command that will be used including all quotes
CMD="dns-sd -P \"${SERVICE_NAMES[$n]}\" ${SERVICE_TYPES[$n]} local ${SERVICE_PORTS[$n]} \"${SERVICE_NAMES[$n]}.local\" \"${SERVICE_IPS[$n]}\" ${SERVICE_TEXTS[$n]} &>/dev/null &"
echo "DEBUG: $CMD"

# use exactly this command 
eval $CMD
PIDS[$n]=$!;

И полученный ключ SERVICE_TEXTS[4], который работал

'txtvers=1 qtotal=1 pdl=application/vnd.hp-PCL,application/vnd.brother-hbp rp=duerqxesz5090 ty="Brother MFC-9120CN" product="(Brother MFC-9120CN)" adminurl=http://BRN001BA9243652.local./ priority=50 usb_MFG=Brother usb_MDL=MFC-9120CN Color=T Copies=T Duplex=F PaperCustom=T Binary=T Transparent=T TBCP=F'

Не помогло то, что dns-sd ожидал выходить за скобки в зависимости от того, какой механизм выхода из пространства вы использовали; если бы вы печатали \[space] избежать value with spaces он ожидал, что вы тоже избежите скобок. Но цитирование всего этого заставляет dns-sd позаботиться о самих скобках...

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

Другие вопросы по тегам