Is it possible to run two batch files from Jenkins? - batch-file

I have the following case. In jenkins I have one build which is running on different envoironments. That's why I have build with parameters with two options PROD/TEST. The build is invoking shell script with parameter PROD or TEST.
Here is example of the script A which jenkins is invoking:
if %1%==TEST(
start F:\test.bat
)
The script A itself is invoking another script - B.
Here is example of script B:
copy test.xt copyFolder\
The problem is that Jenkins only invoking the first script - A - and the second script B doesn't run.
Why does this happen?

You will need to call the batch file, not start it because it creates a new cmd.exe instance, so it can run a called batch file asynchronously (as mentioned by jeb here):
if "%~1" == "TEST" (
call F:\test.bat
)
Here, I want to note some things:
%1% will be interpreted as the first argument of the batch file (if any) and an extra percent-sign (%). You probably wanted here the first argument, so I have replaced %1% with %1. If it is not this what you wanted, then replace it with your variable name, but remember that it should not start with a number!
%1 was replaced by %~1 and quoted because:
%~1 means the first argument without any surrounding quotes.
Quoting the values in an if statement is always the best practice, but if there were quotes, the comparison would fail.
Added a space between ==, just to make the code clearer.
For an one-liner, see aschipfl's comment, it is:
if /I "%~1"=="TEST" (call "F:\test.bat")
See call /? and if /? in cmd for more information about how these commands work.

Related

Calling command with variable through batch file

I have a batch file that copies and moves stuff, but I am getting stuck dealing with Certificates. I have to use a command the vendor provides called installrootcacert.cmd, but I also need to pass the file name of the cert which is aptly named rootca.cer. I have to use the script the vendor provides so there is no way around that.
Normally I would run this from the command like like so:
c:\vendor\Software\Conf\Security\installrootcacert.cmd rootca.cer
I have attempted to call the command from my batch file, but with no luck.
I tried to use a variable, but because that command calls several other processes, it is looking for "rootca.cer" after the command. If I place it in a variable, the other processes fail. I cannot modify the other processes.
echo #off
cd E:\vendor\Software\Conf\Security\trustedCA
e:
call "e:\vendor\Software\Conf\Security\installrootcacert.cmd rootCA.cer"
A possible solution, might be:
#echo off
cd /d "E:\vendor\Software\Conf\Security\trustedCA"
call "E:\vendor\Software\Conf\Security\installrootcacert.cmd" rootCA.cer
echo #off replaced with #echo off because echo #off will echo #off in cmd.
It is mentioned by Compo in comments, you are changing drives: use /d option with cd.
Finally, quote only the filename in the call command, else, windows will interpret this as a complete filename (i.e. E:\vendor\Software\Conf\Security\installrootcacert.cmd rootCA.cer, so filename will be installrootcacert.cmd rootCA.cer).
Try the following. You need to adjust the # in your echo statement and your quotations:
#echo off
cd E:\vendor\Software\Conf\Security\trustedCA
e:
call "e:\vendor\Software\Conf\Security\installrootcacert.cmd" rootCA.cer
The reason that this works is because putting the command #echo off in your script stops ALL commands from being output. If you just have echo #off, you're literally going to echo that. (credit to double-beep for initially suggesting that)
As for the quotes, what you are trying to do is pass that as a command, so when you call the rootCA.cer, you need to make sure you are passing it the proper parameters, which is why you place that filepath in quotes. If you place the WHOLE object in quotes, you aren't actually issuing a call to the rootCA.cer command. (credit to LotPings for initially suggesting that).

Escape characters of a file path argument for a batch file

