1. 程式人生 > >用Ant呼叫系統命令或外部程式

用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仍然繼續