<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/css" href="http://www.tuxad.de/blog/styles/feed.css"?>
<rss version="2.0" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>tuxad blog</title>
<atom:link href="http://localhost/please/edit/me/rss.xml" rel="self" type="application/rss+xml" />
<link>http://localhost/please/edit/me</link>
<description>news and more</description>
<dc:language>de-de</dc:language>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:date>2011-12-31T21:54:36+01:00</dc:date>
<admin:generatorAgent rdf:resource="http://nanoblogger.sourceforge.net" />
<item>
<link>http://localhost/please/edit/me/archives/2011/12/31/djb_daemontools_with_upstart_or_systemd/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/12/31/djb_daemontools_with_upstart_or_systemd/index.html</guid>
<title>DJB daemontools with upstart or systemd</title>
<dc:date>2011-12-31T18:37:32+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>shell</dc:subject>
<description>
<![CDATA[
<p>
The daemontools softwaresuite are widely used for supervising
processes. Unlike the common way of launching daemons or other
processes in background, writing their PID to a file and watch
for a process (actually <em>any</em> process) with this PID by
crappy tools like monit the daemontools offer a direct
supervision of processes with an immediate restart on a crash.
</p>
<p>
Using the traditional <strong>SysV-init</strong> it is most easy
to launch the daemontools processes:
</p>
<pre>
$ grep -B1 SV /etc/inittab
si::sysinit:/etc/rc.d/rc.sysinit
SV:12345:respawn:/command/svscanboot3
</pre>
<p>
<em>
Note: svscanboot3 is a binary replacement of svscanboot. It
is part of
<a href="http://www.tuxad.com/download-ngtx.html">ngtx</a>.
</em>
</p>
<p>
SysV-init process ID 1 is very small, approx. 700 KB RSS. With
many manual optimizations it is possible to start a system /
server as fast as with upstart or systemd.
</p>

<p>
<strong>Upstart</strong> offers event-based booting. A time ago
it was dealed as a successor to SysV-init. To start daemontools
as a upstart-service you must create a config file:
</p>
<pre>
$ cat /etc/init/daemontools.conf 
description     "DJB daemontools"
start on filesystem
stop on runlevel [06]
respawn
exec /command/svscanboot3
</pre>

<p>
Some latest Linux (actual "linux-only") distros switch to
<strong>systemd</strong>. Systemd also offers event-based and
parallel booting with linux-only features like cgroups or
fanotify. Its features are very nice but its PID 1 RSS is 13 MB
which is very big compared to SysV-init. For systemd you must
also create a config file (and a symlink):
</p>
<pre>
$ ls -l /etc/systemd/system/multi-user.target.wants/ \
  daemontools.service
lrwxrwxrwx. 1 root root 39 21. Dez 08:34
  /etc/systemd/system/multi-user.target.wants/ \
  daemontools.service -> /lib/systemd/system/ \
  daemontools.service

$ ls -l /lib/systemd/system/daemontools.service
-rw-r--r--. 1 root root 151 21. Dez 08:33
  /lib/systemd/system/daemontools.service

$ cat /lib/systemd/system/daemontools.service
[Unit]
Description=DJB daemontools
After=sysinit.target

[Service]
ExecStart=/command/svscanboot3
Restart=always

[Install]
WantedBy=multi-user.target
</pre>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/12/03/mysql_slow_query_log_filter/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/12/03/mysql_slow_query_log_filter/index.html</guid>
<title>MySQL Slow Query Log Filter</title>
<dc:date>2011-12-03T20:53:11+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>mysql, shell</dc:subject>
<description>
<![CDATA[
<p>
Filtering all queries of <em>one </em> user out of a MySQL Slow
Query Log is a common task. Maatkit is a toolkit for analyzing
log files and more. Here is an example run to filter all
queries of user123 of a 707 MB big slow-query-log:
</p>
<pre>
$ time mk-query-digest --filter \
 '($event-&gt;{user} || "") =~ m/user123/' \
 --print --no-report log-slow-queries.log &gt;1
log-slow-queries.log:  15% 02:49 remain
log-slow-queries.log:  29% 02:26 remain
log-slow-queries.log:  44% 01:51 remain
log-slow-queries.log:  59% 01:20 remain
log-slow-queries.log:  76% 00:45 remain
log-slow-queries.log:  90% 00:18 remain

real    3m20.097s
user    0m16.616s
sys     3m2.592s
</pre>
<p>
Well, 707 MB in more than 3 minutes? Simple filtering can also
be done with awk, try it:
</p>
<pre>
$ time awk \
'/^# Time: /{t=1;s=$0;p=0}'\
'!/^# /{t=0}/^# User@Host: /{p=0}'\
'/^# User@Host: user123/{p=1};'\
'{if(p){if(t){print s;t=0;}print$0}}' \
 &lt;log-slow-queries.log &gt;2

real    0m58.844s
user    0m2.501s
sys     0m3.268s
</pre>
<p>
Nice speed, but awk is a symlink to mawk, try gawk:
</p>
<pre>
$ time gawk \
'/^# Time: /{t=1;s=$0;p=0}'\
'!/^# /{t=0}/^# User@Host: /{p=0}'\
'/^# User@Host: user123/{p=1};'\
'{if(p){if(t){print s;t=0;}print$0}}' \
 &lt;log-slow-queries.log &gt;2

real    3m30.287s
user    0m29.934s
sys     2m58.800s
</pre>
<p>
Ooops, but didn't we already know, how
<a href="http://www.tuxad.de/blog/archives/2010/09/17/gnu_grep_speed_comparison_fixed_strings/index.html">slow</a>
GNU-software can be? Try a different server:
</p>
<pre>
$ time gawk \
'/^# Time: /{t=1;s=$0;p=0}'\
'!/^# /{t=0}/^# User@Host: /{p=0}'\
'/^# User@Host: user123/{p=1};'\
'{if(p){if(t){print s;t=0;}print$0}}' \
 &lt;log-slow-queries.log &gt;2

real    2m4.899s
user    2m2.240s
sys     0m1.890s
</pre>
<p>
This server runs more fast, but it lacks mawk, is virtual and
it runs like the first server only 32-bit-linux. Try gawk and
mawk on 64-bit-linux (same physical host):
</p>
<pre>
$ time gawk \
'/^# Time: /{t=1;s=$0;p=0}'\
'!/^# /{t=0}/^# User@Host: /{p=0}'\
'/^# User@Host: user123/{p=1};'\
'{if(p){if(t){print s;t=0;}print$0}}' \
 &lt;log-slow-queries.log &gt;2

real    1m49.348s
user    1m40.242s
sys     0m1.528s

$ time mawk \
'/^# Time: /{t=1;s=$0;p=0}'\
'!/^# /{t=0}/^# User@Host: /{p=0}'\
'/^# User@Host: user123/{p=1};'\
'{if(p){if(t){print s;t=0;}print$0}}' \
 &lt;log-slow-queries.log &gt;3

real    0m13.115s
user    0m1.000s
sys     0m2.392s
</pre>
<p>
Conclusions:
<ul>
<li>simple filter can be done faster with awk than with maatkit</li>
<li>mawk does this filtering faster than gawk</li>
<li>mawk and gawk run faster on 64-bit-linux</li>
</ul>
</p>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/11/30/indirekte_variablenzuweisung_mit_eval/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/11/30/indirekte_variablenzuweisung_mit_eval/index.html</guid>
<title>Indirekte Variablenzuweisung mit &quot;eval&quot;</title>
<dc:date>2011-11-30T22:15:57+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>shell</dc:subject>
<description>
<![CDATA[
<p>
Das Shell-Builtin "eval" bewertet Ausdr&uuml;cke bzw. f&uuml;hrt
Befehle aus. Einfaches Beispiel:
</p>
<pre>
$ unset A
$ echo $A

$ eval A=1
$ echo $A
1
</pre>

<p>
Da die Shell vor Ausf&uuml;hren von eval wie auch bei jeder anderen
Kommandozeile erst die &uuml;blichen Ersetzungen (Variablen,
Commands etc.) macht, kann man auch folgendes machen:
</p>
<pre>
$ B=A
$ eval $B=2
$ echo $A
2
</pre>

<p>
Und wenn man ganz verr&uuml;ckte Sachen machen will, wie
beispielsweise in einem Script mehrere Variablen in einer
Schleife auf die gleiche Weise zu ver&auml;ndern, dann sieht das
so aus:
</p>
<pre>
$ U=a
$ for i in U;do eval $i=\"\$$i X\";done;echo $U
a X
$ for i in U;do eval $i=\"\$$i X\";done;echo $U
a X X
$ for i in U;do eval $i=\"\$$i X\";done;echo $U
a X X X
</pre>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/09/19/call_to_undefined_function_gzopen/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/09/19/call_to_undefined_function_gzopen/index.html</guid>
<title>Call to undefined function gzopen()</title>
<dc:date>2011-09-19T22:07:58+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>c, php, developer</dc:subject>
<description>
<![CDATA[
<p>
Auf 32-Bit-Systemen und aktiviertem Largefilesupport in der
Zlib kann es beispielsweise bei Verwendung von PHP zu "Fehlern"
kommen. Dieser Fehler erschien bei dem Versuch, Magento auf
einem 32-Bit-System mit LFS-Support in Zlib und PHP zu
installieren:
</p>

<pre>
Fatal error: Call to undefined function gzopen() in \
  /html/install/downloader/lib/Mage/Archive/Gz.php on line 60
</pre>

<p>
Das ist aber anscheinend ein allgemeines Problem und durchaus
aktuell, wie dieser Thread zeigt:
<a href="https://bugs.launchpad.net/ubuntu/+source/php5/+bug/432291">https://bugs.launchpad.net/ubuntu/+source/php5/+bug/432291</a>
</p>

<p>
Der Fehler tauchte bei dieser Distro auf, nachdem der
Debian-Patch "019-z_off_t_as_long.patch" deaktiviert wurde.
Dabei trat dann der Nebeneffekt auf, dass nur noch gzopen64()
definiert war. Der Ansatz war ja l&ouml;blich, den Patch nicht
ungepr&uuml;ft von dieser Distribution zu &uuml;bernehmen (ya
remember "OpenSSL-Debakel" und "16 Bit Entropie"?), doch leider
wurde dieser Patch dann doch wieder aktiviert, anscheinend ohne
sich &uuml;ber die Hintergr&uuml;nde im Klaren zu sein. Zu dem
Patch findet man folgende Infos:
</p>

<pre>
* Add 019-z_off_t_as_long.patch, including local headers for
zlib, forcing off_t = long for gzip file functions, however
disable it for now, as we'll only need it if we reenable LFS
(closes: #208608)
</pre>

<p>
Der Patch bewirkt die Installation von zwei
Zlib-Header-Dateien. Dabei wird der Zlib-interne off_t-Typ
als "long" definiert. Die Header-Dateien selbst stammen
von der Zlib 1.2.1.1 und &uuml;berschreiben ihre Br&uuml;der,
die systemweit installiert sind und vermutlich von einer
neueren Zlib stammen. So eine Vorgehensweise "unsauber" zu
nennen, w&auml;re ein Kompliment, aber zum Thema QM kann nur
noch einmal auf OpenSSL und die 16 Bit breite Entropie verwiesen
werden.
</p>

<p>
Doch wie l&ouml;st man das Problem? Als Maintainer kann man
bugs.php.net bem&uuml;hen oder es &uuml;ber einen Kontakt
kl&auml;ren. F&uuml;r die Homebrew-Variante schauen wir uns mal
einen Teil der <b>aktuellen</b> Zlib-Header-Dateien an:
</p>

<pre>
$ grep -B1 -A21 "define gzopen" /usr/include/zlib.h 
#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && \
_LFS64_LARGEFILE-0
#  define gzopen gzopen64
#  define gzseek gzseek64
#  define gztell gztell64
#  define gzoffset gzoffset64
#  define adler32_combine adler32_combine64
#  define crc32_combine crc32_combine64
#  ifdef _LARGEFILE64_SOURCE
     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const \
char *));
     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, \
int));
     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong,
\
z_off_t));
     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, \
z_off_t));
#  endif
#else
   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char \
*));
   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, \