I was making a batch file to take dragged-and-dropped folders for program input. Everything was working fine until I passed a folder, which for the sake of this post, called foo&bar.
Checking what %1 contained inside the batch file looked like C:\path\to\foo or C:\path\to\foo\foo. If the file path were in quotes it would work, so the only working code that slightly takes this into effect is :
set arg1=%1
cd %arg1%*
set arg1="%CD%"
Which changes directory to the passed argument using wildcards. However this only works once for if there is another folder with un-escaped characters inside the parent folder, passing the child folder would result in the parent folders' value.
I tried the answer of this post, which suggests to output the argument using a remark and redirection statement during an #echo on sequence. However no progress occurred in rectifying the problem. Any suggestions?
To recap, I am looking for ways to pass folders with un-escaped characters as arguments to a batch file. The implementation should preferably be in a batch file, but answers using VBScript are welcome. However the starting program must be in batch as this is the only program of the 3 that accepts files as arguments.
To test this, create a batch file with following code:
#echo off
set "arg1=%~1"
echo "the passed path was %arg1%"
pause
Then create folders called foobar and foo&bar. Drag them onto the batch file to see their output. foo&bar will only return C:\path\to\foo.
OK, so the problem is that Explorer is passing this as the command line to cmd.exe:
C:\Windows\system32\cmd.exe /c ""C:\path\test.bat" C:\path\foo&bar"
The outermost quotes get stripped, and the command becomes
"C:\working\so46635563\test.bat" C:\path\foo&bar
which cmd.exe interprets similarly to
("C:\working\so46635563\test.bat" C:\path\foo) & bar
i.e., bar is considered to be a separate command, to be run after the batch file.
The best solution would be to drag-and-drop not directly onto the batch file but onto, say, a vbscript or a Powershell script or a plain old executable. That script could then run the batch file, either quoting the argument appropriately or putting the directory path into an environment variable rather than on the command line.
Alternatively, you can retrieve the original command string from %CMDCMDLINE% like this:
setlocal EnableDelayedExpansion
set "dirname=!CMDCMDLINE!"
set "dirname=%dirname:&=?%"
set "dirname=%dirname:" =*%"
set "dirname=%dirname:"=*%"
set "dirname=%dirname: =/%"
for /F "tokens=3 delims=*" %%i in ("%dirname%") do set dirname=%%i
set "dirname=%dirname:/= %"
set "dirname=%dirname:?=&%"
set dirname
pause
exit
Note the exit at the end; that is necessary so that cmd.exe doesn't try to run bar when it reaches the end of the script. Otherwise, if the part of the directory name after the & happens to be a valid command, it could cause trouble.
NB: I'm not sure how robust this script is.
I've tested it with the most obvious combinations, but YMMV. [It might be more sensible to use delayed expansion exclusively, I'm not sure. It doesn't seem to be necessary except in the first set command. Jeb's answer here might be a better choice if you're going this route.]
For the curious, the script works like this:
Load the original command line into dirname [necessary for the reason pointed out by jeb]
Replace all the & characters with ?
Replace all the quote marks with *
If a quote mark is followed by a space, suppress the space.
NB: it is necessary to suppress the space to deal with both the case where the path contains a space (in which case Explorer adds quote marks around it) and the case where it doesn't.
Replace all remaining spaces with /
NB: ? * and / are illegal in file names, so these replacements are safe.
At this point the string looks like this:
C:\Windows\system32\cmd.exe//c/**C:\path\test.bat**C:\path\foo?bar**
So we just need to pull out the third asterisk-delimited element, turn any forward slashes back into spaces and any question marks back into ampersands, and we're done. Phew!

CMD file will not run my command in the else block

I'm writing a CMD script to execute a Java program. The program requires at least one argument so I created an if else block to check that argument one %1 is not blank. When I run the script without providing argument one I get the expected you must provide an argument to run. But when I do provide the argument the program does not execute. Additionally if I don't have #echo off set, the entire script prints out as text in the window when I do provide the proper argument.
Here's the full script:
set APP_HOME=C:\Temp\Hammer
rem Set APP_HOME to the place where you installed Hammer
if ["%1"] == [""] (
echo you must provide a python script to run
) else (
java -cp %APP_HOME%\lib\jython.jar;%APP_HOME%\lib\hammer.jar;%CLASSPATH% bridenstine.hammer.main.Main %1 %2
)
I think this is a problem with the script and not the program itself because when I run the line that's in the else block by itself without the script,
java -cp C:\Temp\Hammer\lib\jython.jar;C:\Temp\Hammer\lib\hammer.jar;%CLASSPATH% bridenstine.hammer.main.Main argument1
The program executes normally. I've been looking at example scripts and cross referencing this site for CMD files and what I have seems to be valid. Do I have a syntax error?
Update:
I'm running the script like so,
cd C:\Temp\Hammer
bin\ProgramScript.cmd argument1
Update 2:
Someone pointed out that when they run this script they get an error message saying Java is not recognized as an internal or external command (the expected message when Java is not set on their PATH) But they made a good point that this means the script is in fact getting inside the else block. I then pointed out the following,
After I run the script with a valid argument it prints out the entire script as text on the command prompt. I am then able to mark the line from inside the else statement (that was printed), copy it, paste it, and it runs the program fine. So the Java command seems to be valid. But you make a good point that the script is obviously getting inside the else block...something is still going wrong here and it doesn't seem to be the program.
Note:
If relevant I am using Windows 8.1 and I am using the standard command prompt, not one that has administrative privileges (the results remained the same regardless of using a command prompt with administrative privileges).
I suggest to use
set APP_HOME=C:\Temp\Hammer
rem Set APP_HOME to the place where you installed Hammer.
if "%~1"=="" (
echo You must provide a Python script to run.
pause
) else (
java.exe -cp "%APP_HOME%\lib\jython.jar;%APP_HOME%\lib\hammer.jar;%CLASSPATH%" bridenstine.hammer.main.Main %*
)
It is always better to enclose an argument string in double quotes if it contains environment variables like CLASSPATH which might have a string value containing 1 or more spaces.
%* is expanded by all arguments passed to the batch file as argument, i.e. %1 %2 ...
It is best to always specify an application like java with full path and file extension as otherwise Windows has to search for a file with a file extension as defined in environment variable PATHEXT in current working directory and all directories defined in environment variable PATH. At least the file extension should be in the batch file if the program files directory of the application varies.
I can only offer a suggestion; I've not tried this.
I would try escaping each ; with a caret ^ thus:
java -cp %APP_HOME%\lib\jython.jar^;%APP_HOME%\lib\hammer.jar^;%CLASSPATH% bridenstine.hammer.main.Main %1 %2
(But I'll admit it's clutching at straws...)
You are missing you she-bang at the top of the script
#!/bin/bash

