I am trying to automate DNS zone creation by using a batch file fired through one of Plesk's events.
我试图通过使用通过Plesk事件之一触发的批处理文件来自动创建DNS区域。
Using the dnscmd command, the batch checks to see if the zone exists. If the zone does not exist, the script adds it according to specs. If it does exist, and it is a secondary zone, the script deletes and recreates it according to specs. If it exists, and it is a primary zone, the script leaves it alone. That part is all working.
使用dnscmd命令,批处理检查区域是否存在。如果该区域不存在,则脚本会根据规范添加该区域。如果它确实存在,并且它是辅助区域,则脚本将根据规范删除并重新创建它。如果它存在,并且它是主要区域,则脚本不管它。这一部分全部有效。
Since we have some custom configurations, I also wanted to verify that if the zone is a secondary zone, it was also using the target server as the master. If it is using a different master, leave it alone. While I was able to retrieve the list of master servers, I was unable to match the text because of an odd problem with the output. Windows uses 0x0d,0x0a as the end-of-line marker, and the batch environment recognizes this. On this particular line of output, however, the end-of-line includes an additional 0x0d; the EOL is marked as 0x0d,0x0d,0x0a.
由于我们有一些自定义配置,我还想验证如果区域是辅助区域,它还使用目标服务器作为主服务器。如果它使用不同的主人,请不要管它。虽然我能够检索主服务器列表,但由于输出的奇怪问题,我无法匹配文本。 Windows使用0x0d,0x0a作为行尾标记,批处理环境识别出这一点。但是,在这个特定的输出行上,行尾包括一个额外的0x0d; EOL标记为0x0d,0x0d,0x0a。
The problem section is after the :check3 label. I was receiving some weird feedback from the FOR /F loop, and added the echo commands to help debug. I eventually loaded the output of dnscmd directly into a hex editor to have a look. Using the algorithm shown in the script below, my test variables %%A and %%B retain the additional 0x0d, thus messing up my comparisons. The other lines I check from dnscmd do not show this issue - it is only with the output related to the MasterServers information. How can I resolve this?
问题部分位于:check3标签之后。我收到了来自FOR / F循环的一些奇怪的反馈,并添加了echo命令来帮助调试。我最终将dnscmd的输出直接加载到十六进制编辑器中以查看。使用下面脚本中显示的算法,我的测试变量%% A和%% B保留了额外的0x0d,从而弄乱了我的比较。我从dnscmd检查的其他行没有显示此问题 - 它只与输出相关的MasterServers信息。我该如何解决这个问题?
The requirements: batch functionality only...we know we can recode this as VBScript and instantly resolve the issue, but that is not our goal here. The solution must not involve any other applications to parse the output from dnscmd.
要求:仅批量功能...我们知道我们可以将其重新编码为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=
1 个解决方案
#1
0
I was able to get a script to ignore extra CR (0x0D) characters by using a combination of the FOR "call :subroutine" and SET substring capabilities.
通过使用FOR“call:subroutine”和SET子串功能的组合,我能够得到一个脚本来忽略额外的CR(0x0D)字符。
First I created a test file with extra CRs on a few lines, in the CR CR LF arrangement that you were getting from DNSCMD. I was actually just trying to figure out the SET substring capability to strip off the extra CR, when I realized that the variables in the body of a multiline FOR statement (lines between parentheses) all get expanded at once, so SET substring manipulation doesn't work. Instead these commands needed to be executed line by line, which led me to the "call :subroutine" capability.
首先,我在几行中创建了一个带有额外CR的测试文件,这是你从DNSCMD获得的CR CR LF安排。我实际上只是试图弄清楚SET子串能力去除额外的CR,当我意识到多线FOR语句的主体中的变量(括号之间的行)都被立刻扩展,所以SET子串操作不会工作。相反,这些命令需要逐行执行,这使我得到了“call:subroutine”功能。
To get the remainder of the line passed to the ":show" subroutine", I had to put the third variable in quotes. This itself seems to strip the extra CR on lines that have it, neatly avoiding further conditional logic to skip lines that don't have an extra CR. Then I used substring manipulation in the subroutine to remove the quotes.
为了将行的其余部分传递给“: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
Batch programming has certainly come a long way from the old DOS days, but even so it just seems to be a pile of work-arounds to deal with the side effects of other work-arounds!
从旧的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.
无论如何,你应该能够利用这样的东西让你的脚本工作。在您的情况下,如果您只是将%% A和%% B参数传递给子程序,您可以全部设置,而不必担心添加和删除引号。我对DNSCMD知之甚少,所以我无法复制你的输出,否则我会提供更具体的解决方案。
#1
0
I was able to get a script to ignore extra CR (0x0D) characters by using a combination of the FOR "call :subroutine" and SET substring capabilities.
通过使用FOR“call:subroutine”和SET子串功能的组合,我能够得到一个脚本来忽略额外的CR(0x0D)字符。
First I created a test file with extra CRs on a few lines, in the CR CR LF arrangement that you were getting from DNSCMD. I was actually just trying to figure out the SET substring capability to strip off the extra CR, when I realized that the variables in the body of a multiline FOR statement (lines between parentheses) all get expanded at once, so SET substring manipulation doesn't work. Instead these commands needed to be executed line by line, which led me to the "call :subroutine" capability.
首先,我在几行中创建了一个带有额外CR的测试文件,这是你从DNSCMD获得的CR CR LF安排。我实际上只是试图弄清楚SET子串能力去除额外的CR,当我意识到多线FOR语句的主体中的变量(括号之间的行)都被立刻扩展,所以SET子串操作不会工作。相反,这些命令需要逐行执行,这使我得到了“call:subroutine”功能。
To get the remainder of the line passed to the ":show" subroutine", I had to put the third variable in quotes. This itself seems to strip the extra CR on lines that have it, neatly avoiding further conditional logic to skip lines that don't have an extra CR. Then I used substring manipulation in the subroutine to remove the quotes.
为了将行的其余部分传递给“: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
Batch programming has certainly come a long way from the old DOS days, but even so it just seems to be a pile of work-arounds to deal with the side effects of other work-arounds!
从旧的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.
无论如何,你应该能够利用这样的东西让你的脚本工作。在您的情况下,如果您只是将%% A和%% B参数传递给子程序,您可以全部设置,而不必担心添加和删除引号。我对DNSCMD知之甚少,所以我无法复制你的输出,否则我会提供更具体的解决方案。