用Ant呼叫系統命令或外部程式
最近用到了Ant,發現還是有許多功能是Ant沒有提供相應Task支援,而作業系統 提供了相應的系統命令。
Ant說明書上說了,用<exec>可以呼叫系統命令,實際操作起來才發現陷阱可不少,一不小心就會掉下去。
下面以按日期倒序列舉當前目錄下檔案為例說明。
對於Windows平臺,命令是:dir /o:-d
對於Unix(包括Linux ,下同)平臺,命令是 ls –ltr
陷阱1:呼叫誰?
這在Ant文件中已經提到了,在Windows下,不能直接呼叫dir、del(因為沒有這個程式!)等,必須通過cmd.exe來呼叫:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="cmd.exe">
<arg line="/c dir"/>
</exec>
</target>
</project>
對於Unix,則可以直接呼叫ls:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="ls"/>
</target>
</project>
也可以指明由Shell呼叫
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="/bin/sh">
<arg line="-c ls" />
</exec>
</target>
</project>
我覺得後者要好一些,否則無法保證呼叫的是否系統命令,
因為只要Path環境變數指明的路徑下有一個同名的程式,都可能被呼叫到。
通過Shell呼叫,Windows必須加 /c,Unix則是加 –c 。
陷阱2:arg line, arg value 還有引號
假如我們擴充Windows平臺下的例子,滿足按修改時間倒序的要求:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="cmd.exe">
<arg line="/c dir /o-d"/>
</exec>
</target>
</project>
成功。換Unix了:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="/bin/sh">
<arg line="-c ls -ltr" />
</exec>
</target>
</project>
對不起,失敗:java .lang.IOException。
之所以這樣,是因為<arg line>把每個空格分隔的字串作為引數傳給呼叫程式,
但是對於”/bin/sh”來說,”ls –ltr”應該是一個引數而不是兩個。
解決辦法有兩個:
加引號:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="/bin/sh">
<arg line="-c 'ls –ltr'" />
</exec>
</target>
</project>
或者使用<arg value>:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="/bin/sh">
<arg value="-c" />
<arg value="ls -ltr" />
</exec>
</target>
</project>
陷阱3:阻塞(block)
不論是Windows還是Unix,呼叫一個程式後都必須等到該操作結束才能繼續作下面的操作。
如果你想呼叫一個程式的同時還做其它的工作 ,必須使用<parallel>:
<?xml version="1.0" ?>
<project name="testExec" default="test">
<target name="test">
<exec executable="notepad.exe"/>
<echo message="You must close notepad first!"/>
<parallel>
<exec executable="notepad.exe"/>
<echo message="You do not need to close notepad."/>
<parallel>
</target>
</project>
需要注意的屬性:
dir 指明程式執行的路徑。對搜尋程式也有影響
os 指明執行的平臺
failonerror 預設為false,即該命令執行了但是失敗了,build仍然繼續