I execute following batch ('Execute Windows batch command') through Jenkins. Although it always (tested more than 50 times) works when I build my project 'manually' (when I click on 'build' button), it sometimes crashes during scheduled builds.
REM
REM get date in following format - day name - day - month name - year
REM
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do (set dt=%%a)
set year=%dt:~0,4%
set month=%dt:~4,2%
set day=%dt:~6,2%
if %month%==01 set month=Jan
if %month%==02 set month=Feb
if %month%==03 set month=Mar
if %month%==04 set month=Apr
if %month%==05 set month=May
if %month%==06 set month=Jun
if %month%==07 set month=Jul
if %month%==08 set month=Aug
if %month%==09 set month=Sep
if %month%==10 set month=Oct
if %month%==11 set month=Nov
if %month%==12 set month=Dec
For /f %%# In ('WMIC Path Win32_LocalTime Get DayOfWeek^|Findstr [1-7]') Do (Set DOW=%%#)
if %dow%==1 set dow=Monday
if %dow%==2 set dow=Tuesday
if %dow%==3 set dow=Wednesday
if %dow%==4 set dow=Thursday
if %dow%==5 set dow=Friday
if %dow%==6 set dow=Saturday
if %dow%==7 set dow=Sunday
set dayinfo=%dow% - %day%-%month%-%year%
The error message is as follows:
For> /F
%# In ('WMIC Path Win32_LocalTime Get DayOfWeek|Findstr [1-7]') Do
(Set DOW=%# ) set was unexpected at this time.
if> ==1
set dow=Monday Build step 'Execute Windows batch command' marked build
as failure
Since I am unable to reproduce it - is it possible to make batch command not mark build as failed?
Is it a bug in Jenkins or within my batch file?
is it possible to make batch command not mark build as failed?
Yes, write echo Done or something as the last line in your Execute Windows Batch Command step (not in the batch itself). Since that line will always succeed, the whole step will be marked as successful always. Obviously, you are foregoing any possibility of the script failing for valid reasons though.
Now, the reason your script is failing is because in some circumstances (undetermined), your value for DOW is not set. So the comparison statement becomes invalid as it has no left side.
To avoid this, you should always quote your variables and strings in comparison.
if "%dow%"=="1" set dow=Monday
if "%dow%"=="2" set dow=Tuesday
This way, at least the script won't fail due to syntax errors, however you will still end up with empty dow (and incomplete dayinfo)
To figure out why exactly your dow ends up being empty sometimes, you need to actually see the result of the command that generates it's value. So do the following:
WMIC Path Win32_LocalTime Get DayOfWeek
For /f %%# In ('WMIC Path Win32_LocalTime Get DayOfWeek^|Findstr [1-7]') Do (Set DOW=%%#)
When it's successful, it will display the full output of the command in console. When it fails, you will see the error of that command, and take it from there.
Related
I am trying to build my software using cx_freeze for which I built a bat file that runs the build command so when the build is completed it generates build directory inside which there is another directory exe.win-amd64-3.6 containing the bundled code. inside which there is lib/scipy/spatial/cKDTree.cp36-win_amd64.pyd now this file has to be renamed as ckdtree.cp36-win_amd64.pyd for the build to run. I am trying to automate this by including rename in batch file but it's giving error.
I am trying to run rename command when build is completed but it's not working i get the error the syntax is incorrect. i tried to remove
%~dp0
even this didn't work
#ECHO OFF
Set "FRAS_Folder=%~dp0build_logs\FRAS"
If Not Exist "%FRAS_Folder%" MD "%FRAS_Folder%"
Call :Gen_Report_Name fras_logname
echo FileName : "%fras_logname%"
echo Absolute PathName : "%FRAS_Folder%\%fras_logname%"
REM Example save the result of this command with a log file into this folder
python setup.py build>"%FRAS_Folder%\%fras_logname%"
#REM rename the scipy.spatial.cKDtree file to scipy.spatial.ckdtree in lib/scipy/spatial
#REM rename the file cKDTree.cp36-win_amd64.pyd to ckdtree.cp36-win_amd64.pyd in lib/scipy/spatial
ren "%~dp0build\exe.win-amd64-3.6\lib\scipy\spatial\cKDTree.cp36-win_amd64.pyd" "%~dp0build\exe.win-amd64-3.6\lib\scipy\spatial\ckdtree.cp36-win_amd64.pyd"
pause & exit /b
:::::::::::::::::: FUNCTION :::::::::::::::::::
:Gen_Report_Name <file_with_date to be set>
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set "dt=%%a"
set datestamp=%dt:~0,8%
set timestamp=%dt:~8,6%
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set "stamp=%YYYY%%MM%%DD%_%HH%%Min%%Sec%"
Set "%1=%stamp%.log"
Exit /b
::------------------------------------------------------------------------------------
Kindly help me figure what's the issue!
You are using the wrong syntax for the ren command. See ren /?
The second filename must be a filename without path.
If you prefer to include the path for the second filename use the move command.
Windows is case insensitive so the files are having the same name. You will need to use an intermediate filename to change the case of the filename.
Try this:
ren "%~dp0build\exe.win-amd64-3.6\lib\scipy\spatial\cKDTree.cp36-win_amd64.pyd" "%~dp0build\exe.win-amd64-3.6\lib\scipy\spatial\ckdtree.cp36-win_amd64.tmp"
ren "%~dp0build\exe.win-amd64-3.6\lib\scipy\spatial\ckdtree.cp36-win_amd64.tmp" "%~dp0build\exe.win-amd64-3.6\lib\scipy\spatial\ckdtree.cp36-win_amd64.pyd"
I have this batch to compare the modified dates of two files that works great on an old version of Windows 10 '10.0.10240' but not at all on a slightly newer version of Windows 10 '10.0.17134.1304', so what am I missing here? Does the slightly newer version of Windows 10 require the installation of any additional software?
The batch file is as follows:
#echo off
Set _File1="D:\Steam\steamapps\common\dota 2 beta\game\dota\bin\win64\client.dll"
Set _File2="D:\Programs\client.dll"
For /F "Delims=" %%I In ('xcopy /DHYL %_File1% %_File2% ^|Findstr /I "File"') Do set /a _Newer=%%I 2>Nul
If %_Newer%==1 (Set _Newer=%_File1%) Else (Set _Newer=%_File2%)
Echo The newest file is %_Newer%
Pause
works perfectly on 'Windows 10.0.10240' but fails to start on 'Windows 10.0.17134.1304' (only opens for a fraction of a second and then immediately closes)
By including the /Q option with XCOPY, there is no need to pipe through to FINDSTR.
You could therefore use this modification of your chosen FOR /F idea:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "_File1=D:\Steam\steamapps\common\dota 2 beta\game\dota\bin\win64\client.dll"
Set "_File2=D:\Programs\client.dll"
For %%G In ("%_File1%" "%_File2%") Do If Not Exist %%G (Echo A file is missing.& GoTo :EndIt)
Set "_Newer="
For /F %%G In ('%SystemRoot%\System32\xcopy.exe "%_File1%" "%_File2%" /DHLQY 2^>NUL') Do If %%G Equ 1 (Set "_Newer=%_File1%") Else Set "_Newer=%_File2% or neither"
If Not Defined _Newer (Echo An error occurred.& GoTo :EndIt)
Echo %_Newer% is the newer file.
:EndIt
Pause
EndLocal
GoTo :EOF
I have added some additional 'debugging' code to help you to determine what happens on each different system version, and to correct your assumption that 0 means that %_File2% is newer, when both may be datestamped the same.
Your problem appears to be that the response from xcopy, as filtered through findstr will either be 1 File(s) or 0 File(s) and this string is applied to newer
Your if statement then is resolved to
if 1 File(s)==1 ....
So you get a syntax error.
To resolve, remove the "delims=" from the for /f which will then use the default delimiters which includes Space and return the default first token, which is 1 or 0.
Only real puzzle is how it ever worked in your earlier Win10.
Obligatory sermon:
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign a terminal \, Space or " - build pathnames from the elements - counterintuitively, it is likely to make the process easier.
When you use the point-click-and-giggle method of executing a batch, the batch window will close if a syntax-error is found or the script runs to completion. You can put a pause after statements and home in on the error, but better to open a 'command prompt' and run your batch from there so that the window remains open and any (error) messages will be displayed.
--- Revision ---
After a little experimentation, I looked a little closer at the code.
The "delims=" delivers the strings I described - BUT - the set /a (rather than what I expected, set) would grab that number, then fail (hence the 2>nul)
So - what I found is that if file2 does not exist, the script stops waiting for a response to xcopy's question "is file2 a file or directory?`
This may be the cause of the failure on clicking the batch.
So - I'd suggest
set "_newer="
if exist %_file1% set "newer=1"&if exist %_file2% for ...
if defined _newer (if _%_newer%==1....) else Echo %_file1% not found
I am trying to run a batch script on my local machine that will take care of some log archiving on some servers. I can access the servers via file explorer "\SERVERNAME\C$\SOME FOLDER." When I attempt to xcopy from the source to the destination locally and append a timestamp its like the TIMESTAMP variable doesn't store my date/time concatenation.
This is for windows 2012r2 servers, I've tried to append just the date\time to the end which works fine, however, its not the desired format I am looking for and it starts nesting the directory with the date but no time and it looks like a mess. :(
I've also tried to use the wmic however this is the first time I am writing a batch file to automate some tasks so all this has been a great learning experience.
I've tried to echo %TIMESTAMP% and nothing returns? I've even tried to add the concatenation (%CUR_YYYY%%CUR_MM%%CUR_DD%-%CUR_HH%%CUR_NN%%CUR_SS%) directly to the file directory and its doesn't work :(
REM Check to see if a service on the machine is stopped (it is always stopped by the time it gets here) before we move the files from the logging directory to a new one.
for /F "tokens=3 delims=: " %%H in ('sc \\REMOTESERVER query "SOME SERVICE NAME" ^| findstr " STATE"') do (
if /I "%%H" == "STOPPED" (
REM substring the date and time and then concat it together at the end to make the desired timestamp variable
set CUR_YYYY = %date:~10,4%
set CUR_MM = %date:~4,2%
set CUR_DD = %date:~7,2%
set CUR_HH = %time:~0,2%
set CUR_NN = %time:~3,2%
set CUR_SS = %time:~6,2%
set CUR_MS = %time:~9,2%
set TIMESTAMP = %CUR_YYYY%%CUR_MM%%CUR_DD%-%CUR_HH%%CUR_NN%%CUR_SS%
REM copy files from the servers source directory and then move the files to a newly created logging folder with a timestamp appened at the end
echo d | xcopy /f /y "\\REMOTE SERVER\src" "\\REMOTE SERVER\dest\Logging_%TIMESTAMP%" /E /I
REM delete the contents of the servers source directory to keep things nice and clean
pushd \\REMOTE SERVER\src && del . /F /Q popd
)
)
The expected result would look like:
SourceFolder on the server will be there but empty
DestinationFolder will have a new Logging folder created Logging_20190325010101 and within the newly created logging folder all the contents from the SourceFolder should be there.
You need to get rid of the whitespace before and after your = in your set commands, also, You need delayedexpansion in the codeblock with changing variables, and there is a better way to get rid of the colons and comma.
#echo off
setlocal enabledelayedexpansion
REM Check to see if a service on the machine is stopped (it is always stopped by the time it gets here) before we move the files from the logging directory to a new one.
for /F "tokens=3 delims=: " %%H in ('sc \\REMOTESERVER query "SOME SERVICE NAME" ^| findstr " STATE"') do (
if /I "%%H" == "STOPPED" (
REM substring the date and time and then concat it together at the end to make the desired timestamp variable
set "CUR_YYYY=%date:~10,4%"
set "CUR_MM=%date:~4,2%"
set "CUR_DD=%date:~7,2%"
set "mytime=!time::=!"
set "mytime=!mytime:,=!"
set "TIMESTAMP=!CUR_YYYY!!CUR_MM!!CUR_DD!-!mytime!"
REM copy files from the servers source directory and then move the files to a newly created logging folder with a timestamp appened at the end
echo d | xcopy /f /y "\\REMOTE SERVER\src" "\\REMOTE SERVER\dest\Logging_!TIMESTAMP!" /E /I
REM delete the contents of the servers source directory to keep things nice and clean
pushd \\REMOTE SERVER\src && del . /F /Q popd
)
)
To explain your issue however, when you set a variable, the whitespace comes as part of the variable.. So:
set variable = value
Will result in a variable with a trailing space %variable % and a value with a leading space <space>value So we always get rid of the whitespace and best to use double quotes to eliminate possible whitespace after the value. for instance:
set "variable=value"
which will create %variable% and value
Within parenthetical code blocks you have to delay expansion when retrieving variable values in the same block in which they were set. For example:
(
set "test=1"
echo [%test%]
)
... would echo "[]" because %test% was retrieved within the same parenthetical code block in which it was set. At the time %test% is evaluated, it has no value. You must delay expansion either by using setlocal enabledelayedexpansion or by using call echo [%%test%%] (or cmd /c or similar). When using setlocal enabledelayedexpansion, you delay expansion by using ! instead of % to denote variables. See setlocal /? and set /? in a cmd console for more information -- particularly the section of set /? that begins "Finally, support for delayed environment variable expansion has been added."
Also, it's much simpler and more locale agnostic to compose your timestamp using wmic os get localdatetime. Example:
for /f "delims=." %%I in ('wmic os get localdatetime /value ^| find "="') do set "%%~I"
echo %localdatetime%
That should result in %localdatetime% containing the current numeric value of YYYYMMDDHHMMSS.
I wrote a batch file 2 years ago that seemed to work great making a backup copy of an excel spreadsheet daily. All of a sudden 1 day it stopped working properly and began assigning the variables literally instead of pulling the actual date so it just began overwriting itself every day.
I went from getting this file name:
Tasty Schedule 2018 - 04-30-2018
To now getting this filename:
Tasty Schedule 2018 - ~4,2-~6,2-~0,4
Looking at the code it seems obvious where the values are coming from but I am not sure why the date is no longer being pulled. Im assuming there had to be some type of system update that changed something to cause this? What is the best way to fix this? Please see my current code below:
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set stamp=%MM%-%DD%-%YYYY%
copy "J:\TROY C\2018 Schedule\Tasty Schedule 2018.xlsx" "J:\Joe's Folder\ChocScheduleBackUps\Tasty Schedule 2018 - %stamp%.xlsx"
Launch the following command in a command prompt:
wmic OS Get localdatetime
This should show the date, you can start from there.
Verify your locale settings: the mentioned WMIC command is locale dependent.
In order to make WMIC work, you need to see the following when you run set PATH in a command prompt:
C:\Program Files\7-Zip>set PATH
Path=...;C:\WINDOWS\System32\Wbem;...
(Do no modify C:\Windows directory, your computer will not work anymore)
I solved my issue by adding 'C:\Windows\System32\wbem\' to PATH so that WMIC worked and also adding 'C:\Windows\System32\' to PATH so FIND would work.
Here's an example using RoboCopy instead:
#Echo Off
Set "dStamp="
For /F "Tokens=1-3 Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null') Do If Not Defined dStamp Set "dStamp=%%B-%%C-%%A"
If Defined dStamp Copy "J:\TROY C\2018 Schedule\Tasty Schedule 2018.xlsx" "J:\Joe's Folder\ChocScheduleBackUps\Tasty Schedule 2018 - %dStamp%.xlsx"
I have a script that performs upgrade to a database.
The script also logs before the upgrade starts, but when this script tries to access the log file it hangs for an indefinte time.
The line that's causing the issue is:
%LOGMESSAGE% Start update %UPDVERSION% .
LOGMESSAGE is a cmd file which is as follow:
SETLOCAL enabledelayedexpansion
SET /A FT=500
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year
/Format:table') DO (
IF NOT !FT!==500 GOTO proceed
SET FD=%%F-%%D-%%A
SET FT=%%B:%%C:%%E
:proceed
SET /A FX="DS"
)
endlocal
The main function of the LOGMESSAGE is to get the current system time.
The log file into which the scripts writes to has no issues and so does the function LOGMESSAGE, as the log file is written many times before the line %LOGMESSAGE% Start update %UPDVERSION% . is called. The script seems to work without any hassle on many other computer, but I am having an issue with one server, the server is running windows server 2003 R2 SP2.
Any idea what the issue might be?
try this:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
SET /A FT=500
FOR /F "tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table^|find "20"') DO (
IF NOT !FT!==500 GOTO proceed
SET FD=%%F-%%D-%%A
SET FT=%%B:%%C:%%E
:proceed
SET /A FX="DS"
)
endlocal
If you just want to get the date and time, you can use
DATE /T
TIME /T
instead of WMI.
Three comments:
.cmd files are rare - normally, .bat files are used. There are minor differences between the two, but I'm not sure whether they would be relevant (I can no longer remember them...)
It's perfectly legitimate to have have a line-break just before the opening single-quote and just after the closing. A break in the middle of the command, I'm not sure about - not saying this IS a problem, but it's so easily eliminated.
I'm no longer sure, since I rarely use XP any more, and never S2003 - but ISTR there were problems with having a label within a block statement. The label seemed to end the block.
So - I'd suggest
running the routine as a .bat instead of a .cmd, using
for...(
'whatever whatever...'
) do (
structure, and implementing whatever tomfoolery is happening about FD, FT and FX within a subroutine.