windows - Batch kører korrekt på tredje forsøg, men ikke i task manager overhovedet

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har læst forskellige svar her og prøvet et par stykker, men uden held.


Mit problem er med af scriptet 'log\_copy\_script.cmd', jeg har et par subrutiner indenfor det, men man virker meget mærkeligt. Skriften er beregnet til at få dagens dato, trække 1 år og derefter starte en sletning af en mappe dateret for et år siden. Det virker undertiden. Faktisk hvis jeg kører det via kommandolinjen, vil det først forsøge at slette en mappe med navnet '', så det vil prøve bare måneden og dagen 'MMDD', så en tredje gang det vil gøre det korrekt 'ÅÅÅÅMMDD'. Eventuelle yderligere efterfølgende tider vil lykkes, som om noget er cachelagret.


Også når jeg kører dette via Windows Task Scheduler, kører det og logger til min logfil, men hver gang vil det forsøge at slette blankt.


Er der nogen der ved hvad der foregår her? Tak. : -/


REM Get IP and Vol Name from file, define variables
for /f "delims=" \%\%x in (C:/SystemHealthScripts/ip\_address.txt) do set IP\_ADDRESS=\%\%x
for /f "delims=" \%\%x in (C:/SystemHealthScripts/vol\_name.txt) do set VOL\_NAME=\%\%x
set MAINDIR="\\%IP\_ADDRESS\%\%VOL\_NAME\%"
set SUBDIR="\\%IP\_ADDRESS\%\%VOL\_NAME\%\%LOG\_DATE\%"
set LOGFILE="\\%IP\_ADDRESS\%\%VOL\_NAME\%log.txt"

if [\%1]==[delete\_oldest] (

  REM Format date
  for /f "tokens=1,2,3,4 delims=/ " \%\%a in ("\%date\%") do set month=\%\%b&set year=\%\%c&set day=\%\%a
  set LOG\_DATE=\%year\%\%month\%\%day\%

  set /A "DEL\_YEAR=year-1"
  set DEL\_DATE=\%DEL\_YEAR\%\%month\%\%day\%

  REM Basic validation (Greater than or equal to 20160101 then valid date)
  if [\%DEL\_DATE\%] GEQ [20160101] (
    call echo "\%LOG\_DATE\% \%LOG\_TIME\%: Deleting date '\%DEL\_DATE\%' started" >> \%LOGFILE\%
    call rmdir /s /q \%MAINDIR\%\%DEL\_DATE\%
    call echo "\%LOG\_DATE\% \%LOG\_TIME\%: Deleting date '\%DEL\_DATE\%' finished" >> \%LOGFILE\%

  ) else (
    call echo "\%LOG\_DATE\% \%LOG\_TIME\%: ERROR in deleting date '\%DEL\_DATE\%', validation not met!" >> \%LOGFILE\%
  )
)

Bedste reference


Da du ikke tildeler tegn, der har betydning for cmd til dine variabler, bør du være sikker på at indsætte en linje setlocal enabledelayedexpansion øverst på din scipt (første linje).


Med en hvilken som helst kodeblok (parenteseret kode) analyseres blokken først - og en del af parsningsproceduren er at erstatte ALLE \%var\% variabel med dens daværende værdi. Da du tildeler f.eks. month inden for en kodeblok, er dens værdi på første gang intet - med setlocal fraværende, værdien af ​​month på første runde vil blive brugt som sin indledende værdi på den anden og så videre.


setlocal enabledelayedexpansion gør to ting. Først når batchen slutter, genoprettes miljøet til dets oprindelige indstilling. Alle ændringerne er sikkerhedskopieret, så alle værdier, der er tildelt eller ændret i en kørsel, er 'reset'.


Den anden ting er at lade syntaksen !var! få adgang til værdien af ​​variablen som den ændrer sig inden for blokken (normalt som følge af en for loop, men også som følge af if/else operationer).


Så - tilføj setlocal enabledelayedexpansion og erstat enhver variabel, hvis værdi ændres inden for en blok fra \%var\% til !var!


Dette er kendt som 'forsinket ekspansion' - der er hundredvis af emner på SO om emnet. Brug search til mange mange mange eksempler.

Andre referencer 1


En alternativ tilgang, der tager ud ved at bruge enhver forsinket ekspansion.


@echo off
REM Get IP and Vol Name from file, define variables
for /f "usebackq delims=" \%\%x in ("C:SystemHealthScriptsip\_address.txt") do set "IP\_ADDRESS=\%\%x"
for /f "usebackq delims=" \%\%x in ("C:SystemHealthScriptsvol\_name.txt") do set "VOL\_NAME=\%\%x"
set "MAINDIR=\\%IP\_ADDRESS\%\%VOL\_NAME\%"
set "SUBDIR=\\%IP\_ADDRESS\%\%VOL\_NAME\%\%LOG\_DATE\%"
set "LOGFILE=\\%IP\_ADDRESS\%\%VOL\_NAME\%log.txt"

if "\%1"=="delete\_oldest" CALL :delete\_oldest

GOTO :EOF

:delete\_oldest
REM Format date
for /f "tokens=1,2,3,4 delims=/ " \%\%a in ("\%date\%") do (
    set "month=\%\%b"
    set "year=\%\%c"
    set "day=\%\%a"
)
set "LOG\_DATE=\%year\%\%month\%\%day\%"

set /A "DEL\_YEAR=year-1"
set "DEL\_DATE=\%DEL\_YEAR\%\%month\%\%day\%"

REM Basic validation (Greater than or equal to 20160101 then valid date)
if \%DEL\_DATE\% GEQ 20160101 (
    echo "\%LOG\_DATE\% \%LOG\_TIME\%: Deleting date '\%DEL\_DATE\%' started" >> "\%LOGFILE\%"
    rmdir /s /q "\%MAINDIR\%\%DEL\_DATE\%"
    echo "\%LOG\_DATE\% \%LOG\_TIME\%: Deleting date '\%DEL\_DATE\%' finished" >> "\%LOGFILE\%"

) else (
    echo "\%LOG\_DATE\% \%LOG\_TIME\%: ERROR in deleting date '\%DEL\_DATE\%', validation not met!" >> "\%LOGFILE\%"
)