Ant scp todir with space symbol - ant

I've got a task to copy a directory to the remote server. The problem is that destination folder contains 'space' symbol.
<scp todir="${admin_name}:${admin_password}#${admin_hostname}:/home/user/DIR HERE" trust="true">
<fileset dir="${DIR}/">
<include name="server/**"/>
</fileset>
As result I've got:
[printStackTrace] /home/myuser/install/install.xml:39: server indicated an error: scp: ambiguous target
[printStackTrace] at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:482)
[printStackTrace] at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:443)
It works fine when there is no 'space' in the path.
I've tried:
todir="${admin_name}:${admin_password}#${admin_hostname}:/home/user/DIR\ HERE"
todir="'${admin_name}:${admin_password}#${admin_hostname}:/home/user/DIR\ HERE'"
todir="'${admin_name}:${admin_password}#${admin_hostname}:/home/user/DIR HERE'"
todir="${admin_name}:${admin_password}#${admin_hostname}:'/home/user/DIR HERE'"
and many other variants, but it doesn't help...

The scp line gets parsed multiple times. If this was a standalone scp command, I'd recommend double backslashes before all spaces. You might have to triple backslash when part of an Ant recipe, but give both a try.

You must put a backslash \ before each space:
<!-- Escaping the space character with a backslash character -->
<scp todir="${username}:${password}#${hostname}:/home/user/DIR\ HERE">
...
</scp>

Related

passing command line arguments to ant

I am relatively new in ant, at school I have an assignment to do a build file. One of my questions is to copy to "/foldercopy" the file whose name(or path) is taken as argument for ant. I need to do something like:
ant cpfile file.txt
So ant will copy the file.txt to /foldercopy. I searched a lot on google but all I could find was something with "-Darg", but my teacher said that it's not correct. Is there any way to do it?
Plain command line arguments to ant are considered to be target names, so if you want to pass arguments to your target you need to use properties, via -D:
ant -Dfile=file.txt cpfile
and access the value as ${file} inside build.xml
This will help you:
<target name="copytask" >
<copy file="file.txt" todir="path-od-dir" failonerror="false" />
</target>

copy and unzip files to remote machine - ant

I need to copy the zip files from local machine and paste in remote machine and unzip those files in remote machine.
I know the first part can be done using the scp (copy zip files from local and paste in remote machine) but how to do the second part using ant?
Thanks in advance
You could use the sshexec task to call the command line unzip command on the remote machine (assuming the remote machine has unzip installed).
<!-- local directory containing the files to copy -->
<property name="archives" location="C:\path\to\zipfiles" />
<property name="archives.destination" value="/home/testuser/archives" />
<property name="unzip.destination" value="/home/testuser/unpacked" />
<fileset id="zipfiles.to.copy" dir="${archives}" includes="*.zip" />
<!-- copy the archives to the remote server -->
<scp todir="${user}:${password}#host.example.com:${archives.destination}">
<fileset refid="zipfiles.to.copy" />
</scp>
<!-- Build the command line for unzip - the idea here is to turn the local
paths into the corresponding paths on the remote, i.e. to turn
C:\path\to\zipfiles\file1.zip;C:\path\to\zipfiles\file2.zip... into
/home/testuser/archives/file1.zip /home/testuser/archives/file2.zip
For this to work there must be no spaces in any of the zipfile names.
-->
<pathconvert dirsep="/" pathsep=" " property="unzip.files" refid="zipfiles.to.copy">
<map from="${archives}" to="${archives.destination}" />
</pathconvert>
<!-- execute the command. Use the "-d" option to unzip so it will work
whatever the "current" directory on the remote side -->
<sshexec host="host.example.com" username="${user}" password="${password}"
command="/bin/sh -c '
for zipfile in ${unzip.files}; do
/usr/bin/unzip -d ${unzip.destination} $$zipfile ; done '" />
The unzip command can take a number of other options, see its man page for full details. For example the -j option will ignore any directory hierarchy inside the zip files and put all the extracted files directly in the target directory. And -o will force overwrite existing files in the target directory without prompting.

How can I escape double-quotes in ant?

