Thursday, October 31, 2002

Uygulama Servisi Başlatmak ve Beklemek

Farzedelim ki bazı testlerimizin (entegre testleri) işlemesi için, Weblogic, JBoss ya da Tomcat'in çalışıyor olması gerekiyor. Entegre testleri, birim testlerinin aksine direk komut satırından ya da müşteri tarafında (client side) çalıştırılamaz, meselâ, yazdığımız bir EJB modülünü test etmek için, EJB'nin kesinlikle çalışıyor olması, yâni Weblogic üzerine konmuş ve Weblogic'in çalışıyor durumda olması gerekecektir.

Biz de bunun üstüne entegre testlerini otomize olarak çalıştırmak istersek, ki Extreme Programcılık dahilinde bunu yapmamız gerekecektir, o zaman bir problemle karşılaşırız. Diyelim ki Weblogic'i startup.bat gibi bir betik ile ateşledik. Arkasından hemen entegre testlerini işleteceğiz. Fakat, Weblogic'in başlamış olduğunu nasıl anlayacağız ki hemen arkasından entegre testlerine devam edebilelim? Weblogic bâzen 30 saniye, bâzen 1 dakikada ayağa kalkıyor olabilir. Zamanlama ile bu işi çözemeyiz.

Demek ki, bir yere bakarak Weblogic'in durumunu öğrenmemiz gerekiyor. Bunu her uygulama servisinin dışarı afişe ettiği port üzerinden öğrenebiliriz. Fakat daha da kolayı, her uygulama servisinin muhakkak yazdığı bir log dosyasında belli aralarla Perl ile tarama yaparak bir anahtar kelimenin gelmesini beklemektir. Bu, Weblogic için "listenin on port 7001" dir, Tomcat için başka bir şey olabilir.

Alttaki Perl programı ve Ant komutları, bu amaç için kullanılabilir. İlk önce, bir uygulama servisi log dosyasını okuyan ve belli bir kelime bekleyen programı gösterelim.

while (! /$ARGV[1]/) {
open IN, $ARGV[0];
undef $/;
$_ = <IN>;
print "\nServisin ba�lamasını bekliyoruz ... $ARGV[0] taranıyor\n";
sleep (2);
close(IN);
}


Bu program, Perl programına $ARGV[0] (ilk parametre) ile gönderilen log dosya ismini okuyarak, $ARGV[1] kelimesininde belirtilen kelimeyi tarayarak, beklemektedir. Kelime bulunmazsa, 2 saniye uyuyarak tarama tekrar yapılır. Bu betik, genelde build.xml içinden çalıştırılacaktır, çünkü entegre testlerini Ant içinden işletiriz. Ant içinde bu çağırımın nasıl yapıldığını görelim. Dikkat, bu çağırım sadece beklemek için; Servisi başlatmak için değil.

 <target name="servis-bekle">
<exec executable="perl">
<arg line="./servisBasladimi.pl"/>
<arg line="${bea.dizin}/gmlcdomain.log"/>
<arg line="${sunucu.hazir.kelimesi}"/>
</exec>
</target>


Ant içinde kullandığımız değişkenleri, build.properties içinde tutuyoruz.

bea.dizin=D:/bea/user_projects/domains/gmlcdomain
bea.dizin.win=D\:\\bea\\user_projects\\domains\\gmlcdomain
cygwin=d:/cygwin
sunucu.hazir.kelimesi="listening on port 7001"

Ant içine aşağıdaki ibareyi ekleyerek, bu değişkenleri okuyabiliriz

    


Komut satırından servis-bekleyi çağırdığımız zaman, ve Weblogic başlar başlamaz bu komut geri dönecektir. Geri dönmesi de bizim için yeterli, çünkü "ant filan falan servis-bekle entegre-testleri" komutu verince, servis-bekle geri dönünce, entegre-testlerine geçilebilecektir.

Şimdi, servisi başlatmayı da otomize hâle getirelim. Fakat ondan da önce, o anda çalışıyor olan servisi öldürmemiz gerekiyor.

