0

我的工作批处理文件扫描一长串远程服务器,将那里的任何内容复制到本地服务器,检查日志文件中的关键字,如果找到关键字,则发送电子邮件。我注意到它总是在发送电子邮件,即使是空白日志文件也是如此。

我发现两个FOR循环都使用%1变量作为它们的输出 - 如在ECHO %1被调用的每一行中所见:servermove。由于缺乏更好的解释,它不会%1在循环之间重置为空。

我查看了近十几篇 SO 帖子,并且有点相信使用SETLOCAL ENABLEDELAYEDEXPANSION会解决这个问题。这就是我的理解结束的地方,到目前为止我还没有成功。

以下是相关代码:

SET DATE=%date:~4,2%-%date:~7,2%-%date:~10,4%
SET HH=%time:~0,2%
SET MN=%time:~3,2%
SET TSTAMP=Time Run is %HH%%MN%
SET DATETIME=%DATE% at %HH%%MN%
SET LOGFILE="\\nt980a3\CreditFileImagesTransmission\LogFiles\%DATETIME%-File Move Log.txt"

SET MailDst=
SET MailSrc=
SET MailSrcName=Center to LDSD File Mover
SET OKMailSub=A Branch Has Sent You Some Files

ECHO %DATETIME% > %LOGFILE%
ECHO. >> %LOGFILE%

FOR /F "tokens=1" %%A IN (%~dp0SourceServers.txt) DO CALL :ServerMove %%A

:cleanuplogs
PUSHD "\\nt980a3\CreditFileImagesTransmission\LogFiles" &&(
FORFILES /S /M *.txt /D -45 /C "CMD /C DEL /Q @path"
) & POPD

:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"

:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit

:successmail
IF EXIST %temp%\to.txt DEL %temp%\to.txt
FOR %%a IN (%MailDst%) DO ECHO %%a>>%temp%\to.txt
"%~dp0sendmail.exe" /TO=%temp%\to.txt /FROM=%MailSrcName% ^<%MailSrc%^> /REF=%OKMailSub% /MESSAGE=%LOGFILE% /HOST=

:exit
EXIT

:ServerMove
DIR /S /B \\%1\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%1\CreditFileImagesTransmission\*.*" "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%1\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%1\CreditFileImagesTransmission\*.*"

我尝试更改:mailtest%%B在这两种情况下使用,但这也失败了。将SETLOCAL ENABLEDELAYEDEXPANSION及其对应物ENDLOCAL放在一个或另一个循环之前并将其更改%%A!A!也不起作用。

有人会以我的方式指出错误并提供可以帮助我解决此问题的建议或资源吗?

4

3 回答 3

1
:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"

您在GOTO :EOF这里缺少一个或类似的 goto,因为一旦完成上述操作,它将进入下面的例程。

:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit
于 2014-07-25T13:55:27.730 回答
1

%1是提供给过程的第一个参数 - 来自命令行(在主过程中)或call :procedurename parameter1.

在您的情况下,%1to:servermove是 from 的条目SourceServers.txt%1to:searchlog是 from 的每一行%LOGFILE%

由于您已经审查了您的批次,因此您发布的内容毫无意义。例如,该:searchlogs例程将取第一行 from%LOGFILE%并 go to successmailorcleanlogs取决于第一行是否包含目标 string \\nt。它从那里做什么,我们无法判断。

我们面临一个XY 问题- 试图解决一个解决方案,而不是一个问题。


第一个问题:不要date用作用户变量。这是一个包含日期被特定set语句覆盖的“魔术变量”。

:servermove为 中的每个条目运行后SourceServers.txt,您正在从\CreditFileImagesTransmission\*.*该服务器上累积一个目录列表。- 将这些文件复制到nt980a3带有日期/时间戳但不包括源服务器名称的服务器,因此任何地方的任何重复名称都将覆盖早期版本。我建议您将其包含%1在您的目的地名称中。- 删除子目录 - 删除文件。

我建议您只需删除目录\\%1\CreditFileImagesTransmission\,然后重新创建它。

我还建议您添加额外的一行

goto :eof

行后del /q /s...。这将导致执行转移到文件末尾(:eof需要冒号)并且可能看起来是多余的,但它确保例程具有定义的端点 - 如果您添加进一步的例程,则:servermove例程没有办法将继续进入您的新代码。

处理完每台服务器后,您继续执行:cleanuplogs例程,我认为该例程会删除超过 45 天的日志。

你的下一个陈述是一个真正的问题。它将做的是抓取日志文件的第一行(其中包含"%DATE% at %HH%%MN%"您在开始时设置的解析日期,然后它处理这一行:searchlog;这一行中没有\\nt,所以errorlevel设置为 1,并且批处理继续:EXIT(在我看来不是一个好的标签,因为它是一个关键字);执行一个exit并且应该终止批处理。

这似乎不是它实际在做什么,我不知道为什么。

我建议改变

:mailtest
FOR /F "tokens=*" %%A IN (%LOGFILE%) DO CALL :searchlog "%%A"

:searchlog
ECHO %1 | find "\\nt">NUL
IF NOT ERRORLEVEL 1 GOTO successmail
GOTO exit

:mailtest
find "\\nt" %LOGFILE%>NUL
IF NOT ERRORLEVEL 1 GOTO successmail
:failmail
echo "\\nt" was found in the log
pause
GOTO exit

但我无法测试...

于 2014-07-24T23:58:52.037 回答
0

我觉得您不能将第一个 for 循环的 %1 传递给其他人。尝试将其转移到另一个变量,如下所示。

:ServerMove

set servername=%1

DIR /S /B \\%servername%\CreditFileImagesTransmission\*.* >> %LOGFILE%
XCOPY /E /C /I /Y "\\%servername%\CreditFileImagesTransmission\*.*"     "\\nt980a3\CreditFileImagesTransmission\%DATE%\%HH%%MN%\"
FOR /D %%P IN ("\\%servername%\CreditFileImagesTransmission\*.*") DO RMDIR "%%P" /Q /S
DEL /Q /S "\\%servername%\CreditFileImagesTransmission\*.*"

干杯,G

于 2014-07-24T22:03:36.487 回答