I need to exec the following command from ant, but I can't figure out how to escape the double-quotes:
tasklist /FI "IMAGENAME eq java.exe" /FI "MEMUSAGE gt 50000"
Ant uses XML, so you can use the normal XML entities like ":
tasklist /FI "IMAGENAME eq java.exe" /FI "MEMUSAGE gt 50000"
Ant script is xml. So in xml, here is the rule.
For > use >
For < use <
For “ use "
For & use &
For ‘ use &apos;
Notice! ";"
Reference:
http://www.jguru.com/faq/view.jsp?EID=721755
I don't believe you really do if you use <arg value> and not <arg line>:
tasklist /FI "IMAGENAME eq java.exe" /FI "MEMUSAGE gt 50000"
<exec executable="tasklist">
<arg value="/FI"/>
<arg value="IMAGENAME eq java.exe"/>
<arg value="/FI"/>
<arg value="MEMUSAGE gt 50000"/>
</exec>
Despite the spaces, the <arg value> will send it as a single parameter to the command. Unless the command itself requires quotes, this should work.
But doesn't work if you need to use the find DOS command in a /CMD exec task:
<target name="install" depends="install2">
<exec executable="cmd.exe" outputproperty="result.process">
<arg line='/c tasklist | find "httpd"'/>
</exec>
<echo message="RESULT: ${result.process}" />
</target>
gives,
install:
[exec] Current OS is Windows 7
[exec] Output redirected to property: result.process
[exec] Executing 'cmd.exe' with arguments:
[exec] '/c'
[exec] 'tasklist'
[exec] '|'
[exec] 'find'
[exec] 'httpd'
[exec]
[exec] The ' characters around the executable and arguments are
[exec] not part of the command.
[exec] Result: 2
[echo] RESULT: FIND : format incorrect de paramètre
Its like if ANT deletes the double quotes around the parameter when it is passed to the CMD interpereter. The help for the find DOS function says you need to use double quotes for the text you're looking for.
Here is an example http://ant.apache.org/faq.html#shell-redirect-2. Simply use single quotes as xml parameter separator. This way you could freely use double quotes inside the arguments.

EXEC args (value) with quotes on linux from Ant script

bash shell:
./mimic_cmd "startDaemon()"
Corresponding Ant code:
<exec failonerror="true" executable="/bin/mimic_cmd">
<arg value='"startDaemon()"' />
</exec>
Does the Ant code exactly represent the above command at the bash shell? Based on the debug info, it looks like it:
[exec] Executing '/bin/mimic_cmd' with arguments:
[exec] '"startDaemon()"'
[exec]
[exec] The ' characters around the executable and arguments are
[exec] not part of the command.
Execute:Java13CommandLauncher: Executing '/bin/mimic_cmd' with arguments:
'"startDaemon()"'
The ' characters around the executable and arguments are not part of the command.
However, the Ant code returns and exit code of 1 while the Bash shell command returns 0.
Toggling vmlauncher doesn't help, and paths are all correct.
The same Ant code works on windows with the resulting debug output:
[exec] Executing 'C:\bin\mimic_cmd' with arguments:
[exec] '"startDaemon()"'
[exec]
[exec] The ' characters around the executable and arguments are
[exec] not part of the command.
Execute:Java13CommandLauncher: Executing 'C:\bin\mimic_cmd' with arguments:
'"startDaemon()"'
The ' characters around the executable and arguments are not part of the command.
Can you tell us what mimic_cmd is? (Is it an ELF executable, is it a script -- and if so, what is its contents?)
You don't need nor want the double-quotes inside your ANT XML attributes (incidentally, for it to be well-formed XML you should have written them as " not ", but that changes nothing with respect to this discussion) unless your executable expects them. The corresponding ANT code for either of the following (100% equivalent) shell command lines:
./mimic_cmd "startDaemon()"
./mimic_cmd 'startDaemon()'
./mimic_cmd startDaemon\(\)
./mimic_cmd startDaemon"()"
./mimic_cmd startDaemon'()'
...actually is:
<exec failonerror="true" executable="/bin/mimic_cmd">
<arg value="startDaemon()" />
</exec>
...or, for illustrative purposes:
<!-- spawn a shell with your original command line -->
<exec failonerror="true" executable="/bin/sh">
<arg value="-c" />
<arg value="/bin/mimic_cmd "startDaemon()"" />
</exec>
Why that is so is longwinded to explain; suffices to say that, in your specific case, the only time when you'd have to use double quotes would be when ultimately issuing the command via a *nix shell (either interactively or as part of another script or programatically via the execing of sh -c), and only in order for that shell not to think that the round parens () have special meaning. By the time the shell would in turn spawn mimic_cmd it would have already stripped the double quotes (and substituted backslash-escaped sequences etc. -- see how a *nix shell parses its command line) ANT does not run your command via the shell but rather executes it directly, so in this case mimic_cmd finds itself with a bunch of double quotes on its hand which it apparently doesn't know how to handle.
You essentially have to think of it as replacing all forms of shell quoting and escaping with XML escaping and breaing down into <arg/> tags.
Windows' CMD.EXE is special in the sense that, unline *nix shells, it does minimal parsing (and generally does not care about double quotes in program arguments), leaving it up to the program to figure out what you meant by quoting. (This is actually a hard limitation of Windows' CreateProcess which does not have the notion of argv[], leaving it up to each program to intepret lpCommandLine in whichever way it sees fit; some will get rid of the quotes for you, but that behaviour is extremely inconsistent, e.g. issue echo "bla" on the CMD.EXE prompt to see what CMD.EXE's builtins think about quoting.) Again, in your case the round parens () have no meaning for CMD.EXE so you don't need them even when typing the command at a command prompt. As for ANT, on Windows as on *nix platforms, it spwans mimic_cmd via CreateProcess not CMD.EXE so you don't really want to quote anything.

