我正在尝试使用通过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=
答案 0 :(得分:0)
我能够通过结合使用FOR“call:subroutine”和SET子串功能来获取一个脚本来忽略额外的CR(0x0D)字符。
首先,我在几行中创建了一个带有额外CR的测试文件,这是你从DNSCMD获得的CR CR LF安排。我实际上只是试图弄清楚SET子串能力去除额外的CR,当我意识到多线FOR语句的主体中的变量(括号之间的行)都被立即扩展,所以SET子串操作不会'工作。相反,这些命令需要逐行执行,这使我得到了“call:subroutine”功能。
为了将该行的其余部分传递给“: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时代走了很长一段路,但即便如此,它似乎只是一堆处理其他解决方案的副作用的解决方法!
无论如何,你应该能够利用这样的东西让你的脚本工作。在您的情况下,如果您只是将%% A和%% B参数传递给子程序,您可以全部设置,而不必担心添加和删除引号。我对DNSCMD知之甚少,所以我无法复制你的输出,否则我会提供更具体的解决方案。