Why doesn't environment variable get updated in script - windows

I am basically a Linux guy forced into a Windows world lately, so I need to write a bat script, but I ran into the following problem.
Here is my .bat script
///////////////////////////
echo.
echo This is testbat script
echo -----------------------------------------------------------
echo.
if "%1"=="" (
echo "You did not enter an argument
) else (
set "myvar="
echo Argument is %1%
set myvar=%1%
if "%myvar%"=="%1%" (
echo myvar is %myvar%
) else (
echo myvar is not set to %1
)
)
////////////////////////////////////////////////////////
It seems that I need to run this script twice to get myvar to change.
For example,
FIRST RUN:
testbat.bat hello
OUTPUT:
This is testbat script
-----------------------
Argument is hello
myvar is not set to hello
SECOND RUN:
testbat.bat hello
OUTPUT:
This is testbat script
-----------------------
Argument is hello
myvar is hello
NOW CHANGE the argument to bye
THIRD RUN:
testbat.bat bye
OUTPUT:
This is testbat script
-----------------------
Argument is bye
myvar is not set to bye (In fact, it is still hello here)
FOURTH RUN (same input as THIRD):
> testbat.bat bye
OUTPUT:
This is testbat script
-----------------------
Argument is bye
myvar is bye (Finally gets updated)
////////////////////////////////////
My question is why the script doesn't update the environment variable the first time?
Why do I need to run the script a second time to get the variable to change to the new value in the script? I used the SET command and discovered that the value is changed in the environment, why does the script output reflect the old value. Of course, the value in the environment might not change until after the script completed, not sure.
I'm running the script and then using the up arrow to edit the command line if that makes any difference, it doesn't seem to though.

You cannot use %1% as an environment variable because %1 is a command line replaceable parameter.
To set/change and display a variable within parentheses or a loop you need
#echo off
setlocal enabledelayedexpansion
and use echo !myvar!

Related

How do I use property defined with Jenkins Pipeline properties step in batch script in the same pipeline?

I have defined the properties using snippet generator and below is the portion from the jenkinsfile.
properties([[$class: 'RebuildSettings', autoRebuild: false, rebuildDisabled: false], parameters([string(defaultValue: 'SNAPSHOT', description: '', name: 'BUILD_TYPE'), string(defaultValue: '5.7.0', description: '', name: 'BRANCH_VERSION')]), pipelineTriggers([])])
When I echo the above defined properties using either "echo param" or "echo env.param" these parameters are correctly resolved.
Below are resolved correctly:
echo BUILD_TYPE
echo BRANCH_VERSION
echo env.BUILD_TYPE
echo env.BRANCH_VERSION
However, I need to use these parameters in batch script which is part of the same jenkinsfile, but these parameters are not resolved there. Below is batch portion from the jenkinsfile
bat '''echo off
echo "flag: env.BUILD_TYPE"
echo "flag: env.BRANCH_VERSION"'''
As the batch script is a Windows CMD Script, it must follow syntax for windows CMD.
ie. This means using correct variable expansion for environmental variables as handled by the CMD Interpreter.
CMD scripts expand the environmental variables by wrapping them in percent signs (or Exclamation Marks ! when you have Enabled Delayed Expansion).
eg: Jenkins sets Environmental Variable BUILD_TYPE CMD Expands this value using %BUILD_TYPE% (or !BUILD_TYPE! if you use delayed expansion in the cmd script)
If it was in a stand-alone CMD file it would look like this:
REM Script: Jenkinsbat.cmd
#(SETLOCAL
ECHO OFF
)
echo "flag: %BUILD_TYPE%"
echo "flag: %BRANCH_VERSION%"
(ENDLOCAL
Exit /b
)
And Jenkins would call it like this by referencing the full path of the script:
bat '''REM Call Script: Jenkinsbat.cmd
ECHO OFF
CALL "\\URL\Share\Path_to_Bat\Jenkinsbat.cmd"'''
Since your batch script is code sitting inside the Jenkins file it should look like this:
bat '''REM Script: Jenkinsbat.cmd
ECHO OFF
echo "flag: %BUILD_TYPE%"
echo "flag: %BRANCH_VERSION%"'''

Passing parameter from window bat to UNIX shell script