How can I ensure all output from Ant's exec task goes to stdout?

The Ant exec task has an output property which can be used to tell Ant where the output goes. I've used it to redirect the output to a file. The thing is, if I don't do something with the output, the stuff that Ant prints isn't that much of a help - it's not complete.
Is there someway of setting the output property to System.out?
When executing a batch file with ant's apply or exec tasks on Windows, I found there are special cases where some of the stdout and stderr is not captured by ant. (For example: if you call a batch file that in turn calls other commands (like node.exe), then the stdout and stderror from the child node.exe process is lost.)
I spent a long time trying to debug this! It seems that the batch file's stdout and stderr is captured, however commands called by the batch file are somehow not seen by ant. (perhaps because they are separate child processes). Using the output and error attributes as suggested above doesn't help because only some of the stdout and/or stderr is captured.
The solution I came up with (a hack) is to add these arguments at the end of the command:
<!--Next arg: forces node's stderror and stdout to a temporary file-->
<arg line=" > _tempfile.out 2<&1"/>
<!--Next arg: If command exits with an error, then output the temporary file to stdout, -->
<!--delete the temporary file and finally exit with error level 1 so that -->
<!--the apply task can catch the error if #failonerror="true" -->
<arg line=" || (type _tempfile.out & del _tempfile.out & exit /b 1)"/>
<!--Next arg: Otherwise, just type the temporary file and delete it-->
<arg line=" & type _tempfile.out & del _tempfile.out &"/>
Because this hack only applies to windows, remember to add #osfamily="windows" to the apply or exec task. And create similar task(s) for `#osfamily="unix", etc but without these extra arguments.
The output of exec does go to standard out unless you specify the output attribute.
If you want to output to System.out, then simply do not specify the "output" attribute. If you would like to redirect to a file AND print it to System.out, you can use the tee command, which will redirect output to a given file and also echo it to standard out... I do not know if Windows supports "tee" or an equivalent.
Maybe you want to look at the error, logError, and errorproperty attributes of the exec task too. These deal with the handling of the standard error stream from the exec'd process. There may be useful information there that is going awol for some reason - which might account for the incompleteness you see.
But, if the exec'd process decides to close stdout or stderr and send them elsewhere - there's little you can do.
I have faced similar problem: the output of command execution was suppressed. Perhaps that is the side effect when running cmd under WinXP (I an using maven-antrun-plugin). Anyway setting output="con" worked out perfectly:
<configuration>
<target>
<exec executable="cmd" output="con">
<arg value="/c" />
<arg value="..." />
</exec>
</target>
</configuration>
Working with Ant and Gruntjs:
For anyone trying to get this to work using Gruntjs. I was able to get it working by doing the following (in combination with darcyparker's answer).
In my Ant Build File:
<target description="run grunt js tasks" name="grunt">
<exec dir="/path/to/grunt" executable="cmd" failonerror="true">
<arg value="/c"/>
<arg value="jshint.bat"/> // I broke each task into it's own exec
<arg line=" > jshint.log 2<&1"/>
<arg line=" || (type jshint.log & del jshint.log & exit /b 1)"/>
<arg line=" & type jshint.log & del jshint.log &"/>
</exec>
<exec dir="/path/to/grunt" executable="cmd" failonerror="true">
// another grunt task (IE: uglify, cssmin, ect..)
</exec>
</target>
jshint.bat
#echo off
pushd "C:\path\to\grunt\"
#ECHO _____________________________________________
#ECHO GRUNT JSHINT
#ECHO _____________________________________________
grunt jshint --stack >>jshint.log
NOTE: Path to grunt would be where your Gruntfile.js is located. Also note, I had to initially create the log file (to get it to work with darcyparker's answer) which would output the stack trace from that particular task. This would then give me the grunt task stack output from wherever I call my ant target.
Finally note that pushd "C:\path\to\grunt\" won't be necissary if your bat files are in the same directory as your Gruntfile.js.
I was experiencing this same kind of issue trying to get the build process to fail in Ant after Karma tests intentionally failed, and executing them with "grunt test".
Just added /c before "grunt test", and it worked like a charm
<target name="unittest">
<echo>*** KARMA UNIT TESTING ***</echo>
<exec dir="api_ui" executable="cmd" osfamily="windows" logError="yes" failonerror="true">
<arg value="/c grunt test"/>
</exec>
</target>

Resources