how to capture error conditions in windows ftp scripts? - batch-file

I am using windows batch scripts to run ftp scripts automatically. Where the set of ftp commands I want run is saved in a file.
example:
#echo off
ftp -n -i -s:c:\temp\myftpscriptfile.ftp
I have used the %ERRORLEVEL% syntax to successfully capture error conditions in the batch commands. My challenge is the ftp script command is always returning an ERRORLEVEL of 0 even when the commands inside the script fail.
I am having difficulty figuring out how to have the ftp script actually return or trap when errors occur inside it. It will simply run through the commands blindly and even though i can see the errors echoed on screen I can't capture them as an ERRORLEVEL..
Sample screen shot of trying script which fails to login and then echoing the ERRORLEVEL which shows a zero..
ftp> open fubar.test.com
Unknown host fubar.test.com
ftp> user test test
Not connected.
ftp> ascii
Not connected.
ftp> cd /home/test/dirname
Not connected.
ftp> mput C:\Test\test*.txt
Not connected.
ftp> close
Not connected.
ftp> quit
.0

Use find:
ftp -n -i -s:c:\temp\myftpscriptfile.ftp 2>&1|find "Unknown host">nul
if %errorlevel%==0 (
echo Error!
)

Parse ftp communication using for /F command. Possible approach in next script. Caveat: there supposedly exist some ftp error message(s) not included in given test sequence. Of course, you can test positive ftp messages rather...
#ECHO OFF >NUL
SETLOCAL enableextensions enabledelayedexpansion
set "errsftp=0"
ftp -n -i -s:c:\temp\myftpscriptfile.ftp >c:\temp\31442020.err 2>&1
for /F "tokens=1*" %%G in (c:\temp\31442020.err) do (
rem echo %%G [%%H]
if "%%G"=="ftp>" (
set "line=%%H"
set "errs=0"
) else (
set "reply=%%G %%H"
Call :testreply Unknown host
Call :testreply Connection timed out
Call :testreply Not connected
rem insert next tests here
if !errs! EQU 0 echo !line! =looks OK= !reply!
)
)
echo(
echo :errors total: %errsftp%
ENDLOCAL
goto :eof
:testreply
set "ylper=!reply:%*=!"
if not "!ylper!"=="!reply!" (
echo !line! =ERROR= !reply!
set /A "errs+=1"
set /A "errsftp+=1"
)
goto :eof

Related

Batch file - Multiple FTP upload with wildcard match

I need to upload via FTP some files (not all) from a folder to a remote server.
I coded the following which performs the wildcard match, but I think I am missing something to FTP the resulting files.
Remark: the problem is not to upload the folder (which is relatively simple), but to exclude some entries from the given folder and upload all other files.
I was successful in excluding those files and keep the rest, but I can't find the way to upload the latter.
In particular, mput cmd seems to not work with the input filename. Why ?
I want to focus on this question: how can I feed the FTP cmds to upload each resulting file from the above filtering ?
echo off
setlocal enabledelayedexpansion
FOR /R localfolder %%F IN (*.*) DO (
set fname=%%~nF
set ext=%%~xF
set filename=!fname!!ext!
set subfname=!fname:~0,4!
IF NOT "!subfname!" == "idat" (
echo ftp
echo open ftp.something.it
echo ftpuser
echo ftppass
echo lcd localfolder
echo cd remotefolder
echo binary
echo mput !filename!
echo disconnect
echo bye
)
)
pause
This is the solution, I was nearly close to it: just fill-in an external batch .bat file with ftp commands and then call this file at the end of each loop. Delete it and start again with the next entry on the list.
p.s.: for any further usage, beware of trimming any blank spaces before >> operator, as shown below.
#echo off
setlocal enabledelayedexpansion
FOR /R localfolder %%F IN (*.*) DO (
set fname=%%~nF
set ext=%%~xF
set filename=!fname!!ext!
set subfname=!fname:~0,4!
IF NOT "!subfname!" == "idat" (
echo open ftp.something.it>> ftp.cmds.bat
echo username>> ftp.cmds.bat
echo password>> ftp.cmds.bat
echo lcd localfolder>> ftp.cmds.bat
echo cd remotefolder>> ftp.cmds.bat
echo binary>> ftp.cmds.bat
echo mput !filename!>> ftp.cmds.bat
echo disconnect>> ftp.cmds.bat
echo bye>> ftp.cmds.bat
ftp -i -s:ftp.cmds.bat
del ftp.cmds.bat
)
)
Next script could help. Read List of FTP commands for the Microsoft command-line FTP client
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "localfolder=D:\test\31441809\root" change
set "lcd-folder=%localfolder%"
set "excludeFile=nico" change to `idat`
set "ftpscript=%temp%\35574454ftp.dat" change
(
echo open ftp.something.it
echo user ftpuser
echo ftppass
echo binary
echo cd remotefolder
echo lcd %lcd-folder%
FOR /R %localfolder% %%F IN (*.*) DO (
set "fname=%%~nF"
set "ext=%%~xF"
set "filename=!fname!!ext!"
set "subfname=!fname:~0,4!"
IF /I NOT "!subfname!"=="%excludeFile%" (
if /I not "!lcd-folder!\"=="%%~dpF" (
rem change local directory only if necessary
set "lcd-folder=%%~dpF"
set "lcd-folder=!lcd-folder:~0,-1!" remove trailing backslash
echo lcd !lcd-folder!
)
echo put !filename!
)
)
echo disconnect
echo bye
)>"%ftpscript%"
type "%ftpscript%"
pause
ftp -i -n -s:"%ftpscript%"
Sample output:
d:\bat> D:\bat\SO\35574454.bat
open ftp.something.it
user ftpuser
ftppass
binary
cd remotefolder
lcd D:\test\31441809\root
put JohnDoe.txt
lcd D:\test\31441809\root\Ian-ionescu
put Ian-ionescuY.txt
lcd D:\test\31441809\root\John-doe
put John-doe.txt
put John-doeA.txt
lcd D:\test\31441809\root\Nicola-sheperd
put SheperdNicola.txt
lcd D:\test\31441809\root\Sara-smith
put Sara-smith.txt
put Sara-smithZ.txt
disconnect
bye
Press any key to continue . . .
ftp> open ftp.something.it
Connected to www.something.it.
220 FTP Server ready.
ftp> user ftpuser
331 Password required for ftpuser.
etc.etc.

Batch : Use the FOR command to check the files in the folder

I have made ​​a batch script to perform the following tasks :
if the file abc.laccdb still in the update folder , show a message : wait a minute.... if abc.laccdb file is not in the 'update' folder , show a message : updating data successfully..
My Batch script is :
#ECHO OFF
start update_data.vbs
:check
FOR %%F IN (update\abc.laccdb) DO (
echo wait a minute...
goto :check
)
echo updating data successfully
pause
with the script above , the message "wait a minute ... " continuously displayed in command prompt window, even though abc.laccdb file has not in the Update folder. properly if the abc.laccdb file is not there in the Update folder, the bacth application run the next line (echo updating data successfully). please correct my script. thank you :)
A for command with a wildcard will enumerate the files matching the wildcard, but without a wildcard, it will not ensure that the file exists, so the code in the do clause will always be executed whether the file exists or not.
Use
#ECHO OFF
start update_data.vbs
:check
ping -n 3 localhost >nul 2>nul
if exist "update\abc.laccdb" (
echo wait a minute...
goto :check
)
echo updating data successfully
pause
It is not always a good idea to have a waiting loop without some kind of wait. The ping has been included to generate a 2 seconds pause between loops to reduce the cpu usage.
Using MC ND's answer:
#ECHO OFF
echo wait a minute...
start update_data.vbs
ping -n 5 localhost >nul 2>nul
:check
if exist "update\abc.laccdb" (
ping -n 3 localhost >nul 2>nul
goto :check
)
echo updating data successfully
pause
Display echo wait a minute... message in advance...

redirecting .exe output within batch script to txt file

