Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 68 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
68
Dung lượng
3,37 MB
Nội dung
INTRODUCING ANT’S DEPLOYMENT POWER TOOLS 443 just triggers the crisis. Here you should control the copy with overwrite= "${force}" , for case-by-case control of overwriting. 18.4.2 The <serverdeploy> task A recent addition to the Ant armory of deployment tasks is <serverdeploy>. This task is a container for different server-specific deployment elements. The ultimate aim of this task is to grow to be the one-stop-shop for deployment; it is designed so that different providers can write deployment elements for use inside the task. In Ant 1.5, the task only deploys to two severs, WebLogic and JOnAS(from http:/ /www.objectweb.org/jonas/). 18.4.3 Remote control with <telnet> The <telnet> task lets you connect to a remote host and issue a sequence of com- mands. With an insecure login and no channel encryption, production servers rarely accept inbound calls on telnet from anywhere but the local system. Most develop- ment servers, on the other hand, are malleable to <telnet> control. Table 18.1 lists the task’s attributes. Just like the <ftp> task, you need optional.jar and netcompo- nents.jar in Ant’s lib directory. You must supply the server name; for a normal login, you should supply userid and password. If you don’t supply these then you must implement the entire login pro- cess inside the task declaration. The timeout attribute has a default timeout of zero, which is interpreted as no timeout. We recommend always supplying a timeout, even one of a few minutes, to ensure that server-side problems do not lock up the build indefinitely. A timeout occurring will, of course, break the build. With this task, it is easy to connect to a server: <telnet server="${deploy.server}" userid="guest" password="secret" timeout="30" > NOTE If you cannot connect to a Windows NT server, you need to disable NTLM telnet authentication on the server; without this <telnet> can not authenticate the user. Table 18.1 Most attributes of <telnet>. You should set the first three unless you want to connect using a different port and hence protocol, in which case you should omit the userid and password. The timeout attribute is a safety net that you should always use. Attribute Meaning server Remote hostname or address userid Username for login password Login password port Port to connect to, if not port 23 timeout Timeout for commands initialCR Flag to trigger sending a carriage return before waiting for the login prompt Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 444 CHAPTER 18 PRODUCTION DEPLOYMENT Once the connection is open, you need to make use of it, which you do by using nested <read> and <write> elements. Each <read> statement declares a string that the task waits to receive before it continues. Usually the read command waits for the prompt of the remote shell, be it >, #, or some different and perhaps longer string. The longer the string, the less likely it is that executed commands will accidentally print it. The following are examples of valid reads, all examples of different prompts that we have encountered. The final prompt is an escaped angle bracket ( />), com- mon to many servers: <read string="%"/> <read timeout="30">/home/root%</read> <read string="$"/> <read string=">"/> The <write> element is the mirror image of <read>: its text goes down the wire to be interpreted by the shell or program at the far end. By default, the command string is echoed to the Ant log; there is an echo attribute you can set to false to prevent this. The following example <write> statements are representative of commands you may want to send to a server: <write string="rm /home/web/webapps/oldapp.war" /> <write string="rm -f ${server.webappdir}/${projectname}.war" /> <write >cd %JAVA_HOME%</write> <write >cd $JAVA_HOME</write> <write >ps -ef | grep java > javapps.txt </write> <write echo="false">${admin.password}</write> In these examples, we use Ant properties and environment variables on the remote system. Environment variables can be used to great advantage during deployment, as the remote site itself can be preconfigured with information about where to deploy things. Apart from property expansion, Ant performs no transformations to the com- mand string: file paths must be in the appropriate format for the target server. There is a nice task called <pathconvert> that can turn a path into a property in the appropriate form for both Unix and Windows; you may find this convenient in pre- paring data for this task. To use the <telnet> task, as we stated before, <read> and <write> statements need to be interlaced, with commands being issued after responses are received. Listing 18.2 shows this. <target name="shutdown-remote-server"> <property name="deploy.server" value="eiger" /> <property name="deploy.server.prompt" value="bash-2.04$$" /> <telnet server="${deploy.server}" userid="tomcat" password="********" Listing 18.2 Shutting down a remote server with telnet Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com INTRODUCING ANT’S DEPLOYMENT POWER TOOLS 445 timeout="30" > <read string="${deploy.server.prompt}"/> <write string="cd $CATALINA_HOME/bin" /> <read string="${deploy.server.prompt}"/> <write>./shutdown.sh</write> <read string="${deploy.server.prompt}"/> </telnet> </target> After connecting to the server, we wait for the login prompt then change to the server’s bin directory, where we call the shutdown script. With properties defined for the server and the prompt, this telnet target is nearly ready for factoring out into its own library build file. We could then use <ant> to call it from multiple build files, or against multiple servers. Notice how we close the telnet session with a <read> of the command prompt, to keep the connection open until the final command has completed. This is vital. Without this <read>, the server at the far end may not completely execute the final command sent. When we run this target against our remote server, the output will, if all is suc- cessful, look something like the following: shutdown-remote-server: [telnet] Red Hat Linux release 7.1 (Seawolf) Kernel 2.4.2-2 on an i686 login: [telnet] tomcat [telnet] Password: [telnet] bash-2.04$ [telnet] cd $CATALINA_HOME/bin [telnet] cd $CATALINA_HOME/bin bash-2.04$ [telnet] ./shutdown.sh [telnet] ./shutdown.sh Using CLASSPATH: /opt/Java/Apps/jakarta-tomcat-4.0.1/bin/bootstrap.jar: /usr/java/j2sdk1.4.0/lib/tools.jar Using CATALINA_BASE: /opt/Java/Apps/jakarta-tomcat-4.0.1 Using CATALINA_HOME: /opt/Java/Apps/jakarta-tomcat-4.0.1 Using JAVA_HOME: /usr/java/j2sdk1.4.0 bash-2.04$ BUILD SUCCESSFUL Total time: 8 seconds One of the inconveniences of this approach is that you have to spell out in detail each command, often in a platform- and shell-specific manner, and list the responses you expect. The other is that you cannot deal well with any failure of a command in the Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 446 CHAPTER 18 PRODUCTION DEPLOYMENT chain. It is best to write a shell script or batch file to run on the remote machine, FTP it over, then run it. NOTE Before Ant 1.5, the <telnet> task did not expand properties in nested text inside <read> and <write>, but did in their string attributes. If you want to write a build file that uses properties inside <telnet> con- sistently, use attributes instead of nested text: <read string="$$"/> <write string="nohup ${command}&"/> This was one of those tough “should we fix this behavior and maybe break things” problems; the change only stayed in because we made some other fixes to system behavior to keep more things working (i.e., Ant stopped si- lently removing single dollar signs from strings). The consensus was that stopping this odd behavior was so important that the risk to some build files could be tolerated, but it was not at all clear-cut. We are going to use the <telnet> task to execute the deployment build files we have uploaded to the remote servers. This gives Ant absolute control of the build without us having to write and test complex <telnet> sequences. 18.5 BUILDING A PRODUCTION DEPLOYMENT PROCESS Enough talking, let’s sit down and write the build file, using the tools we have intro- duced in section 18.4 and the process we described in section 18.3. 18.5.1 The plan Here is our simple plan to support remote deployment to multiple servers: 1 Move deployment out to a new build file, remotedeploy.xml. 2 Use a configuration file for each application server type to indicate at build time which libraries are needed. 3 Use a configuration file for each target system to provide information about the system: server type, upload account, password and directory, and whether the system is a debug or release server. 4 Have a separate install-time build file for each application server type; a build file that is run on the target system. 5 Have a system-specific configuration file containing install-time configuration data—the ultimate deployment directory—and an application server username and password if needed. 6 Have the main build file create a WAR file for a particular server, upload it to the destination, then use <telnet> to run the appropriate installation file. One of the interesting tricks here is that we will dynamically determine the hostname in the build file. On the remote server, this lets us pick the appropriate properties file Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com BUILDING A PRODUCTION DEPLOYMENT PROCESS 447 for the machine. On the local build server, we can do the same thing to pick up the name of our build time configuration file. This lets us keep all the deployment details for individual developers under CVS, if the security is adequate. 18.5.2 The directory structure First, we create a new directory tree under webapp to house all the configuration files. We need one configuration file per server type and two per target server, one at build time and one to be uploaded and used during the installation process. The uploaded configuration files should not contain system usernames and passwords, for security reasons, though they may need app server account details. See figure 18.4. 18.5.3 The configuration files If this looks complicated, don’t panic. You need one configuration file and one instal- lation build file per server type, and two configuration files per target system. If you are using the same application server everywhere, then you don’t need many server- type specific files, just those per-system configuration files and a pair of common configuration files to minimize duplication. We are going to start by targeting Tomcat 4.0 on different systems, addressing other server types when the need arises. 18.5.4 The build files The complete build files are too large to place in their entirety in this chapter. We shall just cover the core pieces of the process, and state the gist of what we have omitted. 18.5.5 The remote build.xml build file A centerpiece of this process is a build file that developers or operations will run on the remote server. This file determines the identity of the target system, loads the appropriate configuration file, determines the type of application server in use, and calls the appropriate build file for that server. ranier.properties common.properties nordwand.properties eiger.properties servertypessystems remote tomcat4.1.properties bluestone8.1.properties tomcat4.0.properties jboss3.0.properties tomcat4.0.xml tomcat4.1.xml jboss3.0.xml bluestone8.1.xml install-eiger.properties install-ranier.properties install-nordwand.properties common.properties build.xml deploy.xml deploy Figure 18.4 The configuration file layout. The systems and servertypes directories are used at build time; the remote directory contains the files uploaded and executed on the remote system. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 448 CHAPTER 18 PRODUCTION DEPLOYMENT Identifying the local host We identify the local host by looking at the standard environment variables: <property environment="env"/> <property name="env.HOSTNAME" value="${env.COMPUTERNAME}"/> <property name="hostname" value="${env.HOSTNAME}"/> This extracts the hostname from both the Windows NT and the Unix environment variables. Apparently, it does not work on Mac OS X; non-Unix platforms are an unknown. We have a <hostname> task in the pipeline that will work across all plat- forms, but it came in too late for Ant 1.5. Loading in the system-specific details With the hostname, we can load in hostname-specific properties <property name="config.file" location="install-${hostname}.properties"/> <property file="${config.file}" /> <property file="common.properties" /> These steps read in the configuration file type for the local system, such as this one: target.servertype=tomcat4.0 target.username=admin target.password=password target.port=8080 Ant then loads the common properties file, containing the definitions you do not want to duplicate: target.appname=antbook target.warfile=${target.appname}.war Handing off to the specific build files With the name of our application server, Ant can choose the appropriate build file for the install: <property name="build.file" location="${target.servertype}.xml"/> Running this is a matter of an <ant> call: <target name="install" depends="init"> <ant antfile="${build.file}" inheritall="false"/> </target> The full build file contains validation tests in the init target, for a more robust build. In particular, the target verifies that all the configuration files were present, and that target.servertype is defined. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com BUILDING A PRODUCTION DEPLOYMENT PROCESS 449 18.5.6 Writing the build file for installing to a server For our Tomcat 4.0 deployment, we have taken the code from section 7.7, somewhat simplified as we know we are always deploying to the local host. We do want to be rigorous in deployment, however, copying the files in under the CATALINA_ HOME/webapps directory, so that when the server restarts our application restarts with it. Reusing the same tricks of section 18.5.5 to load application-specific content, we set up some properties to point to the destination directories and files: <property name="target.deploy.directory" location="${env.CATALINA_HOME}/webapps"/> <property name="webapp.expanded.dir" location="${target.deploy.directory}/${target.appname}" /> <property name="webapp.copied.file" location="${target.deploy.directory}/${target.appname}.war" /> We copy the unexpanded WAR file for server restart, and then expand it for the installation onto the running server. Unloading the current installation We will omit the unload target, which issues a <get> against http://localhost:8080/manager/remove?path=/${target.appname} We have demonstrated this in section 7.7. Obviously, we can override the port; most production servers run at port 80. One option to consider here is to actually shut down the application server entirely. This guarantees that any spawned threads are destroyed, and all memory is released. If you do this then you do not need to register the application with Tomcat after deployment, you need to restart Tomcat which is a harder task. Cleaning up the installation For production, we always clean out the previous set of files; after unloading the application from Tomcat, we wait a few seconds then delete the WAR file in its expanded and unexpanded state. <target name="clean" depends="unload" description="clean up: unload app and delete all files"> <sleep seconds="${target.sleep.seconds}" /> <delete file="${webapp.copied.file}" /> <delete dir="${webapp.expanded.dir}" /> </target> Some servers do not always unload all libraries, especially for JAR files containing javax packages. We could set the failonerror flag to false to keep going, but we may encounter problems at unzip time. If this is a common issue, you will need to shut down the web server every deployment. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 450 CHAPTER 18 PRODUCTION DEPLOYMENT Copying the files After cleanup, we copy in the new files: <target name="install-files" depends="clean"> <copy file="${target.warfile}" tofile="${webapp.copied.file}"/> <unzip dest="${webapp.expanded.dir}"/> </target> This leaves us ready to run the application through a server restart or via a manage- ment URL call. The paranoid will restart the server, but we will go for the hot- update. Loading the application Again, a manager URL call will start the program; a <get> against http://localhost:8080/manager/install?path=/${target.appname} &war=file://${webapp.expanded.dir} That’s it. It takes a few seconds longer than usual, with the delete, the copy, and the expansion, but it still only takes 15-20 seconds, all in. 18.5.7 Uploading to the remote server We need to get our local installation and configuration files to the remote server. FTP is the path we shall choose, for now. We do all this in our top-level deploy.xml file, a file that resides in the webapp directory and presides over deployment. Configuring the upload First Ant must determine which files are needed at the far end. We don’t want to send any more files than are needed, to prevent confusion and maintain security. If we build different WAR files for different targets, it is critical that nobody installs them on the wrong machine; stripping out the other build and configuration files helps achieve this. Although we repeat the same hostname trick of section 18.5.5, we expect the system to usually be called with a remote hostname defined, such as from the command line: ant -Dhostname=eiger The build file loads in the property files for the hostname and makes a list of which files are needed. <property name="config.file" location="${systems.dir}/${hostname}.properties"/> <property file="${config.file}" /> <property file="${systems.dir}/common.properties" /> <property name="servertype.file" Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com BUILDING A PRODUCTION DEPLOYMENT PROCESS 451 location="${servertypes.dir}/${target.servertype}.properties"/> <property file="${servertype.file}" /> <property name="redeploy.dir" location="dist/redeploy" /> <property name="remote.config.file" location="${remote.dir}/install-${hostname}.properties"/> <property name="remote.build.file" location="${remote.dir}/${target.servertype}.xml"/> The configuration files at build time contain more information than those we upload. In particular, they can contain passwords to the server: target.server=eiger login.userid=tomcat4 login.password=topsecret ftp.remotedir=/home/tomcat4/install telnet.cd.directory=${ftp.remotedir} target.servertype=tomcat4.0 target.server.debug=false target.isUnix=true We derive some other values from these properties; the aim is to allow target systems to define them in their configuration files if necessary, such as with different FTP and tel- net login accounts, or with different servers and ports for SSH-tunneled connections: <property name="ftp.server" value="${target.server}"/> <property name="ftp.port" value="21"/> <property name="telnet.server" value="${target.server}"/> <property name="telnet.port" value="23"/> <property name="ftp.userid" value="${login.userid}"/> <property name="ftp.password" value="${login.password}"/> <property name="telnet.userid" value="${login.userid}"/> <property name="telnet.password" value="${login.password}"/> The build files also read in the application server-specific configuration files. These state what features are in the server: server.isj2ee=false server.jsp.version=2.3 server.j2ee.version=0 server.xerces.needed=false These settings can be used to control WAR file generation, either in conditional <patternset> includes of JAR files, or in the <webdoclet> task. We don’t need to do this, yet, but the option is important. Obviously, these configuration files are reusable across many projects. Building a directory of upload files Based on the configuration details, Ant knows which files to upload, so it copies them to a new redeployment directory, combining the configuration files with the WAR file itself. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 452 CHAPTER 18 PRODUCTION DEPLOYMENT <target name="build-deployment-package" depends="init"> <copy todir="${redeploy.dir}" file="${warfile}"/> <copy todir="${redeploy.dir}" file="${remote.config.file}"/> <copy todir="${redeploy.dir}" file="${remote.build.file}"/> <copy todir="${redeploy.dir}" file="${remote.dir}/build.xml"/> <copy todir="${redeploy.dir}" file="${remote.dir}/common.properties"/> </target> A local deployment can run straight from this directory; this is the simplest way to test the process. Indeed, a quick test for ${ hostname} equaling ${env.HOST- NAME} lets the build file deploy this way on a local system: <target name="install-local" depends="build-deployment-package" if="is.localhost"> <ant dir="${redeploy.dir}" inheritall="false"/> </target> Uploading the files We will rely on the trusty <ftp> task for deployment, called three times in a row. <target name="upload" depends="build-deployment-package" unless="is.localhost" > <echo>connecting to ${target.server} as ${ftp.userid} into ${ftp.remotedir} </echo> <ftp server="${ftp.server}" port="${ftp.port}" action="mkdir" remotedir="${ftp.remotedir}" userid="${ftp.userid}" password="${ftp.password}" verbose="true" passive="true" ignoreNoncriticalErrors="true" /> <ftp server="${ftp.server}" port="${ftp.port}" remotedir="${ftp.remotedir}" userid="${ftp.userid}" password="${ftp.password}" depends="true" verbose="true" passive="true" binary="true" ignoreNoncriticalErrors="true" > <fileset dir="${redeploy.dir}"> <include name="**/*.war"/> </fileset> </ftp> <ftp server="${ftp.server}" port="${ftp.port}" remotedir="${ftp.remotedir}" userid="${ftp.userid}" password="${ftp.password}" b c Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... http://www.simpopdf.com C H A P T E R 1 9 Writing Ant tasks 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19 .8 What exactly is an Ant task? 4 68 Ant API primer 470 How tasks get data 474 Creating a basic Ant Task subclass 483 Operating on a fileset 485 Error handling 486 Testing Ant tasks 487 Executing external programs 487 19.9 19.10 19.11 19.12 19.13 Executing a Java program within a task 490 Supporting arbitrarily named... Java class requires Java development experience, and the tools to compile the source and make a JAR file from the generated bytecodes This is exactly the same development skill that anyone using Ant for Java development has, and as for the tools needed Ant and the Java SDK are all that is required People overcoming their projects’ build problems wrote all the Ant tasks that come with Ant today The time... make up the Ant codebase, but several key classes that are used in the majority of Ant tasks are worth noting This is an intentionally brief and focused view of Ant s API In practice, these are the classes and methods that you will work with most frequently Ant ships with complete Javadoc references and is well documented With Ant s source code being open, it is easy to learn Ant task development tricks... firewalls 18. 5 .8 The remote deployment in action When you actually run the build, the most surprising thing is how ordinary it is Getting passwords right on remote systems configured with Java, Tomcat, and Ant are chores, but the build itself flies along nicely We show a fragment of the full build in listing 18. 3, omitting the preceding FTP upload, and the functional tests that follow Listing 18. 3 Ant running... Ant was designed to be extendible through Java classes, and it only takes a small amount of Java coding to write a new Ant task If the problem lies in the actual Ant source itself, then the fact that an entire Ant source tree is a download away comes into play If Ant does not work right, then it can be fixed 467 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Adding a new Java. .. WebLogic 7.0 comes with its own copy of Ant We recommend that you rename its version of ant. bat and ant. sh, so that you do not accidentally use that version It is very confusing when there is more than one version of the Ant shell script/batch file on your path, as you may accidentally use an older version of Ant, and may not be adding optional libraries to the appropriate directory 18. 6.3 HP Bluestone... currently one major flaw with this task—it does not work from a normal Ant execution environment, only the vendor’s RadPak Ant GUI tool We don’t know why this is the case, but it stops you deploying via this task from any automated build and deploy process 18. 6.4 Other servers There are many more application servers, each with its own deployment process, but without explicit Ant support We leave deploying... /home/tomcat4/tomcat4.0/webapps/antbook [telnet] install-files: [telnet] [copy] Copying 1 file to /home/tomcat4/tomcat4.0/webapps [telnet] [unzip] Expanding: /home/tomcat4/tomcat4.0/webapps/antbook.war into /home/tomcat4/tomcat4.0/webapps/antbook [telnet] deploy: [telnet] [get] Getting: http://127.0.0.1 :80 80/manager/install?path=/antbook &war=file:///home/tomcat4/tomcat4.0/webapps/antbook [telnet] [echo] OK... is a pleasant addition to writing tasks, allowing you to deal with richer objects in your task than simple strings Inspired by a request by one of the developers of the task who asked that Ant support hexadecimal numbers natively, we decided to add our own support for it by defining a Hex type1 shown in listing 19.3 1 4 78 A variant of this was added to Ant s codebase as org.apache.tools .ant. types.FlexInteger... [telnet] install: 454 CHAPTER 1 8 PRODUCTION DEPLOYMENT Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [telnet] init: [telnet] unload: [telnet] [get] Getting: http://127.0.0.1 :80 80/manager/remove?path=/antbook [telnet] [echo] OK - Removed application at context path /antbook [telnet] clean: [telnet] [delete] Deleting: /home/tomcat4/tomcat4.0/webapps/antbook.war [telnet] [delete] . http://eiger :80 80/antbook/timestamp.txt It is only when something has gone wrong that the target contains any message of importance: verify-uptodate: [get] Getting: http://eiger :80 80/antbook/timestamp.txt BUILD. http://127.0.0.1 :80 80/manager/remove?path=/antbook [telnet] [echo] OK - Removed application at context path /antbook [telnet] clean: [telnet] [delete] Deleting: /home/tomcat4/tomcat4.0/webapps/antbook.war . /home/tomcat4/tomcat4.0/webapps/antbook [telnet] deploy: [telnet] [get] Getting: http://127.0.0.1 :80 80/manager/install?path=/antbook &war=file:///home/tomcat4/tomcat4.0/webapps/antbook [telnet] [echo]