czwartek, czerwca 25, 2009

Workaround na wieszające się serwery Della

Wygląda na to, że serwery Della z 8-mioma rdzeniami Intel Xeon przegrzewają się pod Linuksem. Teoretycznie Xeony mają Thermal Circuit Control, który przy nadmiernym wzroście temperatury powinien spowalniać procesor, ale pod Linuksem nie widać jego działania, widać za to, że serwer wiesza się sprzętowo. Workaround to unikanie niepotrzebnych migracji procesów między rdzeniami, co przy ciągłym (wielodniowym) obciążeniu ~5% załatwia problem:
echo 1 > /sys/devices/system/cpu/sched_mc_power_savings.

piątek, czerwca 19, 2009

Monitoring na sms-a

Kupujemy modem GSM, podłączamy go do linuksowego serwera, stawiamy na serwerze bramkę mail-sms, a potem już tylko:
HOSTNAME=`hostname`
USER=`whoami`
SMTP="10.10.1.25"

function sendmail {
(
sleep 3
echo "HELO $HOSTNAME"
sleep 1
echo "mail from: monitoring@email.com"
sleep 1
echo "rcpt to: smsgw@email.com"
sleep 1
echo "data"
sleep 1
echo "From: monitoring.$USER@email.com"
sleep 1
echo "To: smsgw@email.com"
sleep 1
echo "Subject: $1"
sleep 1
echo ""
sleep 1
echo "$2"
sleep 1
echo "."
sleep 1
echo "quit"
sleep 1
) | telnet $SMTP 25
}

sendmail "$1" "$2"

# ./sendsms "+48602201122" "Brak dzialajacego procesu A dla systemu B"

czwartek, czerwca 18, 2009

Jakim cudem Java ME na komórkach może być szybka?

Procesory ARM miewają natywną obsługę bajtkodu Javy - Jazelle.

Automatyczne testowanie aplikacji webowych

"Przechodzimy" aplikację w Firefoksie wyposażonym w plugin "Live HTTP headers" i kopiujemy dane wysyłane formularzem. Dane te wkleimy potem do linii poleceń wgeta.



Przykładowy skrypt:
WP_URL="http://10.10.1.20:8080/app/AppServlet"
COOKIE="cookie.dat"
WGET_CMD="wget --timeout=15 --keep-session-cookies --save-cookies=$COOKIE --quiet $WP_URL -O -"
> $COOKIE

RUNNING=$(ps uax | grep -c nazwa_skryptu.sh)
[[ $RUNNING -gt 3 ]] && echo "Poprzednie wywolanie skryptu wisi" && exit 1

RES=$($WGET_CMD --post-data="user=jan.kowalski&password=lubieTpsa&action=login" | grep -c "Zalogowany: ")
echo "Test logowania. Wynik: $RES"
RES=$($WGET_CMD --load-cookies=$COOKIE --post-data="action=create-process&action_params=...&state=" | grep -c "Nowy proces")
echo "Zaladowanie procesu. Wynik: $RES"
RES=$($WGET_CMD --load-cookies=$COOKIE --post-data="action=next&action_params=..." | grep -c "Dane zapisano")
echo "Wynik procesu poprawny?: $RES"
RES=$($WGET_CMD --load-cookies=$COOKIE --post-data="action=save-and-close&action_params=..." | grep -c "Zakonczono proces")
echo "Zamkniecie procesu. Wynik: $RES"
RES=$($WGET_CMD --load-cookies=$COOKIE --post-data="action=logout" | grep -c "Wylogowano uzytkownika")
echo "Wylogowanie. Wynik: $RES"

wtorek, czerwca 16, 2009

HostDeny z logów Apache'a

#!/bin/sh
RATE_LIMIT="100"
HOSTS_DENY=".htaccess"
LOG="/home/apache_wp/apache_wp/logs/access_log_443"
DT=$(date +%d/%b/%Y:%k:%M)
PERIODIC_LOG="periodic.log"

cat $LOG | grep "$DT" | grep "SomeServletUrl" | cut -d" " -f1 > $PERIODIC_LOG
echo "### Generated at $DT ###">> $HOSTS_DENY

for ip in $(cat $PERIODIC_LOG | sort -u); do
cnt=$(cat $PERIODIC_LOG | grep -c "$ip");
[[ $cnt -gt $RATE_LIMIT ]] || continue;
echo >> $HOSTS_DENY;
echo "# $ip generated $cnt requests above rate limit $RATE_LIMIT" >> $HOSTS_DENY;
echo "Deny from $ip" >> $HOSTS_DENY;
done;

niedziela, czerwca 14, 2009

OpenESB nightly build

Sun schował je tutaj:
http://download.java.net/jbi/binaries/open-esb-full-install/v2.1/nightly/latest/
http://download.java.net/jbi/binaries/glassfishesb/v2.1/nightly/latest/

[2009-10-11] http://download.java.net/jbi/binaries/installers/single-component/v2.1/nightly/

sobota, czerwca 13, 2009

Upgrade Fedory 10.9x do finalnej 11