Bu, Unix programcıları için gereksiz bir paragraf olabilir. Sonuçta pkill ile isi vererek Linux ve Solaris üzerinde istediğiniz süreci öldürebiliyorsunuz. Windows için bazı ekler yapmak gerekecek.

Cygwin ve ps

Windows üzerinde Unix komutlarını kullanabilmek için Cygwin programını kullanıyoruz. Cygwin içinde ps mevcut,. Seçeneksiz olarak kullanılan ps komutu, sadece Cygwin tabanlı süreçleri göstermektedir. Windows süreçlerini de görmek istiyorsak, ps -W komutunu kullanmamız gerekiyor. O zaman şöyle bir betik yazabiliriz.

01:   $_ = `ps -W | grep bea`;
02: /^\s*(\d*)\s*/;
03: exit if ($1 eq "");
04:
05: `$ARGV[0]/bin/kill --force -9 $1`;

Tamam. Bu kodda neler oluyor? İlk satırda (#1) grep ile "bea" kelimesini taradığımızı görüyoruz. Bu kelime yerine istediğiniz anahtar kelimeyi kullanabilirsiniz. ps -W ile tüm listeye bakın, öldürmek istediğiniz sürecin satırında kendine has bir kelime var mı? O kelimeyi kullanın.

ps -W çıktısı şöyle gözükecek:

1064       0       0       1064    ?    0 19:04:43 C:\emacs-21.3\bin\emacs.exe
1448 0 0 1448 ? 0 19:31:43 C:\Program Files\Mozilla
1596 0 0 1596 ? 0 19:04:24 C:\WINDOWS\Explorer.EXE

Şimdi, ps komutu çıktısından PID (process no'su) çıkartılması/alınması gerekiyor. Bunu yapmamız lâzım, çünkü, kill komutuna verecek PID numarasını bir şekilde bulmamız gerekiyor. Yâni yukarıdaki örnekte 1596 sayısı... Bu işlemi basit bir düzenli ifade ile (#2) hemen yapabiliyoruz. Bundan sonra tek yapmamız gereken kill komutu ile bu PID'i öldürmektir. Ama dikkat! Direk Unix kill, Windows süreçleri üzerinde çalışmıyor, --force seçeneğini de geçmemiz gerekecek.

(#5)'de $ARGV[0] kullanımına dikkat; Bu ARGV Cygwin programının kurulduğu dizini gösteriyor. Ps ve kill komutlarının PATH'te olmama şansına karşı bunu yapmak daha uygun oldu.

Bu betiğin Ant'ten nasıl çağırıldığına gelelim.

        ...
<target name="weblogic-durdur">
<exec executable="perl">
<arg line="./servisOldur.pl"/>
<arg line="${cygwin}"/>
</exec>
<exec executable="${cygwin}/bin/rm">
<arg line="${bea.dizin.win}/gmlcdomain.log"/>
</exec>
</target>



Artık servis başlatmaya hazırız! Bunun için birkaç takla daha atmamız lazım: Ant'in başlatma işlemine "kitlenmemesi" yâni ona takılıp kalmaması için, exec etiketinde spawn=yes seçeneğini kullanmamız gerekiyor. Bekleme işini exec'de değil, Perl betiği ile dışarıdan yapıyoruz, unutmayalım. Spawn seçeneği exec'de verilen komutu sallar, ve sonucunu beklemeden geri döner. Bizim istediğimiz de bu zaten, çünkü hemen arkasından servis-bekle komutunu işletecegiz.

 <target name="weblogic-baslat" depends="weblogic-durdur">
<exec executable="./run.bat" spawn="yes">
<arg line="${bea.dizin.win}"/>
<arg line="${bea.dizin.win}/startWebLogic.cmd"/>
</exec>
</target>


Run.bat, exec için bir sıçrama tahtasından ibarettir. Tek amacı dizin değiştirmek aslında, yoksa direk startWebLogic komutunu da işletebilirdik. Run.bat aşağıda gösteriliyor.

cd %1
start %2

Güzel. Artık tek kalan, herşeyi işletmek.

$ ant weblogic-baslat servis-bekle entegre-testleri-islet

No comments: