Basically when I am running this script, after runprog.exe returns (echos in cmd prompt) everytihng in the do ( ) section.
#echo off
set NODES=(server1.com server2.com)
for %%i in %NODES% do (
echo Log stuff... >> logfile.txt
runprog.exe /switch %%i
if %ERRORLEVEL%==0 (echo success) else (echo fail)
sleep 5
)
Edit: #echo off is at the top of the script.
The problem is in this sleep 5 command: it is a custom batch file that you have.
The funny thing is that if I run your batch file on my computer the exact same thing is happening, and I most probably have a different 'sleep' batch file than you. Mine contains the following:
#echo off
ping -n %1 127.0.0.1 > NUL 2>&1
Replacing sleep 5 with call sleep 5 fixes the problem here.
I have no idea why. Ask Microsoft.
As Mike Nakis said, it's the batch file sleep.
It's not important if sleep.bat contains #echo off or not.
The problem is that starting a batch file from another batch file transfers the control to the new batch file but doesn't return to the caller.
But in your case you have a FOR-loop which is completly cached by the cmd.exe.
That's the cause why the first batch doesn't stops immediately.
But when the second loop runs, the cmd.exe has leaved the batch-file-mode and is now in the cmd-line-mode.
You could control this by adding an echo line.
#echo off
set "world=" -- unset the world variable
for /L %%n in (1 1 3) do #(
call echo Hello %%n %%world%%
sleep.bat 1
)
The output will be
1 Hello
2 Hello %world%
3 Hello %world%
That's because the cmd-line-mode doesn't remove percent expansions when the variable is unset.
The CALL sleep.bat solves the problem, as then control simply returns to the caller, as expected.
Related
I have a windows batch script that is executed by a scheduler after every 1 hour.
I want that certain lines in the batch script to only be executed when the scheduler has executed the batch script 10 times.
myscript.bat sample
#echo off
echo hello world
want the below line to print after every 10 times the batch script(myscript.bat) has been executed.
echo This text will appear after repeating "hello world" for 10 times.
Any help will be highly appreciated!!
You would need to create a file, seeing as the script executes and exits all the time, well each hour in fact.
#echo off
echo Hello World
echo Hello World >> lockfile.txt
setlocal EnableDelayedExpansion
set "string=findstr /R /N "^^" lockfile.txt | find /C "Hello""
for /f %%a in ('!string!') do set number=%%a
echo %number%
IF "%number%"=="10" (ECHO Success! && del /Q lockfile.txt)
So to explain...
We echo Hello world, purely for you to see it in the screen.
We echo Hello world to a lockfile each time the script executes.
We do a count of the rows in the file, once we hit 10 rows (in this case 10 executions, then we echo Success and we delete the lockfile. The reason for the lockfile deletion is purely to make sure that we do not exceed a count of 10
So all of the commands you want to run after hello world was echo'd 10 times will for part of your IF statement. Hope that helps.
You can do it by using looping statements
In your batch file
For eg :-if you want to print hello world 10 time
FOR /F %i IN (1,1,10) DO echo hello_world
I'm running a command in a batch file[Just for info: this command runs a python script which generates different outputs]
The code is as follows:
:meshfunc
echo "starting command"
echo "!inst_dir!runME.bat -parameter1 !parameter2! !parameter1v! -script pythonscript.py"
echo start_time=!time!
for /F "delims=" %%i IN ('"!inst_dir!runME.bat -parameter1 !parameter2! !parameter1v! -script pythonscript.py"') DO (
set cmdline=%%i
echo currentENDline=!cmdline!
)
EXIT /B 0
The output of the script is:
PS: I have stripped the output lines for obvious reasons, but they shouldn't matter here
So my questions is :
If i run the same command without a for loop , it will complete in maybe 30 sec without the warning at the end.
However, if I run it inside a for loop, it takes much longer about 3 mins and gives the warning at the end
Why am I'm getting the Warning at the end as shown. Why is this happening?
Because for /F execute the command enclosed in parentheses and store all its output in a temporary disk file until the command ends; after that, it start to repeatedly execute the group of commands. In this way, if the output is very large, the temporary file needs to grow several times and such a process takes some time... It should be faster to redirect the output to a disk file and then process such a file with for /F:
:meshfunc
echo "starting command"
echo "!inst_dir!runME.bat -parameter1 !parameter2! !parameter1v! -script pythonscript.py"
echo start_time=!time!
call "!inst_dir!runME.bat" -parameter1 !parameter2! !parameter1v! -script pythonscript.py > output.txt
for /F "delims=" %%i IN (output.txt) DO (
set cmdline=%%i
echo currentENDline=!cmdline!
)
EXIT /B 0
I'd like to do something like:
start program1 ^>output
start program2 ^>output
and order the output so that the output is ordered. I don't care which output is first (program1's or program2's), but I'd like it to be a complete dump of that program's output.
Ideally, I'd like to run multiple programs in parallel with output all going to the screen, but a file would be fine. I don't need to see it while it is running, just have it intelligible when it's finished.
EDIT:
If I follow the suggestion to output them to a file then merge them when it's done, I have the trouble of waiting 'til all the programs are done -- so, I need a waitUntilAllTheStartsAreFinished command.
start program1 ^>output1
start program2 ^>output2
#... as many as I need
waitUntilAllTheStartsAreFinished
TYPE output1
TYPE output2
delete output1
delete output2
You can use a loop and tasklist:
:wait
rem just wait a second before looking again
ping -n 2 ::1 >nul 2>nul
tasklist 2>&1 | findstr /b "program1.exe program2.exe ..." >nul 2>&1 && goto wait
It will only continue further until all of program1.exe program2.exe ... are terminated.
Joey's suggested method will work, but it can become problematic if your programs can be launched multiple times. It becomes difficult to tell which tasks are the onces you want to monitor.
Each program will have an exclusive lock on the temporary output file until the program finishes. Any attempt by another process to redirect to the same file will fail. This can be used to detect when the program finishes.
I used TIMEOUT to insert a delay in the polling. If you are on a system like XP that does not have TIMEOUT then you can use ping -n 2 ::1 >nul 2>nul instead.
I've included extensive documentation on how this solution works in the code. Edit - I have simplified the code a bit by removing one unneccessary code block level, and I improved the documentation.
#echo off
setlocal
REM Define a base name for the temporary output files. I've incorporated
REM a random number in the file name to generally make it safe to run this
REM master script multiple times simultaneously. It is unlikely a collision
REM will occur, but incorporating a timestamp in the name would make it more
REM reliable.
set "baseName=%temp%\output%random%_"
set /a "progCount=2, completedCount=0"
REM Start each program with both stdout and stderr redirected to a temporary
REM ouptut file. The program will have an exclusive lock on the output file
REM until it finishes executing. I've assumed the program is another batch file
REM and I use the START /B switch so that the programs are run in the same
REM window as this master script. Any console program will work, and the
REM /B switch is optional.
start /b "" ^"cmd /c test.bat ^>"%baseName%1" 2^>^&1^"
start /b "" ^"cmd /c test2.bat ^>"%baseName%2" 2^>^&1^"
REM etc.
REM Clear any existing completed flags, just in case
for /l %%N in (1 1 %progCount%) do set "completed%%N="
:loopUntilDone
REM Introduce a delay so we don't inundate the CPU while we poll
timeout /nobreak 1 >nul
REM Loop through each of the output file numbers.
REM Redirect the stderr for the DO block to nul so that if the inner
REM block redirection fails, the error message will be suppressed.
for /l %%N in (1 1 %progCount%) do (
REM Only test this particular program if the output file has been
REM created (in other words, the program has started) and we haven't
REM already detected that it has finished. Also redirect an unused
REM file handle to the output file in append mode. The redirection will
REM fail if the program has not completed. If the redirection fails then
REM the IF block is not executed.
if not defined completed%%N if exist "%baseName%%%N" (
REM We are within the block, meaning the redirection succeeded and
REM the program must have finished. So print out the results.
echo(
echo Ouput for program%%N
echo ---------------------------------------------
type "%baseName%%%N"
REM Set a flag so we know this program has finished
set completed%%N=1
REM Increment the completed count so we know when we are done
set /a completedCount+=1
) 9>>"%baseName%%%N"
) 2>nul
if %completedCount% neq %progCount% goto :loopUntilDone
del "%baseName%*"
Hello people on Stack Overflow!
I've searched a lot on the internet, but I didn't get anything relevant.
I am writing a script that opens a file directly once placed in directory. So let's say I have the directory:
F:\Files
Now I download a file to that folder. The following will be created:
F:\Files\download.zip REM This is the actual file, but 0 KB
F:\Files\download.part REM This is the content of the *.zip, until it is fully downloaded.
So which script could I use to open download.zip when its size equals larger than 1 byte?
Assuming %1 is the file name passed to the script as an argument, you could do something like this:
IF %~z1 GTR 0 (
commands to process the file
)
%~z1 evaluates to the size of the file specified in %1. GTR means greater than, so the condition checks if the size is greater than 0, and if that is true, the commands to process the file are executed.
This bach file should do what you want (not sure if it will work on all versions of Windows).
It is using Andriy M's script, but adds the functionality you requested.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET dirname=F:\Files
:Begin
CLS
ECHO %TIME%
FOR /R "%dirname%\" %%a IN (*.zip) DO CALL :process1 %%a
ping.exe localhost -n 11 >nul
GOTO Begin
:process1
IF %~z1 GTR 0 "%1"
GOTO :EOF
The ping.exe localhost -n 11 >nul is just a delay, so that you can leave the batch file running and it will loop about every 10 seconds as defined with -n 11 which results in 11 pings of local host in intervals of 1 second with first one successful already after some microseconds.
I've added the command line ECHO %TIME% so that it can be seen it is still working as this time value updates every loop iteration.
There is a drawback to this batch solution. If the ZIP file is still in the directory when the next loop run occurs, it opens the ZIP file once again.
I got a quite long windows batch script. In the middle of it there's a section using appcmd to detect the root path of a site in my IIS. That section runs fine when executed standalone. But when I execute the whole batch, this section could fail to detect the site path once in a while. I am totally confused by this unreliability issue. Have anyone met this before?
Thanks
Solution
It seems that there's some delay between a variable declaration and its coming into effect. I changed the order of some part of the batch file and it runs fine so far. I must say, it's still weird.
As I don't know what type of problem you have in your unknown code, I can only show the known unpredicable or random behaviour in batch-files.
1- multiple tasks echo of line ends
Sometimes but not always the linefeeds and carriage returns are print as the ASCII-Chars 10/13 (a circle and a note) instead of begin a new line.
#echo off
if "%1"=="/second" (
call :task %2
goto :eof
)
(call "%~0" /second 1 >con ) | ( call "%~0" /second 2 )
echo END OF TASKS
goto :eof
:task
for /L %%n IN (1,1,10) DO (
echo This is task%1, output no %%n
ping -n 2 localhost > nul
)
goto :eof
2- Sometimes but not always an expansion of %~^LF crashes, then the command window closes immediatly.
#echo off
set critical_content=hello%%~^
echo No crash
for %%a in (1 ) do (
for %%x in (4) do (
rem #%critical_content%#
)
)