Запуск программы изнутри 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 позаботиться о самих скобках...
Таким образом, сообщение, которое я заберу от этого, - это создание временной переменной, показывающей расширение переменной, повторяющей ее, чтобы направлять поиск кавычек, прежде чем оценивать его.