Thursday, January 10, 2013

How to change processor affinity in Windows and Linux

We have been playing multiple core processor systems for a long time. It is good to know that there are several cores available to run so many processes and threads in your system. The operating system is responsible how the processes are assigned to the cores. Usually you do not care how this process works. Actually modern operating system kernels are really successful to evenly distribute the load among the cores and can sometimes even migrate a thread or a process from one core to another if it is required. But sometimes you need to control or restrict the threads of a process to a subset of the cores. In Windows operating system you can easily restrict the threads to run on specific CPU's by using start command available since Windows XP.
Let's take a look at the start command line parameters:

s>start /?
Starts a separate window to run a specified program or command.

START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
      [/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
      [/NODE <NUMA node>] [/AFFINITY <hex affinity mask>] [/WAIT] [/B]
      [command/program] [parameters]

    "title"     Title to display in window title bar.
    path        Starting directory.
    B           Start application without creating a new window. The
                application has ^C handling ignored. Unless the application
                enables ^C processing, ^Break is the only way to interrupt
                the application.
    I           The new environment will be the original environment passed
                to the cmd.exe and not the current environment.
    MIN         Start window minimized.
    MAX         Start window maximized.
    SEPARATE    Start 16-bit Windows program in separate memory space.
    SHARED      Start 16-bit Windows program in shared memory space.
    LOW         Start application in the IDLE priority class.
    NORMAL      Start application in the NORMAL priority class.
    HIGH        Start application in the HIGH priority class.
    REALTIME    Start application in the REALTIME priority class.

    ABOVENORMAL Start application in the ABOVENORMAL priority class.
    BELOWNORMAL Start application in the BELOWNORMAL priority class.
    NODE        Specifies the preferred Non-Uniform Memory Architecture (NUMA)
                node as a decimal integer.
    AFFINITY    Specifies the processor affinity mask as a hexadecimal number.
                The process is restricted to running on these processors.

                The affinity mask is interpreted differently when /AFFINITY and
                /NODE are combined.  Specify the affinity mask as if the NUMA
                node's processor mask is right shifted to begin at bit zero.
                The process is restricted to running on those processors in
                common between the specified affinity mask and the NUMA node.
                If no processors are in common, the process is restricted to
                running on the specified NUMA node.
    WAIT        Start application and wait for it to terminate.
    command/program
                If it is an internal cmd command or a batch file then
                the command processor is run with the /K switch to cmd.exe.
                This means that the window will remain after the command
                has been run.

                If it is not an internal cmd command or batch file then
                it is a program and will run as either a windowed application

                or a console application.

    parameters  These are the parameters passed to the command/program.

NOTE: The SEPARATE and SHARED options are not supported on 64-bit platforms.

Specifying /NODE allows processes to be created in a way that leverages memory
locality on NUMA systems.  For example, two processes that communicate with
each other heavily through shared memory can be created to share the same
preferred NUMA node in order to minimize memory latencies.  They allocate
memory from the same NUMA node when possible, and they are free to run on
processors outside the specified node.

    start /NODE 1 application1.exe
    start /NODE 1 application2.exe

These two processes can be further constrained to run on specific processors
within the same NUMA node.  In the following example, application1 runs on the
low-order two processors of the node, while application2 runs on the next two
processors of the node.  This example assumes the specified node has at least
four logical processors.  Note that the node number can be changed to any valid
node number for that computer without having to change the affinity mask.

    start /NODE 1 /AFFINITY 0x3 application1.exe
    start /NODE 1 /AFFINITY 0xc application2.exe


If Command Extensions are enabled, external command invocation
through the command line or the START command changes as follows:

non-executable files may be invoked through their file association just

    by typing the name of the file as a command.  (e.g.  WORD.DOC would
    launch the application associated with the .DOC file extension).
    See the ASSOC and FTYPE commands for how to create these
    associations from within a command script.

When executing an application that is a 32-bit GUI application, CMD.EXE

    does not wait for the application to terminate before returning to
    the command prompt.  This new behavior does NOT occur if executing
    within a command script.

When executing a command line whose first token is the string "CMD "

    without an extension or path qualifier, then "CMD" is replaced with
    the value of the COMSPEC variable.  This prevents picking up CMD.EXE
    from the current directory.

When executing a command line whose first token does NOT contain an

    extension, then CMD.EXE uses the value of the PATHEXT
    environment variable to determine which extensions to look for
    and in what order.  The default value for the PATHEXT variable
    is:

        .COM;.EXE;.BAT;.CMD


    Notice the syntax is the same as the PATH variable, with

    semicolons separating the different elements.

When searching for an executable, if there is no match on any extension, then looks to see if the name matches a directory name.  If it does, the START command launches the Explorer on that path.  If done from the command line, it is the equivalent to doing a CD /D to that path.

The option affinity is the one we are interested in.  This option takes one parameter which instructs the process scheduler that the process threads run only on the selected subset of the cores. The parameter is an integer given in base 16. For 2-core hyper-thread cpu, operating systems senses 4 logical CPU's and let's denote them as CPU0, CPU1, CPU2 and CPU3. In the table given below, you can easily follow how the parameter controls which cores are used:

Parameter CPU3 CPU2 CPU1 CPU0
0x01 - - - +
0x02 - - + -
0x03 - - + +
0x04 - + - -
0x05 - + - +
0x06 - + + -
0x07 - + + +
0x08 + - - -
0x09 + - - +
0x0A + - + -
0x0B + - + +
0x0C + + - -
0x0D + + - +
0x0E + + + -
0x0F + + + +

where + means the corresponding CPU is used, and - means the corresponding CPU is NOT used in the scheduling. To verify that the start command with its options is working properly, i have written the following very simple java code:



package com.example.console;

public class TestCpuAffinity {
    public static void main(String[] args) {
    System.err.println("Number of available processor: "+Runtime.getRuntime().availableProcessors()); 
    }
}


The code simply prints the number of cores available out to the console. Here are the results:

start /affinity 0xF "running" /B java com.example.console.TestCpuAffinity
Number of available processors: 4

start /affinity 0xA "running" /B java com.example.console.TestCpuAffinity
Number of available processors: 2

start /affinity 0x1 "running" /B java com.example.console.TestCpuAffinity
Number of available processors: 1

start /affinity 0x2 "running" /B java com.example.console.TestCpuAffinity
Number of available processors: 1

start /affinity 0x3 "running" /B java com.example.console.TestCpuAffinity
Number of available processors: 2

It is easy to do the same thing in Linux with the help of taskset command which is basically use the same mask defined in Windows. The manual page of taskset is given below:


TASKSET(1)                    Linux User’s Manual                   TASKSET(1)

NAME
       taskset - retrieve or set a process’s CPU affinity

SYNOPSIS
       taskset [options] mask command [arg]...
       taskset [options] -p [mask] pid

DESCRIPTION
       taskset  is  used  to  set  or retrieve the CPU affinity of a running process given its PID or to launch a new COMMAND with a given CPU affinity.  CPU affinity is a scheduler property that "bonds" a process to a given set of CPUs on the system.  The Linux scheduler  will honor  the  given CPU affinity and the process will not run on any other CPUs.  Note that the Linux scheduler also supports natural CPU affinity: the scheduler attempts to keep processes on the same CPU as long as practical for performance reasons.  Therefore, forcing  a specific CPU affinity is useful only in certain applications.

       The  CPU  affinity  is represented as a bitmask, with the lowest order bit corresponding to the first logical CPU and the highest order bit corresponding to the last logical CPU.  Not all CPUs may exist on a given system but a mask may specify more CPUs than are present.
       A  retrieved  mask will reflect only the bits that correspond to CPUs physically on the system.  If an invalid mask is given (i.e., one that corresponds to no valid CPUs on the current system) an error is returned.  The masks are  typically  given  in  hexadecimal. For example,

       0x00000001
              is processor #0

       0x00000003
              is processors #0 and #1

       0xFFFFFFFF
              is all processors (#0 through #31)

       When taskset returns, it is guaranteed that the given program has been scheduled to a legal CPU.

OPTIONS
       -p, --pid
              operate on an existing PID and not launch a new task

       -c, --cpu-list
              specify  a  numerical  list  of  processors  instead of a bitmask.  The list may contain multiple items, separated by comma, and
              ranges.  For example, 0,5,7,9-11.

       -h, --help
              display usage information and exit

       -V, --version
              output version information and exit

USAGE
       The default behavior is to run a new command with a given affinity mask:
              taskset mask command [arguments]

       You can also retrieve the CPU affinity of an existing task:
              taskset -p pid

       Or set it:
              taskset -p mask pid

Here is the sample usage of taskset command on running firefox:

[root@server1 ~]# taskset -c 1 firefox &
[1] 1032
[root@server1 ~]# taskset -p 1032
pid 1032's current affinity mask: 2




Sunday, January 6, 2013

MD-2012-IV

Matematik dünyası dergisinin 2012-IV sayısı çıktı. Abone olmak için bağlantıyı takip edin. Yeni sayının içeriğine buradan bakabilirsiniz. MD-2012-IV sayısının giriş yazısını aşağıda alıntıladım:
Gün geçmez ki bir gazeteci ya da televizyoncu bana eğitimde neden bu halde olduğumuzu sormasın.
Söylenecek o kadar çok şey var ki hangi birini söyleyeceğimi şaşırırım.
Baktım yanlışlarla başa çıkamıyorum, yöntem değiştirdim, doğruları bulayım bari dedim.
 İnanır mısınız bir tane doğru bulamadım.
Her şeyi değiştirin ama eğitimimizin şu özelliğine ne olur dokunmayın diyebileceğim tek bir husus bile yok. 
Bunun ancak tek bir anlamı olabilir: Eğitim sistemimiz reformla filan düzenlenebilecek durumda değildir. Kökten değişmeli. Yönetmeliklerle filan yetinmeyip tüm eğitim anlayışımızı, felsefemizi, eğitime bakışımızı, eğitimle ilgili her şeyimizi sorgulamalı ve tepeden tırnağa değiştirmeliyiz. Kısacası eğitim sistemimizde reform değil devrim yapmalıyız. Başka türlü bu eğitim sistemi düzelmez.
Okul binalarına bir göz atın. Okul binaları okuldan çok bir hapishaneyi andırmıyor mu? Böyle okullarda doğru eğitim yapılabilir mi?  Böyle okullara öğrenciler koşa koşa, güle oynaya gidebilirler mi? Mümkün mü? 
Matematik Köyü'nü kurmadan önce izin için çırpınıp dururken Milli Eğitim Müdürlüğü'ne gittik. Bize iki tip okul binası gösterdiler. İki türden biri olmalıymış!
Daha neler! Müdürlükten nasıl kaçtığımı bilmiyorum. Şirince'deki ilköğretim okulu bildiğimiz standart okullardan, bir beton yığını. Bahçesi bile. Hemen yanında da eski bir Rum binasından devşirme bir meyhane vardır. Yüksek tavanlı, iki katlı taş bir bina. Olağanüstü güzel. Kocaman bahçesinde devasa çam ağaçları yükselir. Meğer bu meyhane Rumlar zamanında köyün okuluymuş. Mübadeleden sonra ilkokulu bozup meyhane yapmışlar. okul niyetine de bildiğimiz ucube binalardan birini yapmışlar!
Galiba eğitim sistemimizi değiştirmeden önce ar duygumuzu geliştirmeliyiz! 
Ama yuvalara ve kreşlere dikkat ettiniz mi, ne kadar sevimliler. Rengarenk, davetkar, iç açıcı, kucaklayıcı, güven verici. Çünkü okul öncesi eğitim zorunlu olmadığından onlara karışmıyorlar!
Ah! İşte çözüm! Çözümü bulduk. Karışma! Serbest bırak!
Popülizmin tuzağına düşüp halkımız en iyisini bilir demeyeyim de, belli ki yetkililerden daha iyisini biliyor. Çoğu şey gibi eğitim de rekabete açık olsun. Başarılı okulları, öğretmenleri, binaları ödüllendir. Müfettişe bile ihtiyacınız kalmaz! 
Şu bir gerçek ki devlet yapısı hantal. Belki de öyle olmalı, bilmiyorum. Oysa toplum, teknoloji ve bilim çok çabuk değişiyor artık. Eğitimin de bu değişime ayak uydurması lazım. Devletin hantal yapısı yüzünden eğitim değişime ve ihtiyaçlara ayak uyduramıyor. 
Bir gün bu düşünceyi savunabileceğim aklıma bile gelmezdi.    
Ama akıl ve mantık bunu gerektiriyor. Karşı koymanın anlamı yok.
Ali Nesin

Saturday, December 1, 2012

SEMBOL TABLOSU

C ya da C++'de geliştirdiğimiz uygulamalarda hata ayıklama yapmamız gerektiğinde, kodu GNU c derleyeyicisi ile -g seçeneği ile derlememiz gerekir. Aksi halde gdb ile uygulamada hata ayıklamak istediğimizde sembol tablosunu bulamadığına ilişkin uyarı verecektir:
[guru@godel ~]$ g++ -o lottery lottery.cpp -std=c++11
[guru@godel ~]$ gdb lottery 
GNU gdb (GDB) Fedora (7.4.50.20120120-42.fc17)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/guru/lottery...(no debugging symbols found)...done.
(gdb) quit
[guru@godel ~]$ g++ -g -o lottery lottery.cpp -std=c++11
[guru@godel ~]$ gdb lottery 
GNU gdb (GDB) Fedora (7.4.50.20120120-42.fc17)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/guru/lottery...done.

lottery.cpp: Sayısal loto için 6 adet [1,49] aralığında birbirinden farklı sıralı sayı üretir

#include <iostream>
#include <algorithm>
#include <random>
#include <list>

using namespace std;

int main(){
   random_device rd; 
   mt19937 gen(rd());
   uniform_int_distribution<uint32_t> dist(1,49);
   list<uint32_t> lst;
   while ( lst.size() < 6 ){
      uint32_t r;
      do {
        r= dist(gen);
      } while(find(lst.begin(),lst.end(),r)!=lst.end());
      lst.push_front(r);
   }   
   lst.sort();
   for (auto x : lst)
       cout <<  x << endl;
   return 0;
}

-g seçeneği ile derlendiğinde çalıştırılabilir dosyanın içinde sembol tablosu da yer alacaktır. Hata ayıklayıcı sembol tablosunu, kod ile bellek alanlarını eşleştirmek için kullanmaktadır. Ancak bunun bir yan etkisi bulunmaktadır. Sembol tablosu çalıştırılabilir dosyanın içinde yer aldığı için dosyanın boyu büyümektedir. İstenirse sembol tablosunu çalıştırılabilir dosyanın dışına ayrı bir dosyaya alınabilir. Bunun için strip ve objcopy komutlarından yararlanıyoruz.
[guru@godel ~]$ objcopy --only-keep-debug lottery lottery.debug
[guru@godel ~]$ strip --strip-debug --strip-unneeded lottery
[guru@godel ~]$ objcopy --add-gnu-debuglink=lottery.debug lottery
[guru@godel ~]$ ls -lh lottery*
-rwxrwxr-x. 1 student student 17K Dec  1 16:05 lottery
-rw-rw-r--. 1 student student 506 Dec  1 15:50 lottery.cpp
-rwxrwxr-x. 1 student student 77K Dec  1 16:04 lottery.debug
[guru@godel ~]$ gdb lottery
GNU gdb (GDB) Fedora (7.4.50.20120120-42.fc17)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/guru/lottery...Reading symbols from /home/guru/lottery.debug...done.
(gdb) list 1,10
1 #include <iostream>
2 #include <algorithm>
3 #include <random>
4 #include <list>
5
6 using namespace std;
7
8 int main(){
9   random_device rd;
10   mt19937 gen(rd());
(gdb) list 11,20
11   uniform_int_distribution<uint32_t> dist(1,49);
12   list<uint32_t> lst;
13   while ( lst.size() < 6 ){
14      uint32_t r;
15      do {
16        r= dist(gen);
17      } while(find(lst.begin(),lst.end(),r)!=lst.end()) ;
18      numbers.push_front(r);
19   }
20   lst.sort();
(gdb) break 13
Breakpoint 1 at 0x401019: file lottery.cpp, line 13.
(gdb) break 20
Breakpoint 2 at 0x4010d2: file lottery.cpp, line 20.
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000401019 in main() at lottery.cpp:13
2       breakpoint     keep y   0x00000000004010d2 in main() at lottery.cpp:20
(gdb) run
Starting program: /home/guru/lottery 

Breakpoint 1, main () at lottery.cpp:13
13   while ( lst.size() < 6 ){
(gdb) print lst
$1 = empty std::list
(gdb) cont
Continuing.

Breakpoint 2, main () at lottery.cpp:20
20   lst.sort();
(gdb) print lst
$2 = std::list = {[0] = 23, [1] = 42, [2] = 7, [3] = 22, [4] = 21, [5] = 36}
(gdb) cont
Continuing.
7
21
22
23
36
42
[Inferior 1 (process 2463) exited normally]
(gdb) quit


Solaris11'de NFS Paylaşımı Tanımlama ve Windows 7'den Erişim

ZFS, Sun Microsystems firmasında Jeff Bonwick ve Matthew Atrens'in başını çektiği bir ekip tarafından tarafından geliştirilmiş hem bir dosya hem de LVM (Logical Volume Management) sistemini içeren bir teknolojidir. Başlangıçta açık kaynak kodlu bir proje olarak Common Development and Distribution License modeli ile geliştirilen sistem artık Oracle firmasının ticari bir ürünüdür. Solaris 11 işletim sisteminin en önemli bileşenlerinden biri olarak öne çıkmaktadır. 

ZFS ile 278 sekizliği adreslemek mümkündür. Bu şimdilik teorik olarak ulaşılabilecek üst değeri ifade ediyor ve çok uzun süre ihtiyaçlarımızı karşılayacaktır. ZFS elbette bu kapasitenin ötesinde farklı yetenekler sunuyor. Bu yeteneklerden birkaç tanesi aşağıda sıralanmıştır:
  • Anlık yedek oluşturabilme, 
  • Kolay kurulum ve yönetim, 
  • Şifreleme, 
  • Sessiz onarım, 
  • Değişken blok boyutu tanımlayabilme, 
  • Little-endian/big-endian farklı sistemler arasında sorunsuz dosya sistemi aktarımı
Bu yazıda zfs üzerinde NFS tipinde bir dosya sisteminin nasıl yaratılacağı ve bu paylaşılan alana Windows 7'den nasıl erişilebileceği anlatılacaktır. İşleme shared isimli bir bölüm yaratarak başlıyoruz. Ardından bu bölüm nfs olarak tanımlanıyor ve paylaşıma açılıyor:

#zfs create rpool/shared
#zfs set share=name=shared,path=/rpool/shared,prot=nfs rpool/shared
name=shared,path=/rpool/shared,prot=nfs,public=true,sec=sys,rw=*
#zfs set sharenfs=on rpool/shared
#cat /etc/dfs/sharetab
/rpool/shared    shared    nfs     sec=sys,rw

Sistemin çalışabilmesi için NFS servisini açmak gerekir:
#svcadm enable svc:/network/nfs/server:default

Windows 7'ye Solaris 11'de paylaşıma açılan NFS bölümünü tanıtmak için öncelikle Windows'da NFS Client özelliğini açmak gerekir. Bunun için ilk olarak Control Panel'den Programs and Features seçilir:


Çıkan pencerede Turn Windows features on or off bağlantısı seçilir:


Çıkan diyalog kutusunda Services for NFS seçilir:


Windows yeniden başlatıldıktan sonra komut satırından mount komutu çalıştırılır: 

C:\Users\godel>showmount -e 192.168.1.3
Exports list on 192.168.1.3:
/rpool/shared                      All Machines

C:\Users\godel>mount -o mtype=hard 192.168.1.3:/rpool/shared z:
z: is now successfully connected to 192.168.1.3:/rpool/shared

The command completed successfully.


Monday, October 29, 2012

XMail E-POSTA SUNUCUSUNUN 64-Bit Windows MAKİNALARA KURULUMU

Kurumsal uygulamaların bir parçası olarak bazen test ortamlarında hafif-sıklet e-posta sunucusuna ihtiyaç duyarız. Bu amaçla XMail e-posta sunucusu kullanılabilinir. XMail açık kaynak kodlu bir projedir ve projenin sayfasına bu bağlantıdan erişebilirsiniz. Windows XP, Windows Server 2003/2008, Windows 7 makinalara kurulum yapılabilinir. Windows işletim sistemi için çalıştırılabilir dosyaları bu bağlantıdan  indirebilirsiniz. Ancak bu çalıştırılabilir dosyalar 32-bit Windows için oluşturulmuştur ve 64-bitlik Windows makinalar için Windows kayıtlarında aşağıdaki gibi bir düzenleme yapılması gerekir:

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\GNU] 
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\GNU\XMail]
MAIL_ROOT=d:\XMail
MAIL_CMD_LINE=

Kurulum ve temel ayarlar için aşağıdaki betiği kullanabilirsiniz:


@echo off
setlocal
REM  Note: Port used include 25 for SMTP, 110 for POP, 6017 for Admin services

set INSTALLDIR=%CD%
set MAIL_ADMIN=demoadmin
set DOMAIN=example.com

if not defined DRV          set DRV=D:
if not defined HOSTNAME     set HOSTNAME=%COMPUTERNAME%
if not defined DOMAIN       set DOMAIN=example.com
if not defined MAILROOT     set MAILROOT=%DRV%\XMail
if not defined MAILROOT_REG set MAILROOT_REG=%DRV%\\XMail

if exist %MAILROOT% (
  echo Stopping XMail Service
  net stop xmail
)

unzip -oq %INSTALLDIR%\XMail.zip -d %MAILROOT%
REM
REM Generate and install a registry entries from a .reg file for XMail
REM
echo Generating and setting Xmail registry entries

if not defined XMAIL_REG_FILE set XMAIL_REG_FILE=XMail_gen.reg

echo Windows Registry Editor Version 5.00 > %XMAIL_REG_FILE%
echo. >> %XMAIL_REG_FILE%
echo [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\GNU] >> %XMAIL_REG_FILE%
echo [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\GNU\XMail] >> %XMAIL_REG_FILE%
echo "MAIL_ROOT"="%MAILROOT_REG%" >> %XMAIL_REG_FILE%
echo "MAIL_CMD_LINE"="" >> %XMAIL_REG_FILE%

regedit /s %XMAIL_REG_FILE%
del/q %XMAIL_REG_FILE%
REM
REM Create the (1) domains.tab (2) smtpreply.tab (3) server.tab (4) aliasdomain.tab in the mail root directory
REM
REM 1. domains.tab
echo Creating Xmail domains.tab file
echo "%HOSTNAME%.%DOMAIN%" > %MAILROOT%\domains.tab

REM 2. Create empty smtprelay.tab
echo Creating Xmail smtpreplay.tab file
echo. > %MAILROOT%\smtprelay.tab

REM 3. server.tab
echo Creating Xmail server.tab file

echo # > %MAILROOT%\server.tab
echo # Server configuration file >> %MAILROOT%\server.tab
echo # Note : remember to use _REAL_ TABs and double quotes to format this file >> %MAILROOT%\server.tab
echo # >> %MAILROOT%\server.tab
echo "RootDomain" "%HOSTNAME%.%DOMAIN%" >> %MAILROOT%\server.tab
echo "SmtpServerDomain" "%HOSTNAME%.%DOMAIN%" >> %MAILROOT%\server.tab
echo "POP3Domain" "%HOSTNAME%.%DOMAIN%" >> %MAILROOT%\server.tab
echo "HeloDomain" "%HOSTNAME%.%DOMAIN%" >> %MAILROOT%\server.tab
echo "PostMaster" "%MAIL_ADMIN%@%HOSTNAME%.%DOMAIN%" >> %MAILROOT%\server.tab
echo "ErrorsAdmin" "%MAIL_ADMIN%@%HOSTNAME%.%DOMAIN%" >> %MAILROOT%\server.tab

REM
REM Add other settings
REM
echo "RemoveSpoolErrors" "0" >> %MAILROOT%\server.tab
echo "MaxMTAOps" "16" >> %MAILROOT%\server.tab
echo "ReceivedHdrType" "0" >> %MAILROOT%\server.tab
echo "FetchHdrTags" "+X-Deliver-To,+Received,To,Cc" >> %MAILROOT%\server.tab
echo "DefaultSmtpPerms" "MRVZ" >> %MAILROOT%\server.tab
echo. >> %MAILROOT%\server.tab

REM 4. aliasdomain.tab
echo Creating Xmail aliasdomain.tab file

echo "server1.example.com" "%HOSTNAME%.%DOMAIN%" > %MAILROOT%\aliasdomain.tab

REM 5. Create ctrlaccounts.tab with administrator username
echo "admin" "120009060a080054" > %MAILROOT%\ctrlaccounts.tab

echo Mail server: %HOSTNAME%.%DOMAIN%
echo Creating XMail User accounts

mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%

set USRLIST=user1 user2 sking jcooper wfaulk jstein istone mtwain jlondon cdickens ltolstoy fkafka szweig mmitch jausten achrist rsteven cdoyle wshake sfitzger
set USRPWD=120009060a080054

for %%i in (%MAIL_ADMIN% %USRLIST%) do (
  echo  Creating user: %%i
  echo "%HOSTNAME%.%DOMAIN%" "%%i" "%USRPWD%" 1 "%%i" "U" >> %MAILROOT%\mailusers.tab
  mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i
  echo "ReceiveEnable" "1" > %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\user.tab
  echo "PopEnable" "1" >> %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\user.tab
  mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\mailbox
  mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\Maildir
  mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\Maildir\cur
  mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\Maildir\new
  mkdir %MAILROOT%\domains\%HOSTNAME%.%DOMAIN%\%%i\Maildir\tmp
)

echo Installing XMail Server as a service

%MAILROOT%\bin\XMail --install-auto
echo Starting XMail Server service
net start xmail

echo XMAil Server service started.
endlocal

Kurulum tamamlandığında servisler listesinde XMail adlı bir servis görülecektir.
İstenildiğinde bu servis net stop xmail komutu ile durdurulabilinir.

Wednesday, October 17, 2012

MD-2012-III

Matematik dünyası dergisinin 2012-III sayısı çıktı. Abone olmak için bağlantıyı takip edin. Yeni sayının içeriğine buradan bakabilirsiniz. MD-2012-III sayısının giriş yazısını aşağıda alıntıladım:

George Bernard Shaw’un meşhur sözüdür: “Pek az kişi yılda iki üç kez düşünür. Ben ise haftada bir iki kez düşünerek dünya çapında bir üne kavuştum!” Aaa ne güzel, biz de haftada birkaç kez düşünelim o zaman... diyesi geliyor insanın.
Çok çabalayıp da anlatamadığım zaman, çok çaresiz kaldığımda, bazen kendimi
tutamayıp öğrencilere “düşünün” diyorum!
Sanki düşünmeyi ben çok iyi biliyormuşumu geçtim, sanki biri bana düşün dese,
ne yapacağımı biliyormuşum gibi...
Birine kolunu kaldır deseniz, o kişi eğer isterse kolunu kaldırır. Kolu yoksa bile kolunu kaldırması için ne yapması gerektiğini bilir ve kolunu kaldırmaya çalışabilir. Koş dersin koşar, yürü dersin yürür, dur dersin durur. En azından ne yapması gerektiğini bilir. Ama “düşün” denildiğinde kişinin ne yapması gerekiyor? Düşünmek ne kadar iradeyle ilgili?
Düşün dediğim öğrenci,
- Düşünüyorum hocam! dese - ki diyor bazen - ne cevap vereceğim?
- Hayır, düşünmüyorsun! Öyle mi düşünülür!
- Ya nasıl düşünülür?
- Bak işte böyle düşünülür...
Keşke bu senaryonun devamını getirebilsem. Zaten devamını getirebilsem kitabını yazardım. Okuyanlar da böylece sayemde düşünmeyi öğrenirlerdi!
Nasıl düşünüleceğini bilmesem de düşünmek için neler gerektiğini aşağı yukarı biliyorum.
Düşünmek için her şeyden önce kavramlara ihtiyaç vardır, tabii bir de bu kavramlar arasındaki ilişkilere. Kavram olmadan düşünülecek şey de olmaz zaten.
Matematikte kavramlar ve aralarındaki ilişkiler simgelerle ifade edilir. Simgeler de düşünceyi kaydetmeye yarar. Böylece hafızanın yükü önemli miktarda azalır ve düşüncede daha derine inilir, derine inilmese de daha ileri gidilir. Düşünceyi kaydetmek, yani yazıya geçirmek, bir dereyi geçmek için su yatağına yerleştirilen taşlar gibidir, o taşlara basıp daha ileri gidilir. Hatta geri dönüp silgiyle taşları siler, daha sağlam taşlarla yepyeni bir güzergâh belirleyebiliriz.
Matematik dışındaki alanlarda simge dünyası o kadar gelişmemiştir. Gene de bildiğimiz harflerle düşünce kaydedilebilir. Formüllerin ifade gücünün yanına yaklaşamasa da bildiğimiz düzyazı da düşünceyi simgeyle kaydetmeye yarar.
Lise öğrencisiyken bir deneme yazacaktım. Her hafta yaptığımız bir şeydi de neme yazmak. O zamanlar tahrir denirdi. Konuyu unuttum şimdi ama “eğitim herkese lazım” filan gibi doğruluğu bariz olan oldukça sıkıcı bir konuydu. Geceli gündüzlü üç hafta uğraştım. Sonunu bağlayamıyor, istediğim sonuca bir türlü ula şa mı yordum, hep bir yerlerde bir eksiklik beliriyordu. Üç hafta sonunda bir şimşek çaktı beynimde, yanılıyormuşum meğer! Savunduğum tez yanlışmış! 
Yazmak doğru düşünmeye yetmeyebilir. Ama yazmadan da doğru düşünülemez.
Ali Nesin

Wednesday, October 10, 2012

APACHE TOMCAT 6'DA GÜNLÜKLERİN SYSLOG SERVİSİNE YÖNLENDİRİLMESİ

Apache Tomcat 6'da günlükler $CATALINA_HOME/logs dizininde saklanmaktadır. Günlüğün yapılandırılması ise $CATALINA_HOME/conf/logging.properties dosyası üzerinden gerçeklenmektedir. Apache Tomcat günlük için tomcat-juli.jar paketini kullanmaktadır. İstenirse günlük oluşturmak için log4j kütüphanesi de kullanılabilinir. log4j kütüphanesi kullanılarak, günlükler veritabanı, syslog gibi farklı hedeflerde saklanabilir. Hem veritabanı hem de syslog servisi istemci-sunucu mimarisinde çalıştığı için günlükler merkezileştirilebilir. Böylelikle, çoklu tomcat sunucusunun olduğu bir yapıda, sunucuların yönetimi kolaylaşır, izlenebilirliği de iyileşir. Bunun yanında log4j ile ERROR yada üzeri seviyedeki günlüklerin e-posta olarak sistem ya da uygulama yöneticisine göndermek mümkün olabilir.

log4j ile günlükleri syslog servisinde toplamak için aşağıdaki adımları izlemek gerekir:

1. İlk olarak $CATALINA_BASE/lib dizininde log4j kütüphanesinin yapılandırma dosyasını (log4j.properties)  oluşturuyoruz:

log4j.rootLogger=INFO, CATALINA

# Define all the appenders
log4j.appender.CATALINA=org.apache.log4j.net.SyslogAppender
log4j.appender.CATALINA.layout= org.apache.log4j.PatternLayout
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.CATALINA.SyslogHost=127.0.0.1
log4j.appender.CATALINA.Facility=local0
log4j.appender.CATALINA.threshold=DEBUG

log4j.appender.LOCALHOST=org.apache.log4j.net.SyslogAppender
log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayout
log4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.LOCALHOST.SyslogHost=127.0.0.1
log4j.appender.LOCALHOST.Facility=local0
log4j.appender.LOCALHOST.threshold=DEBUG

log4j.appender.MANAGER=org.apache.log4j.net.SyslogAppender
log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.MANAGER.SyslogHost=127.0.0.1
log4j.appender.MANAGER.Facility=local0
log4j.appender.MANAGER.threshold=DEBUG

log4j.appender.HOST-MANAGER=org.apache.log4j.net.SyslogAppender
log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.HOST-MANAGER.SyslogHost=127.0.0.1
log4j.appender.HOST-MANAGER.Facility=local0
log4j.appender.HOST-MANAGER.threshold=DEBUG

log4j.appender.CONSOLE=org.apache.log4j.net.SyslogAppender
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.CONSOLE.SyslogHost=127.0.0.1
log4j.appender.CONSOLE.Facility=local0
log4j.appender.CONSOLE.threshold=DEBUG

# Configure which loggers log to which appenders
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO, LOCALHOST
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]=INFO, MANAGER
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager]=INFO, HOST-MANAGER

2. log4j kütüphanesinin güncel sürümünü (log4j-1.2.9.jar) projenin sayfasından indirip $CATALINA_BASE/lib dizinine kopyalıyoruz.

3. Apache tomcat'in proje sayfasında "extras" bölümünden tomcat-juli.jar ve tomcat-juli-adapters.jar dosyalarını indiriyoruz. tomcat-juli.jar dosyasını $CATALINA_BASE/bin dizinine tomcat-juli-adapters.jar dosyasını ise $CATALINA_BASE/lib dizinine kopyalıyoruz. Bu dosyalar adı geçen dizinlerde mevcuttur, dolayısı ile üzerinlerine yazmanız gerekecektir.

4. syslog servisinin 2,3,4,5 çalışma seviyelerinde açık olduğundan emin olun:



[root@station1 lib]# chkconfig --list syslog
syslog  0:off   1:off   2:on    3:on    4:on    5:on    6:off

5. syslog servisinin yapılandırması için iki dosya vardır. 
  • /etc/syslog.conf dosyasına aşağıdaki satırı ekliyoruz:
    local0.*   /var/log/tomcat/messages.log
  • /etc/sysconfig/syslog dosyasında SYSLOGD tanımının yapıldığı satırı aşağıdaki gibi düzenliyoruz:

          SYSLOGD_OPTIONS="-r -m 0"

6. Bu değişiklikleri yaptıktan sonra syslog servisini yeniden başlatıyoruz:

[root@station1 lib]# service syslog restart
Shutting down kernel logger:        [  OK  ]
Shutting down system logger:        [  OK  ]
Starting system logger:             [  OK  ]
Starting kernel logger:             [  OK  ]

7. Son olarak tomcat servisini başlatabiliriz.

Günlükleri veritabanında tutmak için MySQL sunucusunda tomcat_logs adında bir veritabanı yaratıyoruz:


mysql> create database tomcat_logs;
Query OK, 1 row affected (0.02 sec)


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
| test               | 
| tomcat_logs        | 
+--------------------+
3 rows in set (0.00 sec)

Günlüklerin saklanacağı tabloyu ise aşağıdaki create table ifadesi ile yaratıyoruz:

mysql> CREATE TABLE LOGS
    ->    (USER_ID VARCHAR(20) NOT NULL,
    ->     DATED   VARCHAR(40) NOT NULL,
    ->     LOGGER  VARCHAR(50) NOT NULL,
    ->     LEVEL   VARCHAR(10) NOT NULL,
    ->     MESSAGE VARCHAR(1000) NOT NULL
    ->    );
Query OK, 0 rows affected (0.01 sec)

Yukarıdaki sıralanan adımlardan ilkinde verilen log4j.properties dosyasında net.SyslogAppender yerine jdbc.JDBCAppender yazıyoruz:

log4j.rootLogger=WARN, DB

log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
log4j.appender.DB.URL=jdbc:mysql://localhost:3306/tomcat_logs
log4j.appender.DB.driver=com.mysql.jdbc.Driver
log4j.appender.DB.user=tomcat
log4j.appender.DB.password=tomcat
log4j.appender.DB.sql=INSERT INTO LOGS VALUES('%x','%d','%C','%p','%m')

Son adım olarak MySQL Jdbc sürücüsünü $CATALINA_BASE/lib dizinine kopyalamak gerekir.