z_off_t));
   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, \
z_off_t));
#endif
</pre>

<p>
Da wir die Zlib intern in PHP nutzen wollen und dabei auf
keinen Fall gzopen64(), sondern statt dessen gzopen() haben
wollen, definieren wir zum &Uuml;bersetzen von PHP ganz einfach
ZLIB_INTERNAL, beispielsweise mit der gcc-Option
"-DZLIB_INTERNAL=1". Wenn man das an die CFLAGS anh&auml;ngt,
bevor man ./configure aufruft, dann wird PHP damit
&uuml;bersetzt und beim Include der Zlib-Header-Dateien werden
die "internen" Namen gzopen() etc. deklariert.
</p>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/05/29/prozessoren_cores_und_hyperthreading/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/05/29/prozessoren_cores_und_hyperthreading/index.html</guid>
<title>Prozessoren, Cores und Hyperthreading</title>
<dc:date>2011-05-29T12:02:39+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>shell</dc:subject>
<description>
<![CDATA[
<p>
Wie erkennt man auf einem System, wie viele Prozessoren und
Cores man hat, und ob Hyperthreading zur Verf&uuml;gung
steht? Fangen wir direkt mit einem Beispiel an:
</p>

<pre>
s1# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 15
model name      : Intel(R) Xeon(R) CPU            5110  @
1.60GHz
stepping        : 6
cpu MHz         : 1595.984
cache size      : 4096 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 10
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse
sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts
pni monitor ds_cpl vmx tm2 ssse3 cx16 xtpr dca lahf_lm
bogomips        : 3194.84
clflush size    : 64
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 15
model name      : Intel(R) Xeon(R) CPU            5110  @
1.60GHz
stepping        : 6
cpu MHz         : 1595.984
cache size      : 4096 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 10
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse
sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts
pni monitor ds_cpl vmx tm2 ssse3 cx16 xtpr dca lahf_lm
bogomips        : 3192.06
clflush size    : 64
power management:
</pre>

<p>
Hier sieht man das "ht"-Flag, aber der Xeon 5110 hat
<em>kein </em> Hyperthreading. Zum Vergleich mal ein anderes
System:
</p>

<pre>
s2# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 15
model           : 4
model name      : Intel(R) Pentium(R) 4 CPU 3.00GHz
stepping        : 1
cpu MHz         : 2995.049
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse
sse2 ss ht tm pbe constant_tsc pebs bts sync_rdtsc pni
monitor ds_cpl cid xtpr
bogomips        : 5994.31
clflush size    : 64

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 15
model           : 4
model name      : Intel(R) Pentium(R) 4 CPU 3.00GHz
stepping        : 1
cpu MHz         : 2995.049
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep
mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse
sse2 ss ht tm pbe constant_tsc pebs bts sync_rdtsc pni
monitor ds_cpl cid xtpr
bogomips        : 5990.26
clflush size    : 64
</pre>

<p>
Hier steht auch "ht", diesmal hat die CPU aber
Hyperthreading. Das Flag wurde wegen einer gewissen
Abw&auml;rtskompatibilit&auml;t gesetzt. Grund waren unter anderem
Betriebssysteme, die pro Sockel lizenziert wurden. H&auml;tte man
das mit dem Pentium4 eingef&uuml;hrte ht-Flag weggelassen, h&auml;tten
diese "OS" den virtuellen zweiten Kern nicht genutzt / nutzen
k&ouml;nnen.
</p>

<p>
Wichtig sind hierbei die Angaben zu den Siblings (so etwas wie
gleichartige Kinder einer "Vater-CPU"), der Physical
ID, der Anzahl der Cores und die Nummerierung der Core IDs.
Mit grep wird das dann deutlicher:
</p>

<pre>
s1# egrep \
'processor|physical id|siblings|core id|cpu cores|^$' \
/proc/cpuinfo
processor       : 0
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2

processor       : 1
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
</pre>

<p>
Wir haben 2 CPU cores mit ID 0 und 1 auf 1 physischen
Prozessor bei 2 Siblings. die 2 Siblings beziehen sich hier
auf die 2 Cores pro physischer CPU.
</p>

<pre>
s2# egrep \
'processor|physical id|siblings|core id|cpu cores|^$' \
/proc/cpuinfo
processor       : 0
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1

processor       : 1
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 1
</pre>

<p>
Hier haben wir 2 (virtuelle) Prozessoren mit 1 physical ID, 1
Core ID und 1 CPU core, aber mit 2 Siblings. Es handelt sich
somit um eine einzelne Singlecore-CPU. Die zwei virtuellen
Prozessoren kommen durch die 2 Siblings zustande: Diese CPU
hat also Hyperthreading.
Pro Core hat man hier also "cpu cores" geteilt durch
"siblings" = 2 / 1 = 2 virtuelle HT-Prozessoren. 
</p>

<p>
Schauen wir uns einen dritten Server an:
</p>

<pre>
s3# egrep processor /proc/cpuinfo
processor       : 0
processor       : 1
processor       : 2
processor       : 3
processor       : 4
processor       : 5
processor       : 6
processor       : 7
processor       : 8
processor       : 9
processor       : 10
processor       : 11
processor       : 12
processor       : 13
processor       : 14
processor       : 15
root@coabmaster:~ > egrep 'core id' /proc/cpuinfo|sort -u
core id         : 0
core id         : 1
core id         : 2
core id         : 3
</pre>

<p>
Wir haben 16 virtuelle/nicht-virtuelle Prozessoren und 4
Kerne pro physischem Prozessor.
</p>

<pre>
s3# egrep \
'siblings|cpu cores|physical id' /proc/cpuinfo \
|sort -u
cpu cores       : 4
physical id     : 0
physical id     : 1
siblings        : 8
</pre>

<p>
Hier sieht man noch mal die Anzahl der Kerne, die IDs der
physischen Prozessoren und 8 Siblings (8 Siblings durch 4
Cores = 2 virtuelle HTT-CPUs). Das macht also 2 Quadcore-CPUs
mit Hyperthreading = 16 virtuelle Prozessoren.
</p>

<p>
Mit einem kleinen Script l&auml;sst sich das bequem
auswerten:
</p>

<pre>
s4# cat cpucores.sh 
#!/bin/bash

for f in \
  'model name' processor 'physical id' 'cpu cores' siblings
do
  grep "$f" /proc/cpuinfo|tail -n 1
done \
|sed 's,.*: ,,' \
|{
  read M
  read P;let P=P+1
  read I;[ -z "$I" ] && I=0;let I=I+1
  read C;[ -z "$C" ] && C=1
  read S;[ -z "$S" ] && S=1
  echo $M: $I CPUs with $C cores and $S siblings\
    $([ $S -gt $C ] && echo " (hyperthreading)") \
    '("'$P virtual processors'")'
}
s4# ./cpucores.sh 
Intel(R) Xeon(R) CPU E5520 @ 2.27GHz: 2 CPUs with 4 cores and
8 siblings (hyperthreading) ("16 virtual processors")
</pre>

<p>
Da das Script so kurz ist, kann man es auch als
<a href="/blog/files/cpucores.txt">Einzeiler</a> verwenden.
Zum Schluss noch ein paar Beispielausgaben des Scripts:
</p>

<pre>
Intel(R) Xeon(R) CPU E5520 @ 2.27GHz: 2 CPUs with 4 cores and
8 siblings (hyperthreading) ("16 virtual processors")
Intel(R) Xeon(R) CPU X5650 @ 2.67GHz: 2 CPUs with 6 cores and
12 siblings (hyperthreading) ("24 virtual processors")
Intel(R) Pentium(R) 4 CPU 3.00GHz: 1 CPUs with 1 cores and 2
siblings (hyperthreading) ("2 virtual processors")
Intel(R) Core(TM)2 CPU 4400 @ 2.00GHz: 1 CPUs with 2 cores
and 2 siblings ("2 virtual processors")
Intel(R) Xeon(R) CPU 3060 @ 2.40GHz: 1 CPUs with 2 cores and
2 siblings ("2 virtual processors")
Intel(R) Xeon(R) CPU 5110 @ 1.60GHz: 4 CPUs with 2 cores and
2 siblings ("4 virtual processors")
Intel(R) Xeon(R) CPU E5310 @ 1.60GHz: 1 CPUs with 4 cores and
4 siblings ("4 virtual processors")
Intel(R) Xeon(R) CPU E5520 @ 2.27GHz: 2 CPUs with 4 cores and
8 siblings (hyperthreading) ("8 virtual processors")
Intel(R) Xeon(R) CPU E5620 @ 2.40GHz: 2 CPUs with 4 cores and
8 siblings (hyperthreading) ("8 virtual processors")
</pre>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/05/26/base64_f_uumlr_smtp-auth_und_http_basic_authentication/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/05/26/base64_f_uumlr_smtp-auth_und_http_basic_authentication/index.html</guid>
<title>base64 f&uuml;r SMTP-Auth und HTTP Basic authentication</title>
<dc:date>2011-05-26T23:15:58+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>http, smtp, python</dc:subject>
<description>
<![CDATA[
<p>
Sowohl bei SMTP-Auth als auch bei HTTP Basic access
authentication kommt base64-Kodierung zur Anwendung. Dieser
Blogpost zeigt dazu Beispiele und die Verwendung von Python
zur base64-Kodierung.
</p>

<h4>SMTP-Auth</h4>

<p>
Hier der Ausschnitt eines SMTP-Dialogs mit
PLAIN-Authentication:
</p>

<pre>
$ telnet mail.domain.de 25
Trying 128.64.32.16...
Connected to mail.domain.de.
Escape character is '^]'.
220 mail.domain.de ESMTP Postfix
EHLO franksbox.localdomain
250-mail.domain.de
250-PIPELINING
250-SIZE 35840000
250-ETRN
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
AUTH PLAIN bWFpbDEAbWFpbDEAc2FzbHB3
235 2.0.0 Authentication successful
</pre>

<p>
Nach RFC4616 besteht die Zeichenkette f&uuml;r den "PLAIN
SASL Mechanism" aus der "authorization identity", einem
NUL-Zeichen, der "authentication identity", einem weiteren
NUL-Zeichen und dem Passwort. Normalerweise sind
"authorization identity" und "authentication identity" gleich
(die Postfachkennung). Mit Python kann man die Zeichenkette
mit base64 kodieren und auch zur&uuml;ck dekodieren:
</p>

<pre>
$ python -c "import base64;print \
> base64.encodestring('mail1\0mail1\0saslpw')"
bWFpbDEAbWFpbDEAc2FzbHB3

$ python -c "import base64;print \
> base64.decodestring('bWFpbDEAbWFpbDEAc2FzbHB3')" \
> |tr \\000 /
mail1/mail1/saslpw

</pre>


<h4>HTTP basic access authentication</h4>

<p>
Auch hier kommt base64-Kodierung zum Einsatz. Die
Zeichenkette zur Authorisierung besteht nach RFC1945 aus
Name, einem Doppelpunkt und dem Passwort. Ein HTTP-Request
sieht damit beispielsweise so aus:
</p>

<pre>
GET /index.html HTTP/1.1
Host: www.domain.de
Authorization: Basic dzE6aHRwdw==

</pre>

<p>
Auch hier nutzen wir wieder Python, um manuell zu en- und
dekodieren.
</p>

<pre>
$ python -c \
> "import base64;print base64.encodestring('w1:htpw')"
dzE6aHRwdw==

$ python -c \
> "import base64;print base64.decodestring('dzE6aHRwdw==')"
w1:htpw

</pre>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/05/25/apache_hat_keine_freie_semaphore/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/05/25/apache_hat_keine_freie_semaphore/index.html</guid>
<title>Apache hat keine freie Semaphore</title>
<dc:date>2011-05-25T00:35:23+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>apache</dc:subject>
<description>
<![CDATA[
<p>
Das ist auch ein kleiner Klassiker, darum sollen dieses
Problem und seine L&ouml;sung auch nicht unerw&auml;hnt
bleiben. Es kann vorkommen, dass in einem Apache Error-Log
die folgende Zeile auftaucht:
</p>

<pre>
No space left on device (errno: 28)
</pre>

<p>
Eine Pr&uuml;fung ergibt dann oft, dass auf den (HD-) Devices
sehr wohl noch "Space" vorhanden ist. In den Logzeilen findet
sich dann auch ein Eintrag wie:
</p>

<pre>
could not create private SSLMutex semaphore
</pre>

<p>
Das liefert dann auch den entscheidenden Hinweis darauf, dass
Apache keinen neuen Semaphor (ein klassisches Werkzeug
f&uuml;r IPC) erzeugen kann. Die man-page zu semget()
f&uuml;hrt auch diese Fehlerm&ouml;glichkeit auf:
</p>

<pre>
# man semget|grep -A4 ENOSPC
   ENOSPC A semaphore set has to be  created  but  the
          system limit for the maximum number of sema-
          phore sets (SEMMNI), or the system wide max-
          imum number of semaphores (SEMMNS), would be
          exceeded.
</pre>

<p>
Das sind bei vielen Hosts oft noch die zu niedrigen
Standardwerte:
</p>

<pre>
# cat /proc/sys/kernel/sem 
250     32000   32      128
</pre>

<p>
Die man-page proc(5) liefert uns folgende Infos dazu:
</p>

<pre>
   /proc/sys/kernel/sem (since Linux 2.4)
          This file contains 4 numbers defining limits for
          System  V  IPC semaphores.  These fields are, in
          order:

          SEMMSL  The  maximum  semaphores  per semaphore
                  set.

          SEMMNS  A  system-wide  limit  on  the number of
                  semaphores in all semaphore sets.

          SEMOPM  The maximum number  of  operations that
                  may be specified in a semop(2) call.

          SEMMNI  A  system-wide limit on the maximum num-
                  ber of semaphore identifiers.
</pre>

<p>
Eine Z&auml;hlung der Semaphore des Users "www" liefert das:
</p>

<pre>
# ipcs -s|grep -c www
128
</pre>

<p>
Jetzt stoppen wir Apache, l&ouml;schen alle "vergessenen"
Semaphore, setzen die Werte h&ouml;her und starten Apache
wieder:
</p>

<pre>
# ipcs -s|grep www|cut -d\  -f2|xargs -r -n 1 ipcrm -s
# echo '500 64000 32 1024' >/proc/sys/kernel/sem 
</pre>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/05/21/logging_in_der_konsole/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/05/21/logging_in_der_konsole/index.html</guid>
<title>Logging in der Konsole</title>
<dc:date>2011-05-21T09:37:23+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>shell</dc:subject>
<description>
<![CDATA[
<p>
Dieser Post zeigt ein paar M&ouml;glichkeiten, wie man
Befehle oder Ausgaben in einer Shell-Session mitschneiden
kann.
</p>

<p>
Der Befehl script erzeugt eine neue Shell, bei der alle Ein-
und Ausgaben in eine Datei typescript geschrieben werden.
Nach Verlassen der durch script gestarteten Shell kann man
sich dieses Logfile anschauen. Allerdings ist dort jedes
einzelne Zeichen aufgezeichnet, einschliesslich aller
Steuerzeichen f&uuml;r Farben, f&uuml;r Zeilen Editierung
(Backspace, Tab, Return etc). Wie man mittels vi dieses Log
von Steuerzeichen befreit, w&uuml;rde diesen Beitrag
sprengen.
</p>

<p>
Als Alternative kann man sich auch nur die Textausgabe von
Programmen in ein Logfile packen. Hier ein Beispiel:
</p>

<pre>
$ avscan -a . 2>&1 |tee -a log.avscan
</pre>

<p>
Wenn man ein Logging mit Timestamp der einzelnen Zeilen
braucht, kann man so etwas machen:
</p>

<pre>
$ /opt/drweb/drweb -al . 2>&1 |tai64n |tee -a log.drweb
@400000004c5bbe8b1d775b9c Dr.Web (R) Scanner for Linux
@400000004c5bbe8b1e3010c4 Copyright (c) Igor Daniloff,
</pre>

<p>
Das Tool tai64n geh&ouml;rt zu der Softwaresuite
<a href="http://cr.yp.to/daemontools.html">daemontools von Dan Bernstein</a>.
Hier f&uuml;gt tai64n am Beginn jeder Zeile einen Timestamp
@40000... ein. Lesen/konvertieren kann man das mit
tai64nlocal, was den tai64n-Timestamp in lokale und human
readable Zeit konvertiert:
</p>

<pre>
$ tai64nlocal &lt;log.drweb |tail -1
2010-08-06 09:43:03.225062500 2009_02_12-ftp.log.gz - Ok
$ 
</pre>

<p>
Man kann sich den "Live-Stream" auch direkt bei der
Ausgabe wieder konvertiert anzeigen lassen:
</p>

<pre>
$ /opt/drweb/drweb -al . 2>&1 |tai64n \
  |tee -a log.drweb |tai64nlocal
2010-08-06 09:47:52.433362500 Dr.Web (R) Scanner for Linux
2010-08-06 09:47:52.433364500 Copyright (c) Igor Daniloff,
</pre>

<p>
Wenn man mit sehr viel Daten bei der Ausgabe rechnet und
vielleicht nur den letzten Teil haben m&ouml;chte, dann kann
man so eine Zeile nutzen:
</p>

<pre>
$ /opt/drweb/drweb -al . 2>&1 |tee /dev/stderr \
  |multilog t s10000 n20 ./logdir
</pre>

<p>
Diese Zeile zeigt die Programmausgabe kontinuierlich an und
schreibt bis 20 maximal 10 KB gro&szlig;e Logdateien in das
Verzeichnis logdir. Das Tool multilog aus den daemontools hat
ein eingebautes "logrotate". Auf diese Weise kann man die
Menge der Logdaten begrenzen.
</p>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/05/20/access_log-statistiken_mit_awk/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/05/20/access_log-statistiken_mit_awk/index.html</guid>
<title>access_log-Statistiken mit awk</title>
<dc:date>2011-05-20T08:00:18+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>shell, apache</dc:subject>
<description>
<![CDATA[
<p>
Heute gibt's nur kleine Einzeiler. Ein Klassiker zum Anzeigen
der IP-Adressen eines Apache access_log, letzte 1000 Zugriffe
und sortiert nach H&auml;ufigkeit der Zugriffe:
</p>

<pre>
tail -n 1000 access_log | awk \
'{f[$1]++}END{for(g in f)print f[g]" "g}' \
| sort -n | tail -n 5
</pre>

<p>
M&ouml;chte man nach der angefragten Datei sortieren, muss
man '$1' durch '$7' ersetzen, f&uuml;r Sortierung nach Return
Code '$9'.
</p>

<pre>
tail -n 1000 access_log | awk \
'$9=="404"{f[$7" "$11]++}END{for(g in f)print f[g]" "g}' \
| sort -n | tail -n 5
</pre>

<p>
Das sortiert die Zeilen mit 404 Return Code ("File Not
Found") und gibt dabei die angeforderte Datei und den Referer
an.
</p>

<pre>
tail -n 1000 access_log | awk \
'$9~/30./{f[$7" "$11]++}END{for(g in f)print f[g]" "g}' \
| sort -n | tail -n 5
</pre>

<p>
Statt 404 werden hier alle 30x Redirects sortiert.
</p>]]>
</description>
</item>
<item>
<link>http://localhost/please/edit/me/archives/2011/05/19/interaktionen_mit_expect/index.html</link>
<guid isPermaLink="true">http://localhost/please/edit/me/archives/2011/05/19/interaktionen_mit_expect/index.html</guid>
<title>Interaktionen mit expect</title>
<dc:date>2011-05-19T17:44:08+01:00</dc:date>
<dc:creator>Frank W. Bergmann</dc:creator>
<dc:subject>shell</dc:subject>
<description>
<![CDATA[
<p>
Auch wenn die "gro&szlig;en" Zeiten von Tcl/Tk ("Tickel-Tikay")
vorbei sind, es gibt immer noch einige Leute, die die
Scriptscprache und das Toolkit nutzen. Es ist stabil und gut
dokumentiert. Ein aus dem Tcl-Umfeld entstandenes Programm
ist expect, mit dem man Interaktionen bzw. Dialoge mit
anderen Programmen oder auch Serverdiensten realisieren kann.
</p>

<p>
Die man-page zu expect erkl&auml;rt die Grundlagen. Hier ist
ein Beispiel f&uuml;r die Verwendung von expect aus einem
bash-Script heraus:
</p>

<pre>
> cat check_easyraid.sh 
#!/bin/bash

CMD=$1
[ "$CMD" ] || {
  echo "usage: echo PASSWD | $0 easyraidcommand ip-address"
  exit 1
}
IP=$2
[ "$IP" ] || exit 2
ulimit -t 4
read -t 1 PASS

cat <<EOF |expect -|egrep 'Disk State:|State :|s status is'
match_max 65536
spawn telnet $IP
expect "name:"
send "admin\n"
expect "passwd:"
send "$PASS\n"
expect "ACSCLI"
send "$CMD\n"
#interact -nobuffer -re "Disk State:"
expect "ACSCLI"
#send_user "output: $expect_out(buffer)"
send "quit\n"
close
EOF
</pre>

<p>
Das Script baut eine telnet-Session zu einem easyRAID-SAN auf
und schickt Befehle zum Testen ab. Man kann mit expect auch
ftp-Sessions oder andere Interaktionen aus Scripts heraus
einfach handhaben. Das Beispiel ist ein Mix aus bash und
expect, aber man kann mit dem passenden Shebang
nat&uuml;rlich auch "reine" expect-Scripts schreiben.
</p>]]>
</description>
</item>
</channel>
</rss>