i am trying to redirect output from an exe(commanline exe) which is being called in from batch file to log file. In this script IP addresses of hostnames provided in input.txt are being redirected to result.txt. i am trying to run .exe within same batch script to place those IPs in maintenance mode in my monitoring tool. Script runs fine and performs the action as expected but it fails to capture the output from .exe. please help.
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.txt
>nul copy nul %OUTPUT_FILE%
for /f %%i in (input.txt) do (
set SERVER_ADDRESS=ADDRESS N/A
for /f "tokens=1,2,3" %%x in ('ping -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS=%%y
if %%x==Reply set SERVER_ADDRESS=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo !SERVER_ADDRESS::=!>>%OUTPUT_FILE%
)
start c:\MaintenanceMode.exe ON %OUTPUT_FILE% %USERNAME% >> "c:\result2.txt"
Output from .exe if i run it directly from command prompt:
PS C:\> .\MaintenanceMode.exe ON C:\result.txt username
Not an IP!!
Reading IPs from File: C:\result.txt
Valid Arguments
System put into MM Host# 10.*.*.* Status# Success
System put into MM Host# 10.*.*.* Status# Success
You are redirecting the output of the START command, but not the exe.
If you want to use START and redirect the output, then you most execute a new CMD.EXE session and escape the redirection so it occurs within the new session:
start cmd /c c:\MaintenanceMode.exe ON %OUTPUT_FILE% %USERNAME% ^>^> "c:\result2.txt"
But why are you using START? It would be so much simpler if you simply execute your exe directly:
c:\MaintenanceMode.exe ON %OUTPUT_FILE% %USERNAME% >> "c:\result2.txt"

How do I skip a computer in a batch file that is unreachable?

#echo off
:begin
for /f %%a in (computerlist.txt) do (
setlocal
psexec \\%%a -u user -p password -i -d "d:\path\command.exe"
endlocal
)
when the script is running, when it finds a machine to be unreachable I want it to skip it.
How do i write the script to skip an unreachable computer and continue to the next one in the txt file?
How about a simple test to see whether a machine is pingable?
#echo off
setlocal
:begin
for /f %%a in (computerlist.txt) do (
ping -n 1 %%a >NUL 2>NUL
if %errorlevel%==0 (
psexec \\%%a -u user -p password -i -d "d:\path\command.exe"
) else echo Skipping unreachable host %%a
)
endlocal
Actually, windows ping.exe doesn't return meaningful errorlevels, (huh?)
It ALWAYS returns a "0" errorlevel, unless the IP-Protocol stack itself is hosed.
WHAT YOU HAVE TO DO IS: pipe the output of your ping to a txt-file, and "find" for TTL=
ie
ping 10.10.10.10. >pingtest.txt
findstr /C:"TTL=" pingtest.txt >nul
if %ERRORLEVEL% equ 0 (do whatever) else (echo skipping unreachable host "whatever")
Then use Find.exe or Findstr.exe to look for TTL= in your output file
(note find, and findstr both use "0" errorlevel when they "find" what your searched on)
1. Ping can fail for a whole lot of reasons, but "TTL=" is always part of a successful ping
2. I always ping at least -n 3 times, because occasionally the first one or two might have problems, and I want to give it more possible chances to succeed before I skip it.
3. For this to work, you have to use the FOR loop method above, just raw psexec.exe has not current means to test/skip targets called from a text file.
4. If you need to use network resource in your psexec session then you need to run the "-h" option so that you get the elevated token, which allows you to map drives
I HOPE THIS HELPS !

Return Error Message from START /WAIT Command calling DTUTIL

All,
I am using a batch file to automate the deployment of SSIS packages out to MSDB. I am using a START /WAIT command in a FOR loop to iterate through all files in a folder and execute the DTUTIL command.
While I know I can return the %ERRORLEVEL% and use it in the main batch process, what I am losing is the specific error message that DTUTIL outputs.
I want to be able to capture that message output, but I have yet to find a way to. I tried chaining commands by using the &&, || and & concatenation commands. And I also tried to use > and 2> to put the output into a file. Nothing has given me the desires output.
And to be specific, I'm mainly concerned with when DTUTIL ERRORS and the message is more relevant than the error code alone.
Any help or recommendations would be appreciated. Here's the code:
#echo off
SET /P SOURCEFOLDER=Enter the Source Folder where the Packages are located:
SET /P DESTSERVER=Enter the Destination Server:
SET /P DESTLOCATION=Enter Destination Folder (Leave blank for root):
IF NOT EXIST "%SOURCEFOLDER%\*.dtsx" GOTO NOFILES
FOR /F "usebackq delims==" %%i in (`dir /b "%SOURCEFOLDER%\*.dtsx"`) do (
ECHO.
ECHO ^>^>^>^>^>^> Copying %%i to %DESTSERVER%\MSDB\%DESTLOCATION% ^<^<^<^<^<^<^<
ECHO.
START /WAIT dtutil /FILE "%SOURCEFOLDER%\%%i" /DESTSERVER %DESTSERVER% /COPY SQL;"%DESTLOCATION%\%%~ni" /QUIET
ECHO %ERRORLEVEL%
ECHO.
)
GOTO COMPLETE
:NOFILES
ECHO.
ECHO *** No SSIS Packages were found. Please verify the folder location:
ECHO %SOURCEFOLDER%
ECHO.
GOTO END
:COMPLETE
ECHO.
ECHO All Packages have been Processed.
ECHO Please verify that no Error Messages or Warnings were returned.
ECHO.
GOTO END
:END
PAUSE
Simplest would be to drop start and just issue Dtutil (since you wait till it finishes I cannot see a difference). Another two possibilites
start /B dtutil >result.txt
or
start cmd /c dtutil ^>result.txt
(^ is used to escape special chars, here redirection symbol >) (and you already use it...)
Redirect stderr would be 2>result.txt, both stdout and strerr >result.txt 2>&1 (escaped if used with cmd /c: ^>result.txt 2^>^&1)

Resources