W /etc/yum.repos.d wyłączamy fedora-rawhide.repo (Enabled=0), włączamy fedora.repo i fedora-updates.repo oraz wewnątrz tych plików zmieniamy $releasever na 11 i odpalamy yum upgrade.

piątek, czerwca 12, 2009

LicensedCpus.c

Program dedykowany wszystkim dyrektorom IT, którzy nie wiedzą, że software licencjonowany na 2 CPU można uruchamiać na serwerze z 4 CPU.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <string.h>

int get_num_cpus() {
int cnt = 0;
char *line = NULL;
size_t len = 0;
FILE *fp = fopen("/proc/stat", "r");
if (fp!=NULL) {
while (getline(&line, &len, fp)!=-1) {
if (line!=NULL && strstr(line, "cpu")!=NULL)
cnt++;
}
if (line)
free(line);
fclose(fp);
cnt--;
}
return cnt;
}

int main(int argc, char** argv) {
static cpu_set_t mask;
int user_mask, i=0, max, m=0;

if (argc<3) {
fprintf(stdout, "Usage: %s cpu_mask(int) command(full_path)\n",argv[0]);
exit(0);
}

user_mask = atoi(argv[1]);
max = 1 << (get_num_cpus()-1);
CPU_ZERO(&mask);
for (i=0; i<max; i++) {
if ( (user_mask & (1 << i)) == (1 << i)) {
CPU_SET(i, &mask);
m |= (1<<i);
}
}

if (sched_setaffinity(0, sizeof(mask), &mask)==0) {
fprintf(stdout, "Running %s with mask %d, cpus=%d\n", argv[2], m, max);
return execv(argv[2], argv+2);
}
else {
fprintf(stderr, "Cannot set cpu mask: %s. Effective mask was %d\n", strerror(errno), m);
exit(1);
}
}

sobota, czerwca 06, 2009

Jak GCC dzieli przez 100

mov edx, 600
mov eax, 51EB851Fh ; EAX = 32/100 * 2^32
mul edx
mov eax,edx
shr eax,5 ; EAX = EAX/32

środa, czerwca 03, 2009

Naprawiona biblioteka libIntroscopeRedHatStats.so

Idea poprawki polega na stworzeniu proxy na bibliotekę i własnej implementacji metody getAggregateCPUUsage.

Pozostałe funkcje JNI można prawdopodobnie zaimplementować następująco:

getProcessCPUUsage -> getrusage()
getTotalClockTicks -> clock()
isThreadCpuTimeEnabled -> defined RUSAGE_THREAD
getThreadCpuTime -> getrusage(RUSAGE_THREAD, &usage)

Update: Przepisałem całą bibliotekę, gdyby ktoś chciał binarkę prośba o kontakt.

Memory leak in Wily Introscope

Wygląda na to, że agent Introscope ma wycieki pamięci w natywnym kodzie:
[tomcat@swa158 ~]$ jrcmd 0 print_memusage
18130:
[JRockit] memtrace is collecting data...
[JRockit] *** 0th memory utilization report
(all numbers are in kbytes)
Total mapped ;;;;;;;1192600
; Total in-use ;;;;;;1182252
;; executable ;;;;; 12260
;;; java code ;;;; 7680; 62.6%
;;;; used ;;; 5763; 75.0%
;; shared modules (exec+ro+rw) ;;;;; 4540
;; guards ;;;;; 1056
;; readonly ;;;;; 68
;; rw-memory ;;;;;1177604
;;; Java-heap ;;;; 393216; 33.4%
;;; Stacks ;;;; 22871; 1.9%
;;; Native-memory ;;;; 761516; 64.7%
;;;; java-heap-overhead ;;; 12342
;;;; codegen memory ;;; 904
;;;; classes ;;; 29696; 3.9%
;;;;; method bytecode ;; 2927
;;;;; method structs ;; 3278 (#69939)
;;;;; constantpool ;; 11117
;;;;; classblock ;; 1488
;;;;; class ;; 3060 (#8698)
;;;;; other classdata ;; 4942
;;;;; overhead ;; 280
;;;; threads ;;; 107; 0.0%
;;;; malloc:ed memory ;;; 24265; 3.2%
;;;;; codeinfo ;; 1047
;;;;; codeinfotrees ;; 438
;;;;; exceptiontables ;; 591
;;;;; metainfo/livemaptable ;; 9324
;;;;; codeblock structs ;; 3
;;;;; constants ;; 6
;;;;; livemap global tables ;; 2091
;;;;; callprof cache ;; 0
;;;;; paraminfo ;; 88 (#1284)
;;;;; strings ;; 4991 (#92449)
;;;;; strings(jstring) ;; 0
;;;;; typegraph ;; 1593
;;;;; interface implementor list ;; 48
;;;;; thread contexts ;; 81
;;;;; jar/zip memory ;; 5451
;;;;; native handle memory ;; 39
;;;; unaccounted for memory ;;; 694309; 91.2%;28.61
---------------------!!!

16612:
[JRockit] memtrace is collecting data...
[JRockit] *** 0th memory utilization report
(all numbers are in kbytes)
Total mapped ;;;;;;;1192932
; Total in-use ;;;;;;1181960
;; executable ;;;;; 12004
;;; java code ;;;; 7424; 61.8%
;;;; used ;;; 5796; 78.1%
;; shared modules (exec+ro+rw) ;;;;; 4540
;; guards ;;;;; 1068
;; readonly ;;;;; 68
;; rw-memory ;;;;;1177312
;;; Java-heap ;;;; 393216; 33.4%
;;; Stacks ;;;; 23003; 2.0%
;;; Native-memory ;;;; 761092; 64.6%
;;;; java-heap-overhead ;;; 12342
;;;; codegen memory ;;; 592
;;;; classes ;;; 28928; 3.8%
;;;;; method bytecode ;; 2911
;;;;; method structs ;; 3256 (#69475)
;;;;; constantpool ;; 10845
;;;;; classblock ;; 1441
;;;;; class ;; 2938 (#8350)
;;;;; other classdata ;; 4923
;;;;; overhead ;; 61
;;;; threads ;;; 109; 0.0%
;;;; malloc:ed memory ;;; 24479; 3.2%
;;;;; codeinfo ;; 1019
;;;;; codeinfotrees ;; 420
;;;;; exceptiontables ;; 585
;;;;; metainfo/livemaptable ;; 9489
;;;;; codeblock structs ;; 3
;;;;; constants ;; 7
;;;;; livemap global tables ;; 2183
;;;;; callprof cache ;; 0
;;;;; paraminfo ;; 89 (#1288)
;;;;; strings ;; 4997 (#92452)
;;;;; strings(jstring) ;; 0
;;;;; typegraph ;; 1527
;;;;; interface implementor list ;; 47
;;;;; thread contexts ;; 82
;;;;; jar/zip memory ;; 5451
;;;;; native handle memory ;; 41
;;;; unaccounted for memory ;;; 694751; 91.3%;28.38
---------------------!!!

[tomcat@swa158 ~]$
Tomcaty są skonfigurowane z -Xmx384M a pamięć wirtualna (VSZ) dla procesu po dwóch tygodniach wynosi 1192MB, RSS 900MB. Czyli o 500-800MB za dużo. Sama diagnostyka JRockita pokazuje unaccounted for memory 91.3%. Ta sama aplikacja chodząca bez Wily’ego zachowuje się poprawnie. Średnio na dzień wycieka około 50MB pamięci.
W rezultacie po pewnym czasie na produkcji wchodzimy w swapa (co już Wily pokazuje jako wydłużenie się requestów). Jedyne rozwiązanie to cotygodniowy restart tomcatów.

Wyciek mamy w natywnym kodzie. Znajdźmy jakieś natywne biblioteczki:
tomcat@swa175:~/tomcatDiag1/wily> find . -name *.so
./ext/libIntroscopeAIX4PSeries32Stats.so
./ext/libIntroscopeSolarisSparc64Stats.so
./ext/libIntroscopeRedHatStats.so
./ext/libIntroscopeHpuxParisc32Stats.so
./ext/libIntroscopeSolarisSparc32Stats.so
./ext/libIntroscopeSolarisAmd64Stats.so
./ext/libIntroscopeAIX52PSeries64Stats.so
./ext/libIntroscopeAIX53PSeries64Stats.so
./ext/libIntroscopeSolarisAmd32Stats.so
./ext/libIntroscopeHpuxItaniumStats.so
./ext/libIntroscopeAIX5PSeries32Stats.so
./ext/libIntroscopeAIX4PSeries64Stats.so

Zobaczmy jaki kod Javy odwołuje się do libIntroscopeRedHatStats.so:
tomcat@swa175:~/tomcatDiag1/wily> nm ./ext/libIntroscopeRedHatStats.so | grep Java
000015e2 T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getAggregateCPUUsage
0000158e T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getParentProcessID
000011c6 T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getProcessCPUUsage
0000153a T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getProcessID
00001524 T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getProtocolVersion
000017a0 T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getThreadCpuTime
0000148a T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_getTotalClockTicks
0000152e T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_init
00001796 T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_isThreadCpuTimeEnabled
00001534 T Java_com_wily_introscope_agent_platform_linux_LinuxPlatformStatisticsBackEnd_term

Zdekompilujmy JAD-em LinuxPlatformStatisticsBackEnd.class i poszukajmy podejrzanych metod ze słowem kluczowym native:
private native long[] getAggregateCPUUsage(String s)
throws PlaformStatUnavailableException;

Założę się, że char* wyjęte ze Stringa javowego nie jest zwalniane.

Podłączamy IBM JDK z parametrem -Xcheck:jni:all i widzimy:

JVMJNCK071W JNI warning: Memory at 0x080C22A0 acquired by GetStringUTFChars was not released before returning from native. This is probably a memory leak.
JVMJNCK078W Warning detected in com/wily/introscope/agent/platform/linux/LinuxPlatformStatisticsBackEnd.getAggregateCPUUsage(Ljava/lang/String;)[J

czyli Wily faktycznie ma wycieki pamięci. Shame on you CA!

Summary: One of Wily native libraries has improper interactions with Java VM via JNI - it doesn't free memory used for accessing Java strings. I have rewritten the library - sources and binary .so file are avalilable here (archive is protected with password).