I have the following ant snippet
<macrodef name="webapp.start">
<attribute name="name" />
<sequential>
<!--deploy-->
<antcall target="webapp.#{name}" />
<!--start server-->
<antcall target="tomcat-server-start" />
<!--go to URL-->
<exec executable="firefox" os="Linux" >
<arg line="-new-tab http://localhost:${tomcat.port}/#{name}" />
</exec>
</sequential>
</macrodef>
It starts the server but does not open the browser. If I put the exec task in a separate target and run it, it works fine. I am guessing that starting the server which is a process that does not end, the next one does not begin. How to do I overcome this issue? Is there a way I can start exec as a separate process.
I am guessing that starting the server which is a process that does not end, the next one does not begin
I would spend a minute making sure this is the case. Use pgrep or ps to figure out what your processes are up to.
If you confirm the server never finishes, I would have the command "tomcat-server-start" start in the background (by postfixing the shell command with &), unless it is a big deal if firefox starts before tomcat-server. Alternatively, use a parallel block within your sequential block, like this:
<macrodef name="webapp.start">
<attribute name="name" />
<sequential>
<!--deploy-->
<antcall target="webapp.#{name}" />
<parallel>
<!--start server-->
<antcall target="tomcat-server-start" />
<!--go to URL-->
<exec executable="firefox" os="Linux" >
<arg line="-new-tab http://localhost:${tomcat.port}/#{name}" />
</exec>
</parallel>
</sequential>
</macrodef>
Related
I have a got a ANT build system which invokes builds on different projects using following macro;
<macrodef name="buildComponent">
<attribute name="name"/>
<attribute name="dir"/>
<attribute name="antTarget"/>
<attribute name="antCommonDistDir" />
<sequential>
<available property="build.xml.exists.#{dir}" file="#{dir}/build.xml" />
<if>
<equals arg1="${build.xml.exists.#{dir}}" arg2="true" />
<then>
<java classname="org.apache.tools.ant.launch.Launcher"
fork="true"
failonerror="true"
dir="#{dir}"
timeout="4000000"
output="${common.build.dir}/log/#{name}.log"
taskname="startAnt" >
<jvmarg value="-Dant.home=${ant.home}"/>
<classpath>
<pathelement location="${ant.home}/lib/ant-launcher.jar"/>
</classpath>
<arg value="-Dbasedir=#{dir}"/>
<arg value="#{antTarget}"/>
<arg value="-Dprop1=${prop1}" />
<syspropertyset refid="project.common.properties" />
<sysproperty key="common.dist.dir.os" value="#{antCommonDistDir}" />
</java>
</then>
</if>
</sequential>
</macrodef>
I would like to override properties form command line but the problem is that these properties are not being passed by task and my subsequent build uses the default values. For example I am executing the build as follows;
ant dist -Dprop1=override.prop1 -Dprop2=override.prop2 -Dprop3=override.prop3
As you see currently the only option for me to pass these overridden values from command line for prop2 and prop3 is add <arg /> under <java /> task for each property passed like I have done for 'prop1' which works but not desirable. Is there anyway I can access all properties passed to ANT and simply pass them as is to <java /> task?
You can use the echoproperties task to save all current Ant properties to a file, and then pass that file to the java task to be loaded by the subproject.
<echoproperties destfile="my.properties"/>
Having said this, a better solution instead of executing the java command to invoke another Ant build, you can simply call the ant task which will build your subproject and automatically inherit all properties from the parent project:
<available property="build.xml.exists.#{dir}" file="#{dir}/build.xml" />
<if>
<equals arg1="${build.xml.exists.#{dir}}" arg2="true" />
<then>
<ant antfile="#{dir}/build.xml" target="#{antTarget}"/>
</then>
</if>
I couldn't find any thing which can do this directly. So I ended up writing a javascript and populated a ant property to parse command line options which was stored in env variable and passed it to <java /> task as <arg line="${command.line.properties}" />. Remember to use <arg line="" /> as it trim out all extra spaces etc before invoking a task.
I'm aware that I can <exec executable="cp" failonerror="true">, however, I'd really rather have a task that I can call from any OS that can use all (or at least most) of the attributes to copy, but which doesn't suck away the permissions on unix.
I am wondering if there is already a solution out there, or will I have to write my own copy2.
As I was kind of afraid, there's nothing "off the shelf". We have this code, but it only handles directory to directory copy or file to file copy, has custom attributes, and doesn't do any of the other neat things copy does.
<!-- ==================================================================== -->
<!-- Copy files from A to B -->
<!-- <copy> would do this job, if it weren't such a useless pile of fail -->
<!-- and could manage to preserve execute bits on Linux -->
<!-- ==================================================================== -->
<macrodef name="internal-copydir">
<attribute name="fromdir" default="NOT SET" />
<attribute name="todir" default="NOT SET" />
<sequential>
<if>
<os family="windows" />
<then>
<copy todir="#{todir}">
<fileset dir="#{fromdir}" />
</copy>
</then>
<else>
<exec executable="rsync" failonerror="true">
<arg value="-a" />
<arg value="#{fromdir}/" />
<arg value="#{todir}/" />
</exec>
</else>
</if>
</sequential>
</macrodef>
<!-- ==================================================================== -->
<!-- Copy file from A to B -->
<!-- <copy> would do this job, if it weren't such a useless pile of fail -->
<!-- and could manage to preserve execute bits on Linux -->
<!-- ==================================================================== -->
<macrodef name="internal-copyfile">
<attribute name="file" default="NOT SET" />
<attribute name="tofile" default="NOT SET" />
<sequential>
<if>
<os family="windows" />
<then>
<copy file="#{file}" tofile="#{tofile}"/>
</then>
<else>
<exec executable="cp" failonerror="true">
<arg value="#{file}" />
<arg value="#{tofile}" />
</exec>
</else>
</if>
</sequential>
</macrodef>
I wrote this one too.
<!-- ==================================================================== -->
<!-- Copy file to a directory -->
<!-- <copy> would do this job, if it weren't such a useless pile of fail -->
<!-- and could manage to preserve execute bits on Linux -->
<!-- ==================================================================== -->
<macrodef name="internal-copyfiletodir">
<attribute name="file" default="NOT SET" />
<attribute name="todir" default="NOT SET" />
<sequential>
<if>
<os family="windows" />
<then>
<copy file="#{file}" todir="#{todir}"/>
</then>
<else>
<exec executable="cp" failonerror="true">
<arg value="#{file}" />
<arg value="#{todir}/" />
</exec>
</else>
</if>
</sequential>
</macrodef>
I'm not aware of one. As mentioned in the Ant documentation, this is because there was no mechanism to manipulate file permissions in the JRE. Ant Copy task
Java 7 brings much better support for this sort of thing, so perhaps in a future version of Ant this will be possible. This will likely take a very long time, as I think Ant is only moving to Java 5 for version 1.9.
I guess you might be able to simulate the behavior you are looking for by conditionally running OS specific commands based on the OS?
It's not ideal, but there is the "chmod" task that you could use to set the permissions on each file after a "copy" or "copydir":
http://ant.apache.org/manual/Tasks/chmod.html
Is there a way of conditionally redirecting the output to property or the stdout stream as the non-working example below?
<macrodef name="mytask">
<attribute name="output" default="STDOUT"/>
<sequential>
<exec executable="my.exe" outputproperty="#{output}"/>
</sequential>
</macrodef>
The above example redirects the output by default to a property STDOUT. Instead I would like it to be directed to the stdout stream.
I could create mytask_with_stdout as a copy of the above macro and remove the exec outputproperty, but that would violate the DRY principle.
Is there some nice way of doing this?
There are two Ant features you can combine to get what you want.
First, a <macrodef> can be passed whatever <element> you want.
Second, a <redirector> can be used to capture the output of an <exec> command in a property.
I ran the following Ant script on a Windows machine so I could use cmd.exe's echo command. Replace the cmd.exe with your my.exe:
<project name="exec-redirector-example" default="run">
<macrodef name="mytask">
<attribute name="message"/>
<element name="myredirector" optional="true"/>
<sequential>
<exec executable="cmd.exe">
<arg value="/c"/>
<arg value="echo"/>
<arg value="#{message}"/>
<myredirector/>
</exec>
</sequential>
</macrodef>
<target name="run">
<!-- exec outputs to STDOUT by default -->
<mytask message="To STDOUT">
</mytask>
<!-- exec outputs to a property in this example -->
<mytask message="To property">
<myredirector>
<redirector outputproperty="my.property"/>
</myredirector>
</mytask>
<echo>${my.property}</echo>
</target>
</project>
The following is my ant script:
<project name="nightly_build" default="main" basedir="C:\Work\6.70_Extensions\NightlyBuild">
<target name="init">
<sequential>
<exec executable="C:/Work/Searchlatestversion.exe">
<arg line='"/SASE Lab Tools" "6.70_Extensions/6.70.102/ANT_SASE_RELEASE_"'/>
</exec>
<property file="C:/Work/latestbuild.properties"/>
<sleep seconds="10"/>
<echo message="The product version is ${Product_Version}"/>
<exec executable="C:/Work/checksnapshot.exe">
<arg line='"ANT_SASE_RELEASE_${Product_Version}_SASE Lab Tools-NightlyBuild" ANT_SASE_RELEASE_${Product_Version}_AnalyzerCommon-NightlyBuild ${Product_Version}-AppsMerge' />
</exec>
<property file="C:/Work/checksnapshot.properties"/>
<tstamp>
<format property="suffix" pattern="ddMMyyyyHHmm"/>
</tstamp>
</sequential>
</target>
<target name="main" depends="init">
<echo message="loading properties files.." />
<sleep seconds="10"/>
<echo message="Backing up folder" />
<move file="C:\NightlyBuild\NightlyBuild" tofile="C:\NightlyBuild\NightlyBuild.${suffix}" failonerror="false" />
<parallel>
<exec executable="C:/Work/sortfolder.exe">
<arg line="6" />
</exec>
<exec executable="C:/Work/6.70_Extensions/NightlyBuild/antc.bat">
</exec>
</parallel>
</target>
</project>
Basically the sequence goes something like this:
I will run Searchlatestversion.exe and write latestbuild.properties
Using the latestbuild.properties i will obtain ${Product_Version} and would like to allow checksnapshot.exe access to latestbuild.properties and obtain ${Product_Version}
checksnapshot.exe will then generate checksnapshot.properties which will then be used by the target in main antc.bat
am i doing something wrong over here? seems like ${Product_Version} is not being received well by checksnapshot.exe
You appear to have a hard coded wait period of 10 seconds for Searchlatestversion to write out your file. If the executable does not complete inside that time, ${Product_Version} cannot be read from file.
Have you considered using the Waitfor Ant Task? As the name implies, this will wait for a certain condition before it will allow the rest of the task to progress. You could do something like
<property name="props.file" value="C:/Work/latestbuild.properties"/>
<waitfor maxwait="10" maxwaitunit="second">
<available file="${props.file}"/>
</waitfor>
<property file="${props.file}"/>
Does Searchlatestversion.exe produce the file C:/Work/latestbuild.properties?
If so, should you not sleep/wait before you load that properties file?
You have this:
<exec .../>
<property file="C:/Work/latestbuild.properties"/>
<sleep seconds="10"/>
Should you not have this:
<exec ... />
<sleep seconds="10"/>
<property file="C:/Work/latestbuild.properties"/>
If i run a task as root, is there a way to detect its being run as root and run certain tasks as a different user.
I have certain tasks that need to run as root but others that just need to run as the current user.
You can use something like the following to only run certain targets if the current user has a certain name, such as 'root'.
<condition property="rootTasksEnabled">
<equals arg1="${user.name}" arg2="root" />
</condition>
<target name="do-stuff-if-root" if="rootTasksEnabled">
<echo>Doing root stuff</echo>
</target>
As for running Ant as a different user, you could use <exec> with the su command to spawn another Ant process:
<target name="do-stuff" depends="do-stuff-if-root, do-other-stuff" />
<condition property="rootTasksEnabled">
<equals arg1="${user.name}" arg2="root" />
</condition>
<property name="targetToRunAsOtherUser" value="do-stuff-as-other-user" />
<property name="otherUser" value="johnny" />
<target name="do-stuff-if-root" if="rootTasksEnabled">
<echo>Doing root stuff</echo>
<exec executable="su">
<arg value="-c" />
<arg value="${ant.home}/bin/ant -buildfile ${ant.file} ${targetToRunAsOtherUser}" />
<arg value="${otherUser}" />
</exec>
</target>
<target name="do-other-stuff">
<echo>Doing normal build stuff</echo>
</target>
<target name="do-stuff-as-other-user">
<echo>I am running as ${user.name}</echo>
<echo>My home is ${user.home}</echo>
</target>
This example only works under Unix. To do this in Windows you could probably use the runas command instead of su.