i know topic seems very familiar and there are many answers given for same, but my issue is something else.I have a .bat file in which i am passing more then 10 parameters(I know limit is 9 but i need it).It seems to be working fine.Script is below-:
#ECHO OFF
setlocal EnableDelayedExpansion
set n=0
for %%a in (%*) do (
set vector[!n!]=%%a
set /A n+=1
)
SET sadminUser=%vector[0]%
SET sadminPassword=%vector[1]%
SET dsnProvider=%vector[2]%
SET dbUserName=%vector[3]%
SET schemaFilePath=%vector[4]%
SET ddldictschemalogPath=%vector[5]%
SET repositoryName=%vector[6]%
SET ddlimpschemalogPath=%vector[7]%
SET grantUserRole=%vector[8]%
SET userId=anyuser
SET host=myhost
SET password=password
SET datatable=%vector[9]%
SET indexTable=%vector[10]%
SET ddlimpschemalogPath2=%vector[11]%
echo %ddlimpschemalogPath2%
echo y | "C:\Program Files\PuTTY\plink" -ssh %userId%#%host% -pw %password% exit
"C:\Program Files\PuTTY\plink" -ssh %userId%#%host% -pw %password% "PATH=/bin:/usr/bin:/usr/local/bin /opt/siebel/w44gq8sw/DDL_Sync.sh %sadminUser% %sadminPassword% %dsnProvider% %dbUserName% %schemaFilePath% %ddldictschemalogPath% %repositoryName% %ddlimpschemalogPath% %grantUserRole% %datatable% %indexTable% %ddlimpschemalogPath2%" > ddlSuccess.txt 2>&1
Now as you see i am doing echo %ddlimpschemalogPath2% which is last parameter in array,and i can see correct output as well.
Problem is when i try to pass these parameters into UNIX Shell Script.You can see i am doing in bat file using putty command line Plink.I can successfully connect to shell script as well,And i am trying to echo all the passed parameters in shell script.But facing some issue . Script is below-:
#!/bin/bash
sadminUser=$1
sadminPassword=$2
dsnProvider=$3
dbUserName=$4
schemaFilePath=$5
ddldictschemalogPath=$6
repositoryName=$7
ddlimpschemalogPath=$8
grantUserRole=$9
datatable=${10}
indexTable=${11}
ddlimpschemalogPath2=${12}
echo "$sadmimUser"
echo "$sadminPassword"
echo "$ddlimpschemalogPath2"
echo password | sudo -S -l
sudo host << EOF
// Do something else
EOF
I Found one issue. In .bat i have parameter called -: repositoryName . When i do echo %repositoryName% it gives "Siebel Repository" correct output. Now when this spaced value is passed as parameter to shell script it breaks into 2 different values so:
These two parameter in script take 2 different values-:
repositoryName=$7
ddlimpschemalogPath=$8
Output-:
Siebel
repository
And it should be one value for parameter repositoryName=$7 . Giving value Siebel Repository. Why is this happening? Can this me issue why value are up and down?
As you can see in .bat i am making call to shell script, and passing parameters taken from .bat file as below-:
DDL_Sync.sh %sadminUser% %sadminPassword% %dsnProvider% %dbUserName% %schemaFilePath% %ddldictschemalogPath% %repositoryName% %ddlimpschemalogPath% %grantUserRole% %datatable% %indexTable% %ddlimpschemalogPath2%" > ddlSuccess.txt 2>&1
You can see complete line above in .bat.
Invoking .bat file -:
dlSync.bat "SAD" "glob81" "gepf_DSN" "SIEBEL" "/global/u70/globepfdev/siebel/schema.ddl" "/global/u70/globepfdev/siebel/siebsrvr/log/dev2prod/output/expschem.log" "Siebel Repository" "/global/u70/globepfdev/siebel/siebsrvr/log/dev2prod/output/ddlsync1.log" "SSE_ROLE" "GLOB_DATA_SMALL" "GLOB_INDEX_SMALL" "/global/u70/globepfdev/siebel/siebsrvr/log/dev2prod/output/ddlsync2.log"
Same parameter are passing out to shell script . where "Siebel Repository" breaks into 2. Thanks

Error codes seemingly ignored by '&&' on Windows command prompt

