0

我正在尝试使用通过 Plesk 的一个事件触发的批处理文件来自动创建 DNS 区域。

使用 dnscmd 命令,批处理检查区域是否存在。如果该区域不存在,脚本将根据规范添加它。如果它确实存在,并且它是辅助区域,则脚本会根据规范删除并重新创建它。如果它存在,并且它是一个主要区域,则脚本将不理会它。那部分一切正常。

由于我们有一些自定义配置,我还想验证该区域是否是辅助区域,它也使用目标服务器作为主服务器。如果它正在使用不同的主服务器,请不要理会它。虽然我能够检索主服务器列表,但由于输出存在奇怪问题,我无法匹配文本。Windows 使用 0x0d,0x0a 作为行尾标记,批处理环境可以识别这一点。然而,在这个特定的输出行上,行尾包含一个额外的 0x0d;EOL 标记为 0x0d,0x0d,0x0a。

问题部分在 :check3 标签之后。我从 FOR /F 循环中收到了一些奇怪的反馈,并添加了 echo 命令来帮助调试。我最终将 dnscmd 的输出直接加载到十六进制编辑器中进行查看。使用下面脚本中显示的算法,我的测试变量 %%A 和 %%B 保留了额外的 0x0d,从而打乱了我的比较。我从 dnscmd 检查的其他行没有显示此问题 - 它仅与与 MasterServers 信息相关的输出有关。我该如何解决这个问题?

要求:仅批处理功能......我们知道我们可以将其重新编码为 VBScript 并立即解决问题,但这不是我们的目标。该解决方案不得涉及任何其他应用程序来解析来自 dnscmd 的输出。

@echo off
rem 1.2.3.4 = target server holding Plesk domains
rem 5.6.7.8 = our public nameservers

rem *** USER CONFIGURED VARIABLES
set dnsupdlog=test.log
set dnsupdip=1.2.3.4

rem *** other script variables (DO NOT MODIFY)
rem the next line is "set tab=<tab>%"
set tab=        %
set nozone=%1

rem *** make sure a domain was provided
if "%1"=="" set nozone=**NO ZONE PROVIDED**
for /F "delims=" %%A IN ('date /T') DO SET dnsupdtime=%%A
echo --------%dnsupdtime% begin zone %nozone% > %dnsupdlog%
if "%nozone%"=="**NO ZONE PROVIDED**" (
  echo You must provide a domain name, e.g., test.bat mydomain.com >> %dnsupdlog%
  goto :endit
)

rem *** does domain exist yet?  if not, just add the domain
"%plesk_bin%\dnscmd.exe" 5.6.7.8 /zoneinfo %1 | find "query failed" > NUL
if ERRORLEVEL 1 (
  echo Zone exists ... continue checking >> %dnsupdlog%
  goto :check2
)
echo Zone does not exist ... add domains >> %dnsupdlog%
goto :add_domains

:check2
rem *** domain already exists.  Is it primary?  if yes, skip
for /F "tokens=1-2 skip=1 delims=%tab%: " %%A IN ('"%plesk_bin%\dnscmd.exe" 5.6.7.8 /zoneinfo %1 Type') DO (
  if "%%A"=="Dword" (if "%%B"=="1" (
    echo Domain is a primary zone.  No work to be done. >> %dnsupdlog%
    goto :endit
    )
    echo Not a primary zone ... continue checking >> %dnsupdlog%
    goto :check3
  )
)
echo ***ERROR*** Could not determine zone type!! >> %dnsupdlog%
goto :endit

:check3
rem *** secondary domain exists.  Is it using this as master?  if not, skip
set isfound=no
for /F "skip=1 tokens=2-3 delims=%tab%=> " %%A IN ('"%plesk_bin%\dnscmd.exe" 5.6.7.8 /zoneinfo %1 MasterServers') DO (
  echo %%A
  echo %%B
  echo %%A,
  echo %%B,
  if /i "%%A"=="count" (if /i "%%B" NEQ "1" (
    echo Received unexpected master server count %%B!! >> %dnsupdlog%
    goto :endit
    )
  )
  if /i "%%A"=="Addr[0]" (
    if /i "%%B" NEQ "%dnsupdip%" (
      echo Different master server %%B.  No work to be done. >> %dnsupdlog%
      goto :endit
      )
    set isfound=yes
  )
)
if /i "%isfound%" NEQ "yes" (
  echo Did not find expected IP %dnsupdip% as master server.  No work to be done. >> %dnsupdlog%
  goto :endit
)

:del_domains
rem *** delete domains here
echo del >> %dnsupdlog%

:add_domains
rem *** add domains here
echo add >> %dnsupdlog%

:endit
echo --------%dnsupdtime% end zone %nozone% >> %dnsupdlog%
set isfound=
set nozone=
set dnsupdtime=
set dnsupdlog=
set dnsupdip=
4

1 回答 1

0

通过结合使用 FOR "call :subroutine" 和 SET substring 功能,我能够得到一个脚本来忽略额外的 CR (0x0D) 字符。

首先,我在您从 DNSCMD 获得的 CR CR LF 排列中创建了一个在几行上带有额外 CR 的测试文件。我实际上只是想弄清楚 SET 子字符串功能以去除额外的 CR,当我意识到多行 FOR 语句主体中的变量(括号之间的行)都立即展开时,因此 SET 子字符串操作不会不工作。相反,这些命令需要逐行执行,这使我获得了“调用:子程序”功能。

要将行的其余部分传递给“:show”子例程”,我必须将第三个变量放在引号中。这本身似乎去除了具有它的行上的额外 CR,巧妙地避免了进一步的条件逻辑来跳过那些没有额外的 CR。然后我在子例程中使用子字符串操作来删除引号。

@echo off
for /F "tokens=1,2* delims= " %%A in (testfile.txt) do (call :show %%A %%B "%%C")
goto :eof

:show
  echo A=[%1]
  echo B=[%2]
  echo C=[%3]
  set l=%3
  : the param needs to be copied to another var for expansion to work
  set t=%l:~1,-1%
  echo T=[%t%]

  echo ---
  goto :eof

与过去的 DOS 时代相比,批处理编程无疑已经走了很长一段路,但即便如此,它似乎只是一堆变通办法来处理其他变通办法的副作用!

Anyway, you should be able to utilize something like this to get your script to work. In your case, if you just pass your %%A and %%B params to a subroutine you may be all set and not have to worry about adding and removing quotes. I don't know enough about DNSCMD so I can't replicate your output, otherwise I would give a more specific solution.

于 2010-01-07T17:39:39.393 回答