Why CALL command cannot execute a command enclosed with brackets?

The behavior is the same both in the command prompt and in a .bat file.
#echo off
:: the echo that will never be
call(echo echo echo)
:: its the same with non-cmd internal commands
call ( notepad.exe )
:: and even with a code that should fail
call(gibberish)
:: moreover the execution is successful
call (gibberish)&&echo %errorlevel%
:: though there's some parsing done
call(this will print call help because contains "/?"-/?)
:: and will detect a wrong syntax of some parsed-before-execution commands
call ( if a==)
:: and this too
call (%~)
:: same with labels
call(:label)
call(:no_label)
:label
According to the microsoft documentation:
Using multiple commands and conditional processing symbols - (command1 & command2) Use to group or nest multiple commands.
Here's the CALL help page. - So nothing that indicates that syntax is illegal as long as redirection symbols are not used.
More bugs in CALL parser - here
Enter in command prompt window cmd.exe /? and view the last paragraph on last displayed page which belongs to file completion:
The special characters that require quotes are:
<space>
&()[]{}^=;!'+,`~
So all strings with one of those special characters must be enclosed in double quotes.
As file completion is done by cmd.exe, it can be expected that parsing of a line is done similar for entire command lines as well as for lines in batch files.
It is possible to use for example
call "( Notepad.exe )"
which of course results in an error message as Windows will not find an executable with name ( Notepad.exe ) to call.
I have learned just an hour ago here from an interesting comment by phd443322 that cmd.exe parses lines different than all other applications.
As this question will be read most likely never by a programmer with access to source code of cmd.exe, we will never get the answer why those example commands are interpreted as we can see on executing them.
I think the only commands that interpret parenthesis as delimiters for an expression are FOR, IF and SET /A
Adding new lines may look promising:
Call (
Echo Hello
)
but if you try running just
Call (
what that is actually doing is attempting to run the command (.cmd
If you try creating a batch file called (.cmd, then you can in fact call it with
Call "("
The quotes are required because ( is a 'special' character.
In PowerShell parenthesis can be used in many more places which can be confusing if you switch between CMD and PowerShell
(2+3)
Will return 5 in PowerShell but just gives an error in CMD.

How to send command line arguments to batch file containing "=" char

I want to invoke a batch file(tomcat's startup.bat) by passing a command line argument something like c:>startup.bat -Dsun.lang.ClassLoader.allowArraySyntax=true
But the "=" symbol is being replaced with a space.
If I put c:>startup.bat -D"sun.lang.ClassLoader.allowArraySyntax=true" the value was not set properly.
I am using Windows 7.
Is there anyway to pass command line arguments containing "="?
Thanks,
Siva
You can't do much about it inside the batch file, except change %1 to %1=%2, which only works if you know exactly how many parameters you're passing in, or you know they will always come in pairs. (I suppose you could loop and put together all of the -Dxxx parameters with the next parameter, and put those without a leading -D, but if you have other =-style parameters it can get really messy.)
But you can do something outside the batch file, by putting your parameter in quotes:
startup "-Dsun.lang.ClassLoader.allowArraySyntax=true"
You can use %* for all parameters.
In your batch
#echo off
javac %*
Or you can enquote your complete parameter
startup.bat "-Dsun.lang.ClassLoader.allowArraySyntax=true"
And startup.bat looks like (the %~1 removes surrounding quotes from %1)
#echo off
javac %~1

Resources