I have some Batch scripts I use for automating application build processes, most of which involve chaining commands together using the && operator. Admittedly, I'm more experienced with Linux, but based on that experience some_command && other_command should result in other_command being run iff some_command returns an exit code of 0. This answer and this answer seem to agree with that. However this appears not to be the case on Windows cmd.exe, all of the scripts run regardless of the error code of the previous.
I decided to make a simple test for this to convince myself I wasn't going insane. Consider this test.bat, which returns an exit code of 1:
#echo off
EXIT /B 1
Running test.bat && echo This shouldn't print prints 'This shouldn't print'. But since the exit code is clearly 1, echo should not be called. I've tested that the error code was actually 1 using the %errorlevel% variable, they're coming out as expected (0 before I run the script, 1 after).
On Linux I tried the same thing. Here's test.sh:
#!/bin/bash
exit 1
Running ./test.sh && echo "This shouldn't print" gives no output, exactly what I expected.
What's going on here?
(Note: OS is Windows 7 Enterprise)
You need to use call to run the batch script, like this:
call test.bat && echo This shouldn't print
Without call, the && operator does not receive the ErrorLevel returned by the batch script.
When you run a batch file from within another one, you need to use call in order to return to the calling batch file; without call, execution terminates as soon as the called batch file has finished...:
call test.bat
echo This is going to be displayed.
...but:
test.bat
echo You will never see this!
When running test.bat is involved in a command line where multiple commands are combined (using the concatenation operator &, the conditional ones && and ||, or even a block of code within parentheses ()), all the commands following test.bat are ecexuted even if call was not used. This is because the entire command line/block has already been parsed by the command interpreter.
However, when call is used, the ErrorLevel value returned by the batch file is received (which is 1 in our situation) and the following commands behave accordingly:
call test.bat & echo This is always printed.
echo And this is also always printed.
call test.bat && echo This is not printed.
call test.bat || echo But this is printed.
(
call test.bat
echo This is printed too.
echo And again this also.
)
call test.bat & if ErrorLevel 1 echo This is printed.
But without call you will get this...:
test.bat & echo This is printed.
echo But this is not!
...and...:
test.bat && echo Even this is printed!
echo Neither is this!
...and...:
test.bat || echo But this is not printed!
echo And this is not either!
...and:
(
call test.bat
echo This is printed.
echo And this as well.
)
It seems that the && and || operators receive an ErrorLevel of 0 -- even in case ErrorLevel has already been set before test.bat is executed, strangely. Also when if ErrorLevel is used, the behaviour is similar:
test.bat & if ErrorLevel 1 echo This is not printed!
...and...:
set = & rem This constitutes a syntax error.
test.bat & if ErrorLevel 1 echo This is still not printed!
Note that the commands behind test.bat execute after the batch script, even without call.

How to pass a variable into %0 part of batch file with ftp?

I have a batch file I want to be able to call from the command line like:
myBatch.bat testParam
That batch file is the following:
set sid=%1
C:\Windows\System32\ftp.exe -s:%0
goto done
open servername
username
password
get 'FilePath%sid%restoffilepath' targetPath\%sid%MyName.txt
bye
:done
However, I cannot seem to get the FilePath%sid%restoffilepath part to work right - I believe it is because the %0 is treating the input as literal, but I'm not 100% sure. The %sid% variable is not expanded.
I basically want to have FilePath%sid%restoffilepath be FilePathtestParamrestoffilepath in this case.
Think carefully about what you are doing here--the ftp.exe is reading the file. Your batch script, which knows what %1 is, is not feeding the data to ftp.exe.
What you need to do is to shoot the script out to a file, and then run the ftp command:
set sid=%1
echo open servername >> myftp.txt
echo username >> myftp.txt
echo password >> myftp.txt
echo get 'FilePath%sid%restoffilepath' targetPath\%sid%MyName.txt >> myftp.txt
echo bye >> myftp.txt
C:\Windows\System32\ftp.exe -s:myftp.txt

Python Muti-line cmd entries in one environment

I am trying to make a real .bat to .exe converter. I'm currently attempting to create a script witch injects cmd-commands into one cmd-process/environment. Here is what I have so fare:
#!/usr/bin/python3
from os import system as cmd
def ce(*a):
a = list(a)
for b in range(0, len(a)):
cmd(a[b])
# I need each entry of cmd(a[b]) to run in the same cmd environment and therefore
# do what a normal .bat/.cmd program would.
return a
cd1 = ['#echo off', 'set hw=Hi', 'echo %hw%', 'set hw', 'pause']
if ce(*cd1) != cd1:
print('Error')
cmd('pause')
quit()
All it does is iterate through those commands in 'cd1' and executes them one-by-one. As soon as I establish 'hw' as 'Hi', the variable is gone. Not only that but instead of saying "ECHO is off' it displays "%hw%". IF anyone can help me, please do so.
The problem is that you execute each line in a new cmd environment instead of executing line by line in one cmd. To get it workig you have to concatenate all lines with && and then run the whole string as one command line.
But there's still a problem. Concider this line:
#echo off && set x=123 && echo %x% && pause
This will not return the output 123 because the commands are executed at once so echo %x% won't know that %x% is set to 123. To get this working you have to add the command SETLOCAL EnableDelayedExpansion and adress the value of x by !x! instead of %x%.
So the line
#SETLOCAL EnableDelayedExpansion && #echo off && set x=123 && echo !x! && pause
will give you the desired output.
You should decide how you want your script to work. If you use a && b b will only be executed if a was successful. If you user a & b instead b will be executed even if there was an error in